Skip to content

CLI reference

The tenchi command scaffolds the prescribed structure, inspects the composed application, and keeps API changes reviewable.

Commands with --json, plus compatibility commands using --diff-format json, reserve stdout for one versioned JSON object. If Tenchi cannot construct the command's normal result, it emits a shared operation_error object with a stable operation and error code, then exits nonzero. These failures omit application exception text and payloads. This means an agent can parse both success and expected failure without falling back to terminal prose.

Create an application

uvx tenchi new my_app

Names use snake_case. The generated project includes a todos feature, SQLite persistence with request-scoped transactions, a memory test adapter, strict checks, integration tests, Swagger UI, an OpenAPI snapshot, a tenchi.toml verification policy, a concise AGENTS.md, project-local MCP configuration, and GitHub Actions CI. Nothing else is required to serve an HTTP API.

uvx tenchi new my_app --full

--full also generates the composition modules for background jobs, operational tasks, application tools, evaluations, and preflight checks, plus the snapshot, snapshot test, and tenchi.toml stage for jobs, tools, and evaluations, so every extension point exists from the start. Without it, add each module when the application adopts that capability; the matching guide shows the file, and tenchi verify treats the first snapshot as a first adoption when the module did not exist at the baseline.

Generate application slices

uv run tenchi make feature notes
uv run tenchi make feature notes --dry-run
uv run tenchi make use-case notes create_note
uv run tenchi make use-case notes create_note --json
uv run tenchi make use-case notes create_note \
  --from-contract app.features.notes.contracts:create_note_contract \
  --dry-run --json
uv run tenchi make use-case notes create_note \
  --from-contract app.features.notes.contracts:create_note_contract \
  --plan .tenchi/changes/create-note.json \
  --base-ref origin/main --json

Generators create files and print explicit wiring instructions. They never rewrite route or infrastructure modules. A new feature receives tasks.py, jobs.py, tools.py, or evaluations.py only when the matching app/server/ composition module exists, so a feature never gains a file that nothing composes. --dry-run validates the operation and lists every file without writing it. --json emits the same result as a versioned object with the app root, artifact identity, files, follow-up steps, and any error.

When the contract already exists, pass its module:attribute target through --from-contract. Tenchi imports that declaration and derives the use case's exact params, query, headers, request, context, and response annotations in route-call order. Before planning files, it also proves that the contract can be bound as a route and represented in OpenAPI, catching invalid path parameters or unsupported boundary shapes at preview time. The target must live in the selected feature's contracts.py module. Named boundary aliases should live in that feature's schemas.py or domain.py, or under app.shared, so the generated use case can import them without reversing the application's dependency direction. Name deeply nested boundary types there too; Tenchi fails early rather than emit an inline annotation that would not pass the generated app's formatter. Previewing from a contract imports that module to inspect its runtime types, so keep contract modules declarative and free of startup I/O.

Contract-driven generation writes a # tenchi: incomplete marker in the use case and its generated failing test. Ruff and Pyright can validate the boundary immediately, while pytest and tenchi doctor keep tenchi check red until you implement the behavior, replace the placeholder test, and remove both markers. Contracts that use response definitions need an app-owned presenter result, so Tenchi reports a structured configuration error instead of guessing that return type. A contract with response_headers keeps its response type, and the generated follow-up steps call out the required synchronous header projector.

--plan PATH is available with --from-contract. It resolves --base-ref (default HEAD) to a baseline commit and writes a versioned structural plan in the same transaction as the generated use case and test. The result includes the content-derived plan ID. With --dry-run, Tenchi returns the prospective plan but writes neither the plan nor application files. See verify a generated change for the complete workflow and proof boundary.

Inspect routes

uv run tenchi routes
uv run tenchi routes --json

The default target is app.server.routes:routes. Override it with --routes module:attribute. JSON output is a versioned object containing the application root and the composed HTTP surface under routes.

Map the application

uv run tenchi map
uv run tenchi map --json
uv run tenchi map --feature notes --json
uv run tenchi map --feature notes \
  --kind route,job,task,tool,evaluation,use-case,policy,port --json

Map combines the canonical source layout with composed API routes, operational tasks, background jobs, application tools, and evaluations. It returns a deterministic, versioned graph covering features, contracts, routes, background jobs, operational tasks, application tools, evaluations, use cases, policies, ports, adapters, context types, entrypoints, and tests. Edges describe ownership, route bindings, dependencies, authorization, implementations, and feature tests. Each edge carries project-relative source evidence and an exact or inferred confidence value.

--feature keeps the selected feature and its directly connected nodes, which makes cross-feature policy and shared-port dependencies visible without loading the entire application. --kind accepts a comma-separated projection of node kinds. A default job, task, tool, or evaluation target whose module does not exist is skipped; an explicitly overridden target must load. The default route target is app.server.routes:api_routes; override it with --routes module:attribute. The default job target is app.server.jobs:jobs; override it with --jobs module:attribute. The default tool target is app.server.tools:tools; override it with --tools module:attribute. The default evaluation target is app.server.evaluations:runner; override it with --evaluations module:attribute.

The JSON result also embeds tenchi doctor diagnostics and unresolved source relationships. Agents should inspect both before editing and use stable node IDs and source locations to choose the files involved in a change. See coding agents for the complete workflow across map, make, check, and OpenAPI compatibility.

Manage durable job messages

uv run tenchi jobs
uv run tenchi jobs --json
uv run tenchi jobs --diff jobs.json
uv run tenchi jobs --diff-ref origin/main --snapshot jobs.json
uv run tenchi jobs --check jobs.json
uv run tenchi jobs --write jobs.json

The default target is app.server.jobs:jobs; override it with --jobs module:attribute. The manifest contains stable names, descriptions, and producer-to-consumer input schemas without payloads or handler results. --check detects exact drift. --diff and --diff-ref reject removed jobs, narrower accepted payloads, and changes the analyzer cannot prove safe. Use --diff-format json for a versioned compatibility result. See Background jobs for rollout rules around stored messages.

For first adoption only, --allow-missing-baseline permits a --diff-ref whose commit predates jobs.json and records that fact as metadata.

Manage application-tool contracts

uv run tenchi tools
uv run tenchi tools --json
uv run tenchi tools --diff tools.json
uv run tenchi tools \
  --diff-ref origin/main \
  --snapshot tools.json
uv run tenchi tools --check tools.json
uv run tenchi tools --write tools.json

The default target is app.server.tools:tools; override it with --tools module:attribute. Plain output is the canonical portable manifest. --json wraps that manifest with the application root and agent protocol version for automation.

--check is an exact drift check. --diff and --diff-ref classify changes against the historical baseline and fail on breaking or unknown changes. A Git ref supplies a meaningful historical baseline even when the working branch updates its snapshot. Use --diff-format json for the versioned compatibility result. See Application tools for the compatibility rules.

Manage OpenAPI

uv run tenchi openapi
uv run tenchi openapi --diff openapi.json
uv run tenchi openapi --diff-ref origin/main --snapshot openapi.json
uv run tenchi openapi --check openapi.json
uv run tenchi openapi --write openapi.json

Common metadata options are --title, --version, --description, and --security. --diff-ref reads --snapshot (default openapi.json) from a Git commit instead of the working tree. See OpenAPI and compatibility for the safe baseline workflow.

Standalone openapi, check, and verify all default to app.server.routes:api_routes and discover literal OPENAPI_* declarations from that module. Common overrides are --routes, --title, --version, --description, and --security.

When --diff-format json is selected, the versioned result includes the application root, baseline label, compatibility status, severity counts, and classified changes.

Check architecture

uv run tenchi doctor
uv run tenchi doctor --json

Doctor validates the canonical application structure, dependency direction, and authorization consistency. Findings include a stable code, severity, file, line, and message in the versioned JSON result. Application source directories must use real files and directories rather than symlinks; Doctor rejects links instead of scanning different files on different Python versions.

Run every check

uv run tenchi check
uv run tenchi check --json

Check runs Ruff format, Ruff lint, Pyright, pytest, doctor, and the exact OpenAPI, job-message, application-tool, and evaluation-policy snapshot checks. A job, tool, or evaluation snapshot step is omitted only when neither its default composition module nor its snapshot file exists; a snapshot without its module, or a module without its snapshot, still runs and fails as drift. Every step runs even when an earlier one fails. Human output shows a compact status list; JSON includes stable step names, commands, exit codes, durations, and bounded failure output. Use --timeout to change the per-step limit.

OpenAPI defaults come from literal top-level OPENAPI_TITLE, OPENAPI_VERSION, optional OPENAPI_DESCRIPTION, and optional OPENAPI_SECURITY declarations in the module selected by --routes; command flags override them. The route target defaults to app.server.routes:api_routes, and the snapshot defaults to openapi.json. The tool target defaults to app.server.tools:tools, and its snapshot defaults to tools.json. The job target defaults to app.server.jobs:jobs, and its snapshot defaults to jobs.json. Override them with --jobs and --job-snapshot. The evaluation target defaults to app.server.evaluations:runner, and its snapshot defaults to evaluations.json. Override them with --evaluations and --evaluation-snapshot.

Verify a completed change

uv run tenchi verify --base-ref origin/main
uv run tenchi verify --base-ref origin/main --json
uv run tenchi verify --base-ref origin/main \
  --change-plan .tenchi/changes/create-note.json --json

Verify produces one receipt for the finished source tree. It runs tenchi check, rejects application-map diagnostics and unresolved relationships, and compares the generated OpenAPI document, durable job-message manifest, application-tool manifest, and evaluation-policy manifest with the snapshots at the selected Git ref. The receipt records the baseline commit resolved from --base-ref, so all four compatibility reports use the same historical state even if the named ref moves later.

The receipt also records source.head_commit, source.tree_digest, and source.dirty for the application root. The digest covers tracked files, executable modes, symlink targets, tracked deletions, and nonignored untracked files. Tenchi captures it before application-owned checks or imports, rechecks it after every such stage, and fails with a source error if the tree remains changed at a checkpoint. This prevents one receipt from combining checks run against different source states. Git environment variables cannot redirect capture to another checkout. Ignored runtime files do not affect the digest; ignore local caches, databases, and logs that application commands are expected to create.

When --change-plan PATH is present, the receipt also verifies the plan's baseline, generated files, incomplete markers, exact contract and use-case registration, the accepted contract-derived signature, route bindings, and a direct dependency from the exact generated test function. Keep that function's name when replacing its failing body. Verification requires pytest to collect at least one invocation and report every invocation as passed; skipped, xfailed, xpassed, deselected, failed, errored, uncollected, or ambiguous results fail the receipt. The plan is read before and after project-owned commands so a mid-verification mutation fails. The change-plan result supplements the normal checks and compatibility reports; it does not evaluate business semantics or test quality.

The application root may contain a repository-owned tenchi.toml:

schema_version = 1

[verify]
check = true
architecture = true
openapi = true
jobs = true
tools = true
evaluations = true

true makes the evidence required. false requests a deliberate skip, and an omitted key records the current requirement as not_configured. A stage is actually skipped or not_configured only when the historical policy did not require it too; otherwise the historical requirement remains enforced and its evidence reports passed, failed, or not_verifiable. Generated applications declare check, architecture, and openapi; tenchi new --full declares all six. A stage omitted from tenchi.toml while its composition module exists is a verification error, so adopting a capability means declaring its stage in the same change; false remains a deliberate skip. An application without tenchi.toml uses Tenchi's built-in policy: check, architecture, and openapi are required, and jobs, tools, and evaluations are required while their default composition module exists and not_configured otherwise. The current policy judges the working tree; the historical policy judges the baseline commit, so deleting a module cannot quietly drop a requirement the baseline had.

check means the complete local tenchi check loop, including exact drift checks for every checked-in snapshot. openapi, jobs, tools, and evaluations mean their separate historical compatibility comparisons against the selected Git baseline. Disabling one historical comparison does not remove its exact snapshot check while check remains required.

Verify compares the current policy with tenchi.toml at the resolved baseline. Changing a required stage to false or removing its key is incompatible. Tenchi still runs a stage required by either policy, so a change cannot disable the check that would report its own weakening. Adding a repository policy is safe only when it preserves the built-in requirements; removing a committed policy fails closed. Invalid TOML, unknown stages, unsupported schema versions, and unreadable historical policies also fail without suppressing the strict built-in stages. Tenchi reads the policy again after every project-owned stage has completed and rejects the receipt if a test or import changed it while verification was running.

The structured receipt gives every stage its current and historical requirement, whether it was enforced, and one of passed, failed, skipped, not_configured, or not_verifiable. policy.ok is true only when the policy is compatible and all enforced evidence passed.

Use the pull request base, previous push, or previous release as the base ref. The option is required: using the current branch snapshot could hide a breaking change when code and its updated snapshot are committed together. The command exits non-zero for a failed check, incomplete architecture evidence, a breaking or unknown boundary change, or a baseline that cannot be read.

When a job, tool, or evaluation composition module did not exist at the baseline, verify treats the missing historical snapshot as a first adoption automatically and records a job manifest baseline, tool manifest baseline, or evaluation manifest baseline metadata change. The overrides below cover a module that did exist at the baseline while its snapshot did not. If the selected ref predates the application's first jobs.json in that situation, pass --allow-missing-job-baseline once and confirm the job result includes a job manifest baseline metadata change. If it predates the application's first evaluations.json, pass --allow-missing-evaluation-baseline once and confirm the evaluation result includes an evaluation manifest baseline metadata change. Other boundaries follow their own configured requirements. Do not use these overrides to bypass an existing historical snapshot at a renamed or mistyped path.

--snapshot, --job-snapshot, --tool-snapshot, --evaluation-snapshot, and the route, task, job, tool, evaluation, and OpenAPI metadata options override the generated application conventions. Verify never updates snapshots. Because it runs the application's tests and validation commands, those commands retain their normal side effects and per-step timeout.

Verify loads app.server.evaluations:runner for the architecture check and the policy comparison but does not run evaluators. Use --evaluations module:attribute when the application uses another composition target.

Verify the deployment environment

uv run tenchi preflight
uv run tenchi preflight --json
uv run tenchi preflight --timeout 3

Preflight discovers app.server.preflight:checks and runs its read-only async observations concurrently. Each check keeps its declared timeout; --timeout can only cap those limits. Results expose stable names, descriptions, statuses, durations, and failure codes while discarding dependency values and exception messages. The command exits non-zero when any check fails or times out.

Use --preflight module:attribute to override the declaration target. See deployment preflight for declarations, dependency patterns, redaction, and rollout placement.

Run AI evaluations

uv run tenchi eval list
uv run tenchi eval list --json
uv run tenchi eval snapshot --diff evaluations.json
uv run tenchi eval snapshot --diff-ref origin/main \
  --snapshot evaluations.json
uv run tenchi eval snapshot --check evaluations.json
uv run tenchi eval snapshot --write evaluations.json
uv run tenchi eval run
uv run tenchi eval run support.answer_quality --json

eval list discovers app.server.evaluations:runner and returns case names and schemas, metrics, thresholds, timeouts, and token or cost budgets without case inputs. eval snapshot prints, writes, checks, or compares the policy, which contains no case inputs, with a historical snapshot without invoking evaluators. Breaking and unknown changes return a non-zero status; --diff-format json returns the versioned evaluation_diff result. A missing Git snapshot fails by default. During first adoption only, pass --allow-missing-baseline and require the resulting evaluation manifest baseline metadata change; do not use it for a renamed or mistyped path. eval run opens the application lifespan, gives each case a scoped context, and exits non-zero when a case, threshold, or budget fails.

Use --concurrency to override the number of cases in flight and --timeout to tighten each case's declared timeout. Use --evaluations module:attribute to override the runner target. Evaluation execution stays separate from check and verify because it may call external models, vary between runs, and incur cost. Those commands verify only the declared policy. See AI evaluations for declarations, scoring, redaction, and deployment guidance.

Run operational tasks

uv run tenchi task list
uv run tenchi task list --json
uv run tenchi task run projects.repair_members \
  --input '{"dry_run": true}'
uv run tenchi task run projects.repair_members \
  --input '{"dry_run": false}' \
  --json

task list discovers app.server.tasks:runner and reports every task's input and output JSON Schema. task run validates input, opens the application lifespan and scoped context, invokes the use case, validates its result before the context commits, and returns a non-zero exit status for failure results. Use --tasks module:attribute to override the runner target.

See Operational tasks for declarations, composition, dry-run design, failure semantics, and MCP access.

Serve coding-agent tools over MCP

uv run tenchi mcp
uv run tenchi mcp --root path/to/application

This command exposes repository inspection and validation—not the application's ToolGroup. MCP support is installed through the tenchi[mcp] extra. Generated applications include it as a development dependency and register the default command in .mcp.json. --routes, --api-routes, --preflight, --evaluations, --tasks, --jobs, --tools, --snapshot, --job-snapshot, and --tool-snapshot override the conventions captured by the server when it starts. --title, --version, --description, and --security override discovered OpenAPI metadata for the diff and check tools. Pass --allow-task-runs only when the connected agent may perform operational writes; task discovery remains available without it. Pass --allow-evaluation-runs only when the connected agent may call providers and consume evaluation budgets; evaluation discovery remains available without it. The command uses stdio and waits for an MCP client; it does not start an HTTP listener.

See connect an MCP-aware coding agent for tool behavior, safety, and client configuration.

Run development

uv run tenchi dev
uv run tenchi dev --host 0.0.0.0 --port 8080
uv run tenchi dev --no-reload

The default ASGI target is app.server.asgi:app. Override it with --app module:attribute. Production deployments should invoke an ASGI server directly rather than the development command.