Agent behavior instructions for continues — the cross-tool AI session handoff CLI. Read CLAUDE.md for architecture, types, and the step-by-step guide for adding a new parser. This file covers workflow, coding standards, and anti-patterns.
- Before any commit: run
pnpm run check(pnpm lint && pnpm build). Fix all Biome errors; warnings are advisory. - After changing a parser or fixture: run
pnpm testand confirm all tests pass. Do not commit with failing tests. - After adding a new tool: run
pnpm run linkto test the globalcontinues/contbinary locally. - Never run
pnpm run test:watch,e2e-conversions.test.ts,real-e2e-full.ts, orstress-test.tsin CI — these require live session files on the developer's machine.
- ESM-only: all local imports must end in
.js, even for.tssource files (e.g.,import { foo } from './foo.js'). - No
any: Biome reportsnoExplicitAnyas a warning. Avoid it; document the reason if unavoidable. - Exit codes: set
process.exitCode = Nrather than callingprocess.exit(N). - Logging: use
loggerfromsrc/logger.tsfor all diagnostic output. Never use bareconsole.log/console.warn/console.errorin library code. TUI display goes through@clack/promptsorchalkvia the display layer. - Error types: throw typed errors from
src/errors.tson user-facing paths, not barenew Error(). - Tool activity: use
SummaryCollectorfromsrc/utils/tool-summarizer.tsin every parser. Do not buildToolUsageSummary[]arrays manually. - JSONL: stream with
readline.createInterface, neverfs.readFileSync+split('\n'). - SQLite (OpenCode, Crush parsers): use built-in
node:sqlite— do not add third-party SQLite dependencies. - Biome rules in force:
noEmptyBlockStatements(error),noUnusedImports(error),useConst(error). Emptycatch {}blocks fail the linter; usecatch (err) { logger.debug(...) }instead.
All five steps are required. Missing any one is a bug. See CLAUDE.md for detailed implementation guidance.
- Add tool name to
TOOL_NAMESinsrc/types/tool-names.ts - Create
src/parsers/<tool>.tsexportingparse<Tool>Sessions()andextract<Tool>Context() - Register in
src/parsers/registry.ts(the completeness assertion throws at module load if missing) - Add
create<Tool>Fixture()insrc/__tests__/fixtures/index.ts - Add conversion test cases in
src/__tests__/unit-conversions.test.ts
@clack/prompts— all interactive TUI prompts and spinners. Do not usereadlineorinquirer.chalk— terminal color. Chalk v4 is installed (CommonJS compat import); do not upgrade to v5+ (ESM-only).commander— CLI argument parsing.ora— non-interactive spinners.yaml— YAML parsing for Copilot sessions.zod— runtime schema validation. Usez.safeParse()where failures are recoverable.- Do not add new runtime dependencies without strong justification. The install footprint is intentionally small.
- Writing to tool storage directories — the tool is read-only. Any write to
~/.claude/,~/.codex/, etc. is a severe bug. exec()with string interpolation — always usespawn()with an argument array inresume.ts. Session IDs and paths can contain shell metacharacters.fs.readFileSync/fs.writeFileSyncin parsers — these block the event loop. Use async fs APIs orreadline.- Duplicating parser-helpers —
cleanSummary,extractRepoFromCwd,homeDirlive insrc/utils/parser-helpers.ts. Import them; do not reimplement. - Hardcoding tool names — derive from
TOOL_NAMESorSessionSource. Never writeif (tool === 'claude' || tool === 'codex' || ...). - Importing
node:sqliteoutside OpenCode/Crush parsers — SQLite is only needed for those two tools. Do not spread this dependency. - Embedding secrets in handoff markdown —
.continues-handoff.mdis written to project directories and may be committed or read by other AI tools.