Thanks for your interest in contributing! This guide covers the basics.
git clone https://github.com/timwuhaotian/pair-code.git
cd pair-code
npm installPrerequisites:
- Node.js ≥ 20
- npm (comes with Node)
- Create a branch:
git checkout -b feat/my-feature - Make your changes, following the conventions below.
- Verify:
npm run typecheck # must pass npm run lint # must pass npm run build # must succeed npx tsx scripts/preview.tsx # visually check the UI if you touched components
- Commit with a clear message (conventional commits preferred:
feat:,fix:,docs:,refactor:). - Open a pull request against
main.
This project currently has no test suite. To verify changes:
- Run
npm run typecheckandnpm run lint. - Render
scripts/preview.tsxto check UI changes visually. - Exercise the CLI manually against a real Anthropic-compatible endpoint.
If you'd like to add a test framework, please open an issue first to discuss the approach.
- ESM only —
"type": "module", norequire()/CommonJs. - Strict TypeScript —
strict: true. Type every signature; prefer discriminated unions overany. - Relative imports use
.jsextensions even from.ts/.tsxsources (e.g.import { foo } from './bar.js'). - No formatter is configured. Match surrounding style; don't add one without asking.
- JSX:
react-jsx(automatic runtime). In.tsx, import theJSXtype explicitly (import type { JSX } from 'react').
These boundaries are load-bearing — don't mix concerns:
| Module | What it does | What it must NOT do |
|---|---|---|
process.ts |
Pair engine | No React, no rendering |
providers.ts |
Profile resolution | No React |
config.ts |
On-disk config I/O | No profile/merge logic, no React |
state.ts |
State mutations | No rendering, no I/O beyond git status |
components.tsx |
Presentational components | No state mutation |
ui.ts |
Theme tokens | No rendering, no state |
Breaking any of these will silently corrupt the loop:
- Only the Mentor may emit
TASK_COMPLETEon its own line. The Executor's system prompt forbids it. - Roles are asymmetric: Executor has
permissionMode: 'bypassPermissions'+ full tools; Mentor is read-only (Read,Grep,Globonly). - Turn timeout is 10 minutes (
TURN_TIMEOUT_MS). - Mentor reviews must include the structured JSON block (
{"verdict":…, "risk":…, "nextStep":{…}}). Don't change the contract without updatingparseVerdictincomponents.tsx. - Session continuity is per-turn: each turn starts a fresh
query()withresume: <sessionId>.
Use the bug report template. Include:
- Your Node version and OS
- The provider/endpoint you're using
- Steps to reproduce
- Expected vs. actual behavior
- Any error output
Use the feature request template. Describe the use case, not just the solution.
By contributing, you agree that your contributions will be licensed under the Apache-2.0 License.