You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
8.**Confirm** — `ls -la /Applications | grep -i mypa` and report success, reminding the user to (re)launch it from Applications or Spotlight.
35
+
8.**Clean up the build output** — once it's copied into `/Applications`, `dist/` is spent: `rm -rf dist`. Skipping this leaves a second, fully valid `mypa.app` bundle sitting in the repo (`dist/<arch-dir>/mypa.app`), which Spotlight indexes just like the installed one — searching "mypa" then shows two results, and launching the wrong one runs an unregistered, unquarantined copy outside `/Applications`. `dist/` is gitignored build output, entirely regenerated by the next `npm run pack`, so deleting it loses nothing.
36
+
37
+
9.**Confirm** — `ls -la /Applications | grep -i mypa` and report success, reminding the user to (re)launch it from Applications or Spotlight.
36
38
37
39
## Notes
38
40
39
41
- This is `npm run pack`, not `npm run dist` — no dmg/zip, no code signing, just the fastest path from source to a runnable local `.app`. If the user wants an actual distributable installer, use `npm run dist` instead.
40
42
-`electron-builder`'s packaging step rebuilds native dependencies (`better-sqlite3`) for the correct Electron ABI automatically — no separate `npm run postinstall` needed unless a native dependency itself changed.
41
43
- Never touches `~/.mypa/config.json` or `~/.mypa/data.db` — only the app bundle in `/Applications` is replaced, so the user's config and data survive the reinstall.
44
+
- Always finish with `dist/` removed (step 8) — don't leave it behind "just in case." It's regenerated on the next run, and leaving it is what causes the duplicate-Spotlight-result problem this skill should not reintroduce.
42
45
- Auto-update can't be exercised on a build installed this way: `--dir` mode never writes `Contents/Resources/app-update.yml` (electron-builder only writes it when building the mac zip/dmg target). "Check for Updates" on an unpack-installed app shows a friendly "not installed from a signed release" toast rather than checking anything — that's expected, not a bug.
Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@ A local-first personal assistant for developers, built as a macOS/Linux/Windows
16
16
-**Owner identity** — set your name and per-surface handles (GitHub, Slack, Jira, Linear, Notion) so the assistant addresses you as "you" rather than by handle; auto-fills from connected MCP servers with one click
17
17
-**Usage dashboard** — detailed token usage and estimated cost breakdown by feature, model, and time period; powered by data the Claude Agent SDK already reports
18
18
-**MCP integration** — connect to any MCP server (local stdio process) from a built-in catalog or custom config; auto-import from an existing Claude Code config
19
-
-**OAuth integrations** — Notion PKCE and Linear PKCE for enriching routines with live data; GitHub connects via a personal access token instead of OAuth, since org OAuth-app access-control policies can block a device-flow connection
19
+
-**OAuth integrations** — Notion PKCE and Linear PKCE for enriching routines with live data; GitHub connects via a personal access token instead of OAuth, since org OAuth-app access-control policies can block a device-flow connection; Outlook (Microsoft 365 email + calendar) connects via a device-code sign-in that the MCP server manages end-to-end, including token refresh
Copy file name to clipboardExpand all lines: docs-dev/code-authoring.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -46,7 +46,7 @@ interface RepoLink {
46
46
id:string
47
47
localPath:string// absolute path to an existing git checkout
48
48
githubRepo?:string// "owner/name", derived from `git remote get-url origin`
49
-
jiraProjectKeys:string[] // e.g. ["PROJ"]
49
+
jiraProjectKeys:string[] // e.g. ["PROJ"] — auto-derived from git history, not user-entered
50
50
defaultBaseBranch:string// derived from origin/HEAD
51
51
authoringEnabled:boolean// opt-in per repo; defaults to false for discovered repos
52
52
source?:'discovered'|'manual'
@@ -55,7 +55,7 @@ interface RepoLink {
55
55
}
56
56
```
57
57
58
-
Stored in `AppConfig.repos` (config.json), not the DB — registration is a config mutation, mirroring how MCP servers are configured. `RepoLink`s are **auto-discovered**, not hand-registered: the user configures one or more parent folders (`AppConfig.codeRoots`) in Settings, and `repos.ts``rescanRepos()` walks each for git checkouts, deriving `githubRepo`/`defaultBaseBranch` and filtering to the configured GitHub-org scope. New discoveries default `authoringEnabled: false` — authoring (mypa opening a real PR against the checkout) is an explicit per-repo opt-in, toggled in the Settings "Repos" section (`ReposSection` in `Settings.tsx`). mypa **never clones a repo itself** — the scanner only reads (`.git` presence, `git remote get-url origin`, `git symbolic-ref .../HEAD`). A `source: 'manual'` link may still exist from before auto-discovery shipped; the scanner never edits or removes those.
58
+
Stored in `AppConfig.repos` (config.json), not the DB — registration is a config mutation, mirroring how MCP servers are configured. `RepoLink`s are **auto-discovered**, not hand-registered: the user configures one or more parent folders (`AppConfig.codeRoots`) in Settings, and `repos.ts` `rescanRepos()` walks each for git checkouts, deriving `githubRepo`/`defaultBaseBranch`/`jiraProjectKeys` and filtering to the configured GitHub-org scope. `jiraProjectKeys` is inferred, not typed in by the user — `deriveJiraProjectKeys` scans recent commit subjects/bodies and local branch names for `KEY-123`-style references and keeps any key seen more than once, since a one-off stray mention shouldn't route a whole repo. New discoveries default `authoringEnabled: false` — authoring (mypa opening a real PR against the checkout) is an explicit per-repo opt-in, toggled in the Settings "Repos" section (`ReposSection` in `Settings.tsx`). mypa **never clones a repo itself** — the scanner only reads (`.git` presence, `git remote get-url origin`, `git symbolic-ref .../HEAD`, `git log`, `git for-each-ref`). A `source: 'manual'` link may still exist from before auto-discovery shipped; the scanner never edits or removes those.
59
59
60
60
`resolveRepoForSignal(signal)` / `resolveRepoForNode(key, url?)` match a signal or graph-node key to a `RepoLink` with `authoringEnabled`, reusing the same owner/repo and Jira-project-key parsing as `deriveContainer` in `memory-graph.ts`.
Copy file name to clipboardExpand all lines: docs-dev/ipc.md
+7-3Lines changed: 7 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -74,21 +74,22 @@ Links external repos/projects (GitHub `owner/repo`, Jira project keys) to a loca
74
74
| Method | Signature | Description |
75
75
|---|---|---|
76
76
|`getAll`|`() → RepoLink[]`| List all registered repo links (discovered + any legacy manual ones) |
77
-
|`update`|`(id, update: Partial<RepoLink>) → RepoLink`| Patch a repo link — used for the per-repo `authoringEnabled` toggle and `jiraProjectKeys` edits. `localPath`/`githubRepo` are scanner-owned and not user-editable. |
77
+
|`update`|`(id, update: Partial<RepoLink>) → RepoLink`| Patch a repo link — used for the per-repo `authoringEnabled` toggle. `localPath`/`githubRepo`/`jiraProjectKeys` are scanner-owned (re-derived on every rescan) and not user-editable. |
78
78
|`getCodeRoots`|`() → string[]`| Parent folders mypa scans for local git checkouts |
79
79
|`addCodeRoots`|`(paths: string[]) → { roots: string[]; repos: RepoLink[] }`| Adds code roots and immediately rescans; returns the updated roots and repo list |
80
80
|`removeCodeRoot`|`(path: string) → { roots: string[]; repos: RepoLink[] }`| Removes a code root and immediately rescans |
81
81
|`rescan`|`() → RepoLink[]`| Re-scans all configured code roots on demand (Settings "Rescan" button) |
82
82
83
83
### `oauth`
84
84
85
-
OAuth flowsfor Notion and Linear. GitHub is not an OAuth entry — it's a plain PAT/`api_key` catalog entry (see [mcp-and-oauth.md](mcp-and-oauth.md#github--personal-access-token)).
85
+
OAuth/sign-in flows. PKCE for Notion and Linear; device-code sign-in for Outlook. GitHub is not an OAuth entry — it's a plain PAT/`api_key` catalog entry (see [mcp-and-oauth.md](mcp-and-oauth.md#github--personal-access-token)).
86
86
87
87
| Method | Signature | Description |
88
88
|---|---|---|
89
89
|`startPkce`|`(provider: 'notion' \| 'linear') → string`| Begin PKCE flow; returns the authorization URL to open in browser |
90
+
|`startDeviceLogin`|`(entryId: string, env: Record<string, string>) → void`| Run a catalog entry's own device-code login (currently `outlook`); resolves once sign-in completes. No token is returned — the MCP server manages its own token cache. See [mcp-and-oauth.md](mcp-and-oauth.md#outlook--device-code-flow)|
90
91
91
-
The redirect URI for PKCE is `mypa://oauth/callback`. The `state` nonce is validated in `oauth.ts` to prevent authorization code injection.
92
+
The redirect URI for PKCE is `mypa://oauth/callback`. The `state` nonce is validated in `oauth.ts` to prevent authorization code injection. The device-code user code and verification URL are delivered separately via the `oauth:device-code` push channel (below), not this method's return value.
92
93
93
94
### `setup`
94
95
@@ -209,6 +210,7 @@ Subscribed with `window.electron.on(channel, listener)`. Returns an unsubscribe
209
210
|`ambient:chat-message`|`{ intentId: string; chunk: string; done: boolean; error?: string }`| Streaming chunk for an intent's "Chat about it" reply. `done: true` signals completion or error. |**widget + main**|
210
211
|`chat:tool-approval-request`|`PendingToolApproval`| An agent stream reached a write tool and is paused waiting for user approval. The renderer should show an inline approval UI. Resolved by calling `window.electron.chat.resolveToolApproval(approvalId, allow, editedInput?)`. |**widget + main**|
211
212
|`chat:ask-question`|`PendingQuestion`| The model called the `ask_user` tool and the stream is paused waiting for the user's selection. The renderer shows clickable option chips. Resolved by calling `window.electron.chat.answerQuestion(questionId, answer)`. |**widget + main**|
213
+
|`oauth:device-code`|`{ entryId: string; userCode: string; verificationUri: string }`| A device-code login (`oauth.startDeviceLogin`) reached its MSAL device-code prompt. The renderer shows the code and opens `verificationUri` (also auto-opened in the system browser by the main process). | main only |
212
214
213
215
**`routine:run-started` and `routine:run-completed` are broadcast to both windows** via `broadcast()` in `src/main/windows.ts`. The main window uses them to drive in-app toast notifications. The widget uses them to update its inline run card. All other events remain window-specific.
214
216
@@ -292,6 +294,8 @@ Manage PA check-in sessions and their chat threads.
292
294
293
295
## Changelog
294
296
297
+
- 2026-07-23 — **Add Outlook device-code sign-in: `oauth.startDeviceLogin` + `oauth:device-code` push channel.** New `IpcApi.oauth.startDeviceLogin(entryId, env)` (channel `oauth:start-device-login`) runs a catalog entry's own login command and resolves once it exits — used by the new `outlook` connector, whose MCP server manages its own Microsoft token cache/refresh rather than mypa performing an OAuth handshake. New push channel `oauth:device-code` (`{ entryId, userCode, verificationUri }`) delivers the MSAL device code to the renderer as it appears in the login process's output. `AppConfig` gains `device_login_at?:Record<string, string>` (display-only "Connected on <date>" timestamp, not a credential). See [mcp-and-oauth.md](mcp-and-oauth.md#outlook--device-code-flow).
298
+
295
299
- 2026-07-23 — **`repos` namespace switches from manual add/remove to code-root auto-discovery.** `repos.add`/`repos.remove` removed; added `repos.getCodeRoots`, `repos.addCodeRoots`, `repos.removeCodeRoot`, `repos.rescan`. `repos.getAll`/`repos.update` unchanged in shape, but discovered `RepoLink`s now default `authoringEnabled:false` and carry `source`/`lastSeenAt`. See [services.md](services.md#changelog) for the scan/reconciliation details.
296
300
297
301
- 2026-07-22 — **Removed GitHub OAuth device-flow IPC.** `oauth:start-device`/`oauth:poll-device` channels and their preload bindings (`oauth.startDevice`/`oauth.pollDevice`) are removed — GitHub is now a PAT/`api_key` catalog entry, not OAuth (org OAuth-app access-control policies could block the device flow). `IpcApi.oauth` now only exposes `startPkce` (Notion/Linear). See [mcp-and-oauth.md](mcp-and-oauth.md#github--personal-access-token).
0 commit comments