Phase A of productionizing for team sharing. Replaces .env.local-only dev config with a real per-teammate connection flow — the foundation for handing this to your team.
Main
config-store.ts — token encrypted at rest via Electron safeStorage (OS keychain); config JSON in userData. Token lives only in main; the renderer receives everything but the token.
resolveConfig — saved config > .env.local (dev) > null; ignored under COMMITEA_E2E. pm-state repo defaults to ${repo}-pm-state. resetClients() re-reads on change, so saving config takes effect without a restart. gitea:status gains demo.
IPC — config:get (no token), config:test (authed read validates token+repo), config:set (encrypt+save+reset), config:clear. Model bridge reads config.modelUrl and probes reachability — chat is 'configured' only if a model actually answers (localhost default is dev-only via app.isPackaged).
Renderer
ConnectScreen — real onboarding form (URL / owner / repo / PAT / optional model) → test → save. AppShell gates: demo → shell (fixtures/e2e); configured → shell (real); else → connect.
Settings Connection card is real (repo / url / model / sidecar) with Reconfigure + Disconnect.
Chat cleanly disables with a 'no model' state instead of the scripted canned reply.
Verified
main + desktop typecheck clean · 14 fixture e2e green (demo mode unchanged) · live onboarding e2e: a fresh app (isolated userData, no .env.local) → connect form → validated PAT → real board (24 done / 10 open). Screenshot in run.
Next (productionize)
Phase B — kill the remaining fixtures: Standup, Inbox, Gantt + Dependencies tabs, Issue-screen sidecar; hide dev-only rail entries (States/Primitives/First-run) in prod.
Phase C — package: electron-builder → an unsigned macOS .dmg you can share.
**Phase A of productionizing for team sharing.** Replaces `.env.local`-only dev config with a real per-teammate connection flow — the foundation for handing this to your team.
## Main
- **`config-store.ts`** — token encrypted at rest via Electron **safeStorage** (OS keychain); config JSON in userData. Token lives only in main; the renderer receives everything *but* the token.
- **resolveConfig** — saved config > `.env.local` (dev) > null; ignored under `COMMITEA_E2E`. pm-state repo defaults to `${repo}-pm-state`. **`resetClients()`** re-reads on change, so saving config takes effect **without a restart**. `gitea:status` gains `demo`.
- **IPC** — `config:get` (no token), `config:test` (authed read validates token+repo), `config:set` (encrypt+save+reset), `config:clear`. Model bridge reads `config.modelUrl` and **probes reachability** — chat is 'configured' only if a model actually answers (localhost default is dev-only via `app.isPackaged`).
## Renderer
- **ConnectScreen** — real onboarding form (URL / owner / repo / PAT / optional model) → test → save. **AppShell gates**: demo → shell (fixtures/e2e); configured → shell (real); else → connect.
- **Settings Connection** card is real (repo / url / model / sidecar) with **Reconfigure + Disconnect**.
- **Chat** cleanly disables with a *'no model'* state instead of the scripted canned reply.
## Verified
main + desktop typecheck clean · 14 fixture e2e green (demo mode unchanged) · **live onboarding e2e**: a fresh app (isolated userData, no `.env.local`) → connect form → validated PAT → **real board** (24 done / 10 open). Screenshot in run.
## Next (productionize)
- **Phase B** — kill the remaining fixtures: Standup, Inbox, Gantt + Dependencies tabs, Issue-screen sidecar; hide dev-only rail entries (States/Primitives/First-run) in prod.
- **Phase C** — package: electron-builder → an unsigned macOS `.dmg` you can share.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
christian
added 1 commit 2026-07-09 06:10:21 +00:00
The foundation for a shareable team build. Replaces the .env.local-only dev config
with a real, per-teammate connection flow.
main:
- config-store.ts: token encrypted at rest via Electron safeStorage (OS keychain),
config JSON in userData. Token lives only in main; renderer gets everything but.
- resolveConfig: saved config > .env.local (dev) > null; ignored under COMMITEA_E2E.
pm-state repo defaults to `${repo}-pm-state`. resetClients() re-reads on change so
saving config takes effect without a restart. gitea:status gains `demo` (e2e).
- IPC: config:get (no token), config:test (authed read validates token+repo),
config:set (encrypt+save+reset), config:clear. Model bridge reads config.modelUrl
and probes reachability — chat is "configured" only if a model actually answers;
localhost default is dev-only (app.isPackaged gate).
renderer:
- ConnectScreen: real onboarding form (URL/owner/repo/PAT/optional model) → test →
save. AppShell gates on it: demo → shell (fixtures/e2e); configured → shell (real);
else → connect. Settings Connection card is real (repo/url/model/sidecar) with
Reconfigure + Disconnect. Chat cleanly disables with a "no model" state instead of
the scripted canned reply.
Verified: main + desktop typecheck clean, 14 fixture e2e green (demo mode unchanged),
live onboarding e2e: fresh app → connect form → validated PAT → real board (24 done /
10 open). COMMITEA_NO_ENV_LOCAL + COMMITEA_USERDATA are test hooks for the onboarding path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Phase A of productionizing for team sharing. Replaces
.env.local-only dev config with a real per-teammate connection flow — the foundation for handing this to your team.Main
config-store.ts— token encrypted at rest via Electron safeStorage (OS keychain); config JSON in userData. Token lives only in main; the renderer receives everything but the token..env.local(dev) > null; ignored underCOMMITEA_E2E. pm-state repo defaults to${repo}-pm-state.resetClients()re-reads on change, so saving config takes effect without a restart.gitea:statusgainsdemo.config:get(no token),config:test(authed read validates token+repo),config:set(encrypt+save+reset),config:clear. Model bridge readsconfig.modelUrland probes reachability — chat is 'configured' only if a model actually answers (localhost default is dev-only viaapp.isPackaged).Renderer
Verified
main + desktop typecheck clean · 14 fixture e2e green (demo mode unchanged) · live onboarding e2e: a fresh app (isolated userData, no
.env.local) → connect form → validated PAT → real board (24 done / 10 open). Screenshot in run.Next (productionize)
.dmgyou can share.🤖 Generated with Claude Code
The foundation for a shareable team build. Replaces the .env.local-only dev config with a real, per-teammate connection flow. main: - config-store.ts: token encrypted at rest via Electron safeStorage (OS keychain), config JSON in userData. Token lives only in main; renderer gets everything but. - resolveConfig: saved config > .env.local (dev) > null; ignored under COMMITEA_E2E. pm-state repo defaults to `${repo}-pm-state`. resetClients() re-reads on change so saving config takes effect without a restart. gitea:status gains `demo` (e2e). - IPC: config:get (no token), config:test (authed read validates token+repo), config:set (encrypt+save+reset), config:clear. Model bridge reads config.modelUrl and probes reachability — chat is "configured" only if a model actually answers; localhost default is dev-only (app.isPackaged gate). renderer: - ConnectScreen: real onboarding form (URL/owner/repo/PAT/optional model) → test → save. AppShell gates on it: demo → shell (fixtures/e2e); configured → shell (real); else → connect. Settings Connection card is real (repo/url/model/sidecar) with Reconfigure + Disconnect. Chat cleanly disables with a "no model" state instead of the scripted canned reply. Verified: main + desktop typecheck clean, 14 fixture e2e green (demo mode unchanged), live onboarding e2e: fresh app → connect form → validated PAT → real board (24 done / 10 open). COMMITEA_NO_ENV_LOCAL + COMMITEA_USERDATA are test hooks for the onboarding path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>