Documentation
Contributing code
Trace a user action through the real modules, update its contract, and verify the resulting behavior.
Locate the implementation
Start with the behavior you are changing. For a desktop action, follow apps/desktop/src/app/routes.tsx to its page adapter and feature screen. Locate the request in its client or feature helper, the endpoint schema in packages/api, the handler in apps/sidecar/src/http, and the service or repository underneath it.
For a geometry or NC-output change, begin in packages/core and its adjacent tests. For a persistence issue, inspect the repository query and packages/db/src/schema.ts. For native lifecycle, file-dialog, keychain, or updater behavior, inspect apps/desktop/src-tauri/src. This keeps a change close to its actual responsibility.
Workspace responsibilities
| Module | Responsibility |
|---|---|
packages/core | Pure CAD/CAM models and algorithms, posts, program parsing, and verification. |
packages/api | Shared schemas, endpoint contracts, and generated clients. |
packages/db | SQLite connection lifecycle, Drizzle schema, migrations, and upgrade backups. |
packages/ai | Model integration, embedded host, action catalogue, sessions, and AI tools. |
packages/plugin-sdk, packages/nikcli-plugin | Application plugin contract and standalone nikcli action-bridge client. |
packages/vcs, packages/workflow | Project history and workflow definitions/execution. |
apps/sidecar | HTTP adapters, service composition, repositories, gateway, and application integrations. |
apps/desktop, apps/mobile | Desktop UI/native shell and paired iOS client. |
packages/httpapi-codegen, packages/web | API client generation and the documentation/Studio site. |
Use the public entry point of a module when available. Keep SQLite access out of core geometry and clients. Feature screens should not bypass sidecar authorization or embed server credentials. Cross-cutting changes should update each affected boundary explicitly.
Change shared contracts deliberately
- Define the request, response, and typed error schemas in the contract package.
- Implement the handler and its service/repository behavior, including ownership checks.
- Regenerate clients and check that the generated output is current.
- Update desktop, companion, plugin, or external client consumers that use the changed surface.
- Document the supported input, output, failure behavior, and operational limits.
bun run generate
bun run generate:check
bun run --filter @cadcamfun/api typecheck
bun run --filter @cadcamfun/sidecar typecheck Generated clients are outputs of the contract generator. Fix the contract or generator when their shapes are wrong; a handwritten correction to generated output will be lost on regeneration. Preserve existing client semantics or identify the compatibility impact of a deliberate API change.
Implementation conventions
Write code, comments, and documentation in English. Keep exported TypeScript interfaces explicit and use unknown plus schema validation for untrusted values. Relative TypeScript imports use .ts extensions. CAD distances use millimetres and drawing angles use radians; honor explicitly degree-valued feature and CAM rotary inputs. Format NC numbers at the post boundary.
Effect code uses the pinned version's service/layer/error APIs. Services own external dependencies; scoped layers own resources. Avoid adding hidden process configuration reads inside a domain module. Keep geometry calculations pure and isolate filesystem, network, and database operations behind their adapters.
For a schema change, modify schema.ts, generate a migration, and exercise both fresh creation and upgrade of an existing database. For a UI change, keep route adapters small and place interaction logic in the relevant feature. For native work, keep geometry and repository logic in the sidecar/core rather than moving it into Rust.
Verification before review
- Run the affected package's typecheck and meaningful tests for the changed behavior.
- For a bug fix, demonstrate the failing condition and its corrected result.
- For shared contracts, check generated clients and affected consumers.
- For persistence, verify migration behavior and data integrity using isolated databases.
- For native or rendered interactions, exercise the actual target runtime in addition to logic tests.
- Update user/developer documentation and explain operational limitations that remain.
The root checks are bun run typecheck and bun run test. CI also has Rust and companion-specific jobs. Report what was run and any failures or unavailable runtime coverage; distinguish a configured workflow from a successful run.
Keep changes reviewable
Keep generated artifacts, dependency updates, behavior changes, and documentation changes traceable to the same concrete purpose. Avoid reformatting unrelated modules. Preserve existing user work and use disposable data directories for experiments.
Do not include launch tokens, device pairing links, model keys, database contents, or signing credentials in patches or screenshots. Examples should use placeholders. A local fixture or mocked provider can validate a deterministic flow; document where real provider or native integration remains necessary.
Useful checks
bun run --filter @cadcamfun/core typecheck
bun test packages/core
bun test apps/sidecar/test
bun test apps/desktop/src
bun run --cwd apps/mobile typecheck
bun run --cwd apps/mobile test
bun run --cwd packages/web check
bun run --cwd packages/web build Native packaging uses scripts/build.ts; use --help or --dry-run to inspect its stages. Unit tests are separate from the build pipeline's typecheck stage. Consult the release guide for signing, target architecture, and updater validation.
Example: change project validation
Suppose a project create/update rule changes. The request schema is packages/api/src/projects.ts, the HTTP adapter is apps/sidecar/src/http/projects.ts, and persistence is implemented by ProjectRepo. The schema currently makes name optional, while handlers require it for creation and update. Inspect both levels before promising that a schema-valid request will succeed.
- Define the intended input cases: missing name, invalid type, empty text, accessible organization, and inaccessible organization.
- Decide which condition is a decoding error and which is business validation. Preserve the endpoint's documented status/error shape.
- Add assertions at the relevant handler/service boundary and verify unauthorized or non-member callers cannot bypass the rule.
- If the public schema changed, regenerate both client families and typecheck consumers.
- Exercise the desktop form and document any changed request requirements.
Creation currently returns a bare project row with HTTP 201. List/get return relation-enriched rows. Do not impose a generic success envelope on this family without updating its contract and consumers. Other endpoint families intentionally use different envelopes.
The generator entry point is packages/api/scripts/generate-clients.ts. Its outputs live under src/client/generated and src/sdk/generated. Changes to the contract surface belong in the source contract; generated output should be reproducible.
Choose a regression at the right depth
A geometry regression should assert geometry, not only repeat the calculation being changed. Existing collision tests provide useful patterns: a stationary overlap is a collision at time zero; an intermediate rotational sweep can collide even when an endpoint is clear; an insufficient bound is unresolved; and a certified clearance is compared against a dense independent reference.
bun test packages/core/src/cam/kernel/collision.test.ts
bun run --filter @cadcamfun/core typecheck
bun test packages/core Choose the analogous boundary for other work. A database migration needs fresh/upgrade cases and backup failure behavior. A stream parser needs split frames and cancellation. A UI save change needs destination selection, request failure, retry, and reopening saved state. A native command needs validation and lifecycle behavior in addition to a frontend typecheck.
Keep checks proportional to the change. Content edits need navigation/template verification; they do not require inventing new domain tests. A passing narrow test supports only its asserted behavior, so include the package or integration checks required by the changed public surface.
Contribute documentation
The website is in packages/web. Documentation pages use DocsLayout, a table of contents, section identifiers, and shared code/callout/related-link components. Preserve those page conventions and the existing visual design while improving the content.
- Read the implementation, manifest, and configuration for every behavior you document.
- Use a supported command or request shape and state the necessary working directory, credentials, data path, and native prerequisites.
- Describe the result and its failure modes. Label examples as examples; call a response captured only when it was actually captured.
- Update navigation and retrieval metadata when adding or renaming a route, and fix every local link to the old location.
- Run index checks and the Astro build, then inspect the rendered page and its anchors.
bun run --cwd packages/web check
bun run --cwd packages/web typecheck
bun run --cwd packages/web build Claims about configured CI should say what the workflow does. Claims about successful publication or runtime acceptance need the particular run/artifact as evidence. Documentation should distinguish implemented behavior, defaults, and limits without turning internal planning notes into product instructions.
Pull request checklist
bun run typecheckpasses at the root.bun run testpasses; new behaviour has a test next to the code.- Contract changes are regenerated:
bun run generate:checkandbun run --filter @cadcamfun/web checkare clean. - Schema changes include the generated migration folder and are never edits of an applied migration.
- Rust changes pass
cargo clippyandcargo test(CI runs both). - User-visible behaviour is reflected in the docs page that describes it.
CI runs the same commands on every push, so a green local run is the best predictor of a green pull request.