| document_id | doc.development | |||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| last_verified | 2026-04-06 | |||||||||||||||||||||||||
| tokens_estimate | 700 | |||||||||||||||||||||||||
| tags |
|
|||||||||||||||||||||||||
| anchors |
|
|||||||||||||||||||||||||
| ttl_expires_on |
Anchors: SYSTEM_ARCHITECTURE.md, reference/configuration-reference.md
- INVARIANT: Frontend port 3000; backend 8000 when applicable
- INVARIANT: Kill and restart servers rather than using higher ports
- INVARIANT: Run tests before commit; type-check before push
- Node.js 20+
- Anthropic credential (API key or local Claude CLI config)
- GitHub credential for repo operations (OAuth Connect GitHub or PAT with
reposcope)
Use pnpm or npm to install dependencies (pnpm recommended if npm has auth/token issues):
pnpm install # or: npm install- Development: Copy
.env.exampleto.env.local; minimally setGITHUB_OAUTH_CLIENT_ID(for OAuth) orGITHUB_TOKEN(PAT). SetANTHROPIC_API_KEYunless Claude CLI already provides one. - Self-deploy: Use
/setupor edit~/.dossier/config - Precedence:
process.env>.env.local>~/.dossier/config
/setup checks /api/setup/status and redirects to / when both credentials are satisfied.
Anthropic is satisfied by either:
ANTHROPIC_API_KEY(env/config), or- installed Claude CLI config (
~/.claude/settings.json/CLAUDE_CONFIG_DIR).
GitHub is satisfied when resolveGitHubToken() can resolve a token from env/config.
- UI calls
/api/github/oauth/start?return_to=... - Server stores PKCE verifier + state cookies and redirects to GitHub authorize URL (
scope=repo) - Callback
/api/github/oauth/callbackexchanges code for token and writesGITHUB_TOKENinto~/.dossier/config - User returns with
?github_oauth=success
For local development, configure:
GITHUB_OAUTH_CLIENT_ID(required)GITHUB_OAUTH_CLIENT_SECRET(optional, but commonly needed for token exchange)
Loopback callback supports dynamic local ports (for Electron/CLI paths) using:
http://127.0.0.1:<port>/api/github/oauth/callback
Users can provide a PAT in Setup/API Keys UI; it is written to ~/.dossier/config as GITHUB_TOKEN.
Disconnect (DELETE /api/github/auth) removes stored token and writes:
DOSSIER_GITHUB_IGNORE_ENV=1
This intentionally ignores process.env.GITHUB_TOKEN until reconnect, so “disconnect” stays effective even if .env.local still contains an old token.
| Script | Purpose |
|---|---|
npm run dev |
Next.js dev server (port 3000) |
npm run build |
Production build + postbuild (standalone) |
npm run start |
Start production server |
npm run dossier |
Run standalone CLI (opens browser) |
npm run test |
Run Vitest suite |
npm run test:watch |
Vitest watch mode |
npm run lint |
ESLint |
npm run rebuild |
Rebuild and restart (dev) |
npm run rebuild:prod |
Rebuild and restart (prod) |
Default: ~/.dossier/
~/.dossier/
config # API keys, settings (KEY=VALUE)
dossier.db # SQLite database
ruvector/ # Vector embeddings (future)
Override: DOSSIER_DATA_DIR or SQLITE_PATH
- Create feature branch:
git checkout -b feature/task-name - Make changes; run
npm run testandnpm run lint - Commit with descriptive message
- Rebase on main before merge
When a PR is merged outside Dossier, sync the project clone before next build:
curl -X POST "http://localhost:3000/api/projects/<projectId>/repo/sync"Expected: { "success": true, "branch": "<default_branch>" }
If a card build is blocked awaiting decisions:
curl -X POST "http://localhost:3000/api/projects/<projectId>/orchestration/resume-blocked" \
-H "Content-Type: application/json" \
-d '{"card_id":"<cardId>","actor":"user"}'Expected: 202 with assignmentId, runId, and outcome_type.
Use /api/dev/restart-and-open to start a cloned project server on ports 3001..3010 without touching the main Dossier app on 3000.
Common responses:
200started successfully409clone missing (build at least once first)503no free preview port in range404route disabled (hosted runtime / missing enable flag)
On standalone/Electron/CLI production builds, set DOSSIER_ALLOW_PROJECT_DEV_SERVER=1 to allow this route.
Check:
GET /api/setup/statusmissingKeys~/.dossier/configfile permissions and values- whether
DOSSIER_GITHUB_IGNORE_ENV=1is still set after a deliberate disconnect
Typical causes:
- missing
GITHUB_OAUTH_CLIENT_ID - callback mismatch in OAuth app settings
- stale/expired state cookies (retry Connect GitHub)
- user cancelled consent (
github_error=access_denied)
Check:
- project clone exists under
~/.dossier/repos/<projectId> - free port exists in
3001..3010 - runtime allows route (
NODE_ENV=developmentorDOSSIER_ALLOW_PROJECT_DEV_SERVER=1, and not hosted cloud detection)
-
npm run devstarts on 3000 -
npm run testpasses -
npm run buildsucceeds