Contributing
Thanks for your interest. docsxai is Apache-2.0 licensed; contributions are welcome.
Where the design lives
Section titled “Where the design lives”The docs in this repo are the public source of truth: AGENTS.md (operating rules + repo map), the runbooks under docs/, and the design rationale under docs/ai-context/. Read those first if you’re changing scope or design shape, and update them in lockstep with implementation changes. (Pre-public planning history lives in the maintainer’s internal planning archive; nothing contributors need is kept there.)
For browser-bridge / discovery-driver concerns, the cross-repo contract is at docs/browxai-asks.md; the portable actionability predicate is at docs/actionability-contract.md.
Development setup
Section titled “Development setup”corepack enable # provides pnpm 9.xpnpm installpnpm -C packages/engine exec playwright-core install chromium # needed for the keystone test + `docsxai run`Node 20+. Package manager is pnpm 9.x.
Checks (all must pass before a PR merges - CI runs them):
pnpm typecheck # tsc --noEmitpnpm test # vitest unit suite + keystone where presentpnpm build # tsc → dist/ for every packageThe unit suite is fast and browser-free. The keystone
(packages/engine/test/keystone.test.ts) drives a real headless
Chromium end-to-end through the engine’s runtime + the docsxai run
path - it’s the regression gate for anything touching page interaction,
the runtime, auth strategies, or the deterministic-replay contract.
Repo layout
Section titled “Repo layout”packages/ engine/ @docsxai/engine — flow-file runtime, CLI, auth strategies plugin/ @docsxai/plugin — Claude Code plugin (the invocation surface) backend/ @docsxai/backend — auth'd persistence (stub today) skill/ @docsxai/skill — vendorable .claude/skills/ fallback viewer/ @docsxai/viewer — static-HTML viewerdocs/ runbooks + cross-repo contracts (browser-bridge integration, actionability)Code conventions
Section titled “Code conventions”- TypeScript strict. No
anyin published surfaces. - ESM only (
"type": "module"). All cross-package imports use.jsextensions in source. - Tests sit alongside code as
<name>.test.tsunder each package’stest/. Vitest. New code ships with a test. - Don’t add error handling for impossible states. Trust internal code and framework guarantees; only validate at system boundaries.
- Default to writing no comments. Only add one when the why is non-obvious - a hidden constraint, a workaround, behavior that would surprise a future reader.
- No backwards-compatibility shims for unused code paths. Delete unused exports cleanly.
- No internal tracker IDs in code or comments. Ticket / plan / round / PR refs (
W-X#,Round-N, ticket numbers) belong in commit/PR bodies, not in source. State the actual reason instead. - No model-provider SDKs anywhere in
packages/{engine,plugin,backend,viewer,skill}/. The engine is LLM-agnostic by design; the host agent supplies inference at calibration time. Importing a provider SDK in this repo is a contract violation.
Two-mode architecture (read before editing the runtime)
Section titled “Two-mode architecture (read before editing the runtime)”The engine has two modes - calibration (AI-assisted, rare) and execution (deterministic, continuous). The split is load-bearing:
- The engine never calls a model API. The host agent supplies inference at calibration time; execution has no agent in the loop.
docsxai runreproduces a doc pack byte-identically from the same flow-file + same target state. The keystone test asserts this against a real browser.- Adding model-provider code anywhere in
packages/{engine,plugin,backend,viewer,skill}/is a contract violation. The future commercial SaaS surface is the only place provider SDKs live, and it’s not in this repo.
Commits
Section titled “Commits”- Single-line conventional-commit subjects, ≤72 chars. No body, no AI trailers. Hook-enforced (
.claude/hooks/); don’t bypass them. - One logical change per commit. Don’t
git add .- stage paths explicitly withgit add <paths>. - For a multi-package change, one commit per package unless the change is genuinely atomic.
- Allowed types:
build,chore,ci,docs,feat,fix,perf,refactor,revert,style,test.
Examples:
feat(engine): actionability predicate + portable consumer contractfix(viewer): clamp nudge offsets to image boundsdocs(agent-runbook): document the calibration discovery driverDeveloper Certificate of Origin (DCO)
Section titled “Developer Certificate of Origin (DCO)”We require contributors to sign off on commits with git commit -s. This adds a Signed-off-by: trailer that attests you wrote (or have the right to contribute) the change under the project’s license. We use DCO instead of a CLA. The DCO text lives at https://developercertificate.org/.
Branch model
Section titled “Branch model”- Feature branches off
main:feat/<slug>,fix/<slug>,chore/<slug>,docs/<slug>,test/<slug>,refactor/<slug>. - Open a PR against
main. One maintainer review is required (enforced by CODEOWNERS once the CODEOWNERS file lands). - Squash-merge is the default. Keep the subject conformant - it becomes the squashed-commit subject.
- Draft PRs are welcome for in-flight design conversation.
Pull requests
Section titled “Pull requests”- Branch, make the change, add tests, keep
pnpm typecheck/pnpm test/pnpm buildgreen. - Update the relevant runbook (
docs/agent-runbook.md,docs/running-against-an-app-repo.md) for any user-facing surface change. - Update
CHANGELOG.mdunder## Unreleased. - Open a PR; describe the why.
For non-trivial changes, open an issue first so we can align on shape - the issue (anchored on the relevant docs/ runbook or docs/ai-context/ page) is the place for that discussion.
Stability & the public surface
Section titled “Stability & the public surface”docsxai will follow semver post-v1.0. Until v1.0, the public API may change at any time; we will still note breaking changes in CHANGELOG.md.
The stable surface post-v1.0 - docsxai subcommand names + documented flags, flow-file schema, doc-pack output shape, the actionability-contract predicate, the BrowserDriver interface, the backend’s REST surface - does not change in a patch; an additive change is a minor; a breaking change requires a major bump plus a changelog entry and a deprecation note.
Plugin contribution guide
Section titled “Plugin contribution guide”To contribute to the Claude Code plugin (@docsxai/plugin):
- Confirm the contribution is plugin-shaped, not engine-shaped. New capability lives in the engine; the plugin exposes it. A pure plugin-only change is something like adding a skill, refining the calibrate workflow, or adjusting command UX.
- Plugin skills live under
packages/plugin/skills/; plugin commands live underpackages/plugin/commands/. Follow the existing structure. - Plugin skills emit structured questions through Claude Code’s question API and shell out to
docsxai. They do not embed their own runtime; the engine binary is the single source of behaviour. - Plugin commands are deterministic
docsxaiinvocations. They wrap the CLI; they don’t reach into the engine’s internals. - Add a test under
packages/plugin/test/. - Update the package README at
packages/plugin/README.mdif the surface changed. - Note the change in
CHANGELOG.mdunder## Unreleased ### Plugin.
The plugin’s job is to be the recommended invocation surface - not to add capability the engine doesn’t have. If a contribution feels like it needs new engine behaviour, raise that first as an engine PR.
Filing issues
Section titled “Filing issues”- Reproducer minimal? Good.
- For engine issues: mention the engine version (
pnpm -C packages/engine listordocsxai --version), Node version, and platform. - For browser-related issues: include the Playwright version and whether you’re attached over CDP (
--cdp http://localhost:9222) or launched fresh. - For plugin issues: include the plugin manifest version, the Claude Code version, and the calibrate-skill output that caused the failure.
- For viewer issues: include a screenshot of the rendered viewer, the doc-pack
annotations.json, and the browser + version you opened it in. - For backend issues: include the backend version, the request payload (with secrets redacted), and the response.
For security-sensitive reports, please follow SECURITY.md rather than opening a public issue.
Workspace-rooted paths
Section titled “Workspace-rooted paths”Every transient path docsxai writes lives under the workspace directory the operator passes to the CLI (e.g. ~/docsxai/my-app). Code never writes to $HOME, cwd, or /tmp directly. Internal Kalebtec paths do not appear in code, comments, tests, or public docs.
Issue label conventions
Section titled “Issue label conventions”We use these label families on issues and PRs:
area::engine|plugin|backend|viewer|skill|docsphase::triage|accepted|in-progressseverity::critical|high|normal|lowkind::bug|feat|chore|docs|security|proposal
Bot allowlist
Section titled “Bot allowlist”See .github/BOT_ALLOWLIST.md (lands with the launch-gate phase). New GitHub Apps that require write access require owner approval and a rationale entry in SECURITY.md.
License
Section titled “License”By contributing, you agree your contributions are licensed under Apache-2.0.