Skip to content

Anuva CLI Implementation Plan

Purpose

Build a narrow anuva command-line harness in anuva-main-video-creator using Bun, TypeScript, Commander.js, and Google zx. The CLI is the deterministic executor used by Anuva Codex skills in interactive sessions. It operates over Linear, Git/GitHub, repository Markdown/MkDocs, local Development-stage services, and an existing Cloudflare Tunnel.

This plan is the input for a separate implementation task. It does not authorize Web, Python, or Unity product implementation.

Goals

  • Give Codex small, named, typed operations instead of repeatedly composing SDK, Git, GitHub CLI, MkDocs, and cloudflared commands.
  • Make read operations cheap and machine-readable.
  • Make state changes preconditioned, idempotent where practical, approval-gated, and auditable.
  • Manage all four repository documentation previews and the current machine's Development-stage services.
  • Replace anuva-dev-docs/scripts/build-all-docs.ps1 with one anuva docs publish command while keeping canonical publication manual.

Non-goals

  • A generic shell wrapper, task runner, YAML workflow interpreter, plugin host, or autonomous orchestrator.
  • Product reasoning, issue-scope generation without Codex review, code generation, PR review judgment, or unattended background work.
  • Cloudflare route/Access policy provisioning.
  • Codex Goals, Symphony, automated browser-agent testing, Early Users deployment, or Production infrastructure.
  • Replacing repository-native test commands or Playwright.

Technology decisions

Concern Choice Rationale
Runtime/package/test Bun + TypeScript One fast local toolchain for a Windows-first CLI and built-in test runner.
Command tree/help Commander.js Strict options, nested subcommands, generated help, and async actions via parseAsync.
Finite child commands Google zx Readable, safely interpolated calls to git, gh, mkdocs, and cloudflared; centralized PowerShell selection on Windows.
Long-lived processes Bun.spawn behind the same process adapter Persistent MkDocs/services/tunnel processes need PID/log ownership across CLI invocations.
Linear @linear/sdk Strongly typed official SDK for reads and mutations.
GitHub GitHub CLI (gh) Reuses existing user authentication and provides PR/check/merge primitives.
Validation Zod plus TypeScript types Runtime validation for config, manifests, SDK normalization, receipts, and JSON output.
YAML yaml package Machine configuration only; never executable workflow definitions.

Use zx only through an internal adapter. Alias its $ import clearly (for example zx$) so it is not confused with Bun Shell. Interpolate each argument as data; never concatenate Linear text, file paths, branch names, or user values into a raw shell program.

Repository layout

anuva-main-video-creator/
  package.json
  bun.lock
  tsconfig.json
  src/
    cli.ts
    commands/
      doctor.ts
      context.ts
      linear/
        issue-get.ts
        issue-list-ready.ts
        issue-start.ts
        issue-submit.ts
        issue-complete.ts
        change-complete.ts
        change-create-implementation-issues.ts
      work/
        start.ts
      pr/
        create.ts
        inspect.ts
        checks.ts
        merge.ts
      docs/
        ensure.ts
        status.ts
        validate-indexes.ts
        wait.ts
        links.ts
        stop.ts
        publish.ts
      dev/
        start.ts
        status.ts
        logs.ts
        stop.ts
    core/
      config.ts
      context.ts
      errors.ts
      output.ts
      confirmation.ts
      receipt.ts
      redaction.ts
      paths.ts
      lock.ts
    adapters/
      linear.ts
      git.ts
      github.ts
      process.ts
      mkdocs.ts
      cloudflare.ts
      filesystem.ts
      health.ts
    docs-publisher/
      repositories.ts
      build.ts
      copy.ts
      index-page.ts
      linear-status-page.ts
      git-publish.ts
    schemas/
      development-config.ts
      implementation-issues.ts
      result.ts
      process-state.ts
  tests/
    unit/
    integration/
    contract/
    fixtures/
      linear/
      git/
      mkdocs/
      publisher/

Keep command handlers thin. They parse input, load context, call one application service, and render its result. SDK and process details stay behind adapters so tests can run without live Linear, GitHub, Cloudflare, or Unity access.

Command and output conventions

Global options

anuva [--config <path>] [--json] [--verbose] [--no-color] <command>

Defaults:

  • configuration: %APPDATA%\Anuva\development.yaml;
  • process state: %LOCALAPPDATA%\Anuva\state\processes.json;
  • receipts/logs: %LOCALAPPDATA%\Anuva\logs\;
  • repository detection: nearest Git root matched to the configured registry.

JSON envelope

{
  "schemaVersion": 1,
  "ok": true,
  "operation": "docs.wait",
  "data": {},
  "warnings": [],
  "receipt": {
    "id": "20260714T102030Z-docs-wait-ab12",
    "startedAt": "2026-07-14T10:20:30Z",
    "completedAt": "2026-07-14T10:20:31Z"
  }
}

Never place secrets, full process environments, Linear tokens, tunnel credentials, or database URLs in output or receipts.

Exit codes

Code Meaning
0 Success or already in desired idempotent state
2 Invalid command input or schema
3 Missing/invalid configuration or repository context
4 Authentication/authorization failure
5 Precondition or state-transition failure
6 Required interactive confirmation missing
7 External command/service failure
8 Partial mutation requiring recovery
9 Timeout/health-check failure

Mutation protocol

Every state-changing operation must:

  1. read and validate current state;
  2. calculate and display a dry-run plan;
  3. require --confirm for execution;
  4. acquire a scoped lock to prevent duplicate concurrent mutation;
  5. perform the minimum external changes;
  6. re-read and verify the resulting state; and
  7. return a receipt plus a recovery instruction for partial failure.

--confirm proves only that the caller selected the execution form. Codex skills must still obtain explicit user approval at workflow boundaries.

Configuration schema

schemaVersion: 1
machine: machine1
devRoot: C:\\Anuva\\dev

repositories:
  anuva-main-video-creator:
    path: C:\\Anuva\\dev\\anuva-main-video-creator
    github: Shoonya-Game-Technologies/anuva-main-video-creator
    docsPort: 4001
    docsUrl: https://main1.girishd.com
  anuvax-cms:
    path: C:\\Anuva\\dev\\anuvax-cms
    github: Shoonya-Game-Technologies/anuvax-cms
    linearRepositoryLabel: anuvax-cms
    docsPort: 4002
    docsUrl: https://web1.girishd.com
  anuva-python-server:
    path: C:\\Anuva\\dev\\anuva-python-server
    github: Shoonya-Game-Technologies/anuva-python-server
    linearRepositoryLabel: anuva-python-server
    docsPort: 4013
    docsUrl: https://python1.girishd.com
  anuva-unity-video-creator:
    path: C:\\Anuva\\dev\\anuva-unity-video-creator
    github: Shoonya-Game-Technologies/anuva-unity-video-creator
    linearRepositoryLabel: anuva-unity-video-creator
    docsPort: 4004
    docsUrl: https://unity1.girishd.com

linear:
  teamKey: ANU
  states:
    backlog: Backlog
    ready: Ready
    inProgress: In Progress
    inReview: In Review
    done: Done
    canceled: Canceled
  labels:
    repositoryGroup: Repository

github:
  branchPrefix: codex/
  defaultRemote: origin

tunnel:
  name: anuva-machine1
  tokenFile: C:\\Users\\<user>\\AppData\\Local\\Anuva\\secrets\\cloudflared-anuva-machine1.token

services:
  webapp:
    repository: anuvax-cms
    command: [bun, run, dev]
    port: 3000
    healthUrl: http://127.0.0.1:3000/api/health
    publicUrl: https://anuva1.girishd.com
  python:
    repository: anuva-python-server
    command: [python, -m, anuva_server]
    healthUrl: http://127.0.0.1:8000/health
  unity:
    mode: availability-check
    editorPath: C:\\Program Files\\Unity\\Hub\\Editor\\<version>\\Editor\\Unity.exe

publisher:
  repository: anuva-dev-docs
  outputFolders:
    anuva-main-video-creator: main-video-creator
    anuvax-cms: anuvax-cms
    anuva-python-server: anuva-python-server
    anuva-unity-video-creator: anuva-unity-video-creator

Validate absolute paths, unique ports/URLs, known repository keys, expected Linear state names, a tunnel name, and an absolute tunnel token-file path. The YAML stores the path only; the tunnel token stays in its ACL-restricted file. Environment variables or tool-native credential stores supply LINEAR_API_KEY and gh authentication.

Linear operations

Read issue

anuva linear issue get ANU-310 --json

Return normalized issue ID/key/title/description, priority, state, repository label, parent/children, blockers, labels, Product Main source path, review preview URL, canonical docs URL when published, PR URL, and timestamps. Keep the SDK's internal UUID out of normal human output but retain it in typed data.

List ready issues

anuva linear issue list-ready --repository current --json

Filter server-side where the SDK supports it, then verify client-side:

  • state equals configured Ready;
  • repository label exactly matches current repository;
  • issue is not archived/canceled;
  • all blocking issues are Done; and
  • description includes Product Main link, scope, acceptance checks, docs, and verification requirements.

Return malformed candidates separately as warnings rather than silently hiding them.

Create implementation issues

anuva linear change create-implementation-issues <manifest.json> --dry-run
anuva linear change create-implementation-issues <manifest.json> --confirm

Manifest shape:

{
  "schemaVersion": 1,
  "parentIssue": "ANU-310",
  "changeId": "2026-07-14-render-stage-progress",
  "productDocs": {
    "sourcePath": "docs/changes/2026-07-14-render-stage-progress/index.md",
    "previewUrl": "https://main1.girishd.com/changes/2026-07-14-render-stage-progress/",
    "canonicalUrl": null
  },
  "issues": [
    {
      "clientKey": "unity",
      "repository": "anuva-unity-video-creator",
      "title": "Emit accurate render stage and progress events",
      "description": "...",
      "priority": "High",
      "dependsOn": []
    }
  ]
}

Validate all issues before creating any. Create in dependency order, set parent, repository label, Ready state, and backlinks, then return a clientKey → Linear ID/URL mapping. Store a deterministic marker containing Change ID + repository in the description so a retry finds and reuses already-created issues without a high-cardinality Change ID label. On partial failure, do not delete successful issues; return exact recovery steps.

Named state changes

Implement only start, submit, complete, block, and unblock if/when each is required. Avoid a generic transition --to <anything> command. start, submit, and complete check the allowed source state, required links/artifacts, and target state. block and unblock manage explicit issue relations without changing the blocked issue's lifecycle state.

linear change complete is a separate named operation. It requires every non-canceled child implementation issue to be Done, every linked PR to be merged, and a Product Main CompletionReview.md containing acceptance evidence.

Git and GitHub operations

Start work

anuva work start ANU-311 --dry-run
anuva work start ANU-311 --confirm

Preconditions: correct repository, issue ready, dependencies done, no conflicting branch, and no unsafe dirty changes. Create codex/anu-311-<slug> from configured base, then move Linear to In Progress. If the branch succeeds and Linear fails, return exit 8 with the branch name and retry command.

Standalone repository changes use a typed allowlisted path:

anuva repository-change start <intake-json> --dry-run
anuva repository-change start <intake-json> --confirm
anuva repository-change docs start <issue-id> --plan <absolute-plan> --confirm
anuva repository-change docs pr create <issue-id> --plan <absolute-plan> --preview <url> --confirm
anuva repository-change docs pr ready <issue-id> --confirm
anuva repository-change complete <issue-id> --report <absolute-report> --confirm

The skill performs read-only classification. The CLI schema cannot represent Escalate; it accepts only evidenced Not required or Required intake. Start creates or reuses one marked, top-level, repository-labeled issue directly in In Progress and reconciles codex/<issue-id>-<slug>.

Issue normalization distinguishes Product Main parents, implementation children, and marked standalone issues so their command families cannot cross. The common PR create/ready path accepts children and standalone issues. Child merge remains child-specific.

A Required standalone issue may own one bounded Product Main documentation branch and draft PR. Completion reuses normal check, review, mergeability, guarded-head, merge verification, base-update, and branch-cleanup contracts; orders implementation before documentation; records evidence; and moves Linear Done last. Identical retries reconcile supported partial states.

Pull requests

  • pr create verifies branch/issue, pushes through Git, invokes gh pr create, links the PR in Linear, and moves to In Review.
  • pr inspect returns PR URL/number/base/head/draft/review/mergeability/checks.
  • pr checks wraps gh pr checks with stable normalized results.
  • pr merge requires all configured checks, no blocking review, mergeability, completion report, exact issue/PR link, and --confirm. Use a configured merge strategy and verify the merged state.

Do not stage or commit unrelated files. Initial CLI scope may require Codex to use normal Git for selective staging/commits; a future named commit operation can be added only with a clear scope contract.

Documentation preview operations

Phase 3 makes docs preview and docs verify the installed primary contracts while retaining the Phase 2 operations below for rollback compatibility.

Preview

anuva docs preview --repository current --file <paths...> reuses a healthy owned MkDocs process across Markdown, branch, and HEAD changes. It restarts only for command, working-directory, port, configuration, health, or trusted identity changes; refuses external/conflicting listeners; performs no strict build; and returns exact local and public URLs.

Verify

anuva docs verify --repository current --file <paths...> validates root and user-facing indexes, navigation, local links, orphans, and empty sections. It runs one strict build for all requested pages and compares the served output without a timestamp or restart prerequisite. An external listener is accepted for that invocation only after every page matches and is never adopted or terminated.

Compatibility ensure and state tracking

anuva docs ensure --repository current:

  1. resolve repository and mkdocs.yml;
  2. read configured port and public base URL;
  3. check the recorded PID plus command fingerprint and OS identity;
  4. hash the Git branch, HEAD, MkDocs configuration, and docs source tree;
  5. restart the owned process with mkdocs serve -a 127.0.0.1:<port> when that generation changes, and reject any unowned listener;
  6. wait for local HTTP success; and
  7. return local/public URLs, generation, and log path.

Record PID, start time, repository, generation hashes, port, executable, and log path. Never kill a PID unless its executable/start fingerprint still matches the record.

Compatibility wait and URL mapping

docs wait requires a pre-edit timestamp and a post-edit owned generation. It builds the working tree strictly into a temporary site and compares each requested live page with that output, rejecting stale navigation and local .md links. It times out with the relevant build or comparison error. docs links maps paths under docs_dir according to MkDocs use_directory_urls; reject paths outside docs_dir with a clear message.

Compatibility index hierarchy validation

anuva docs validate-indexes --repository current recursively checks every directory under the configured docs_dir. It fails when any directory lacks an index.md, when an index is empty, or when a documentation directory is empty. The human and JSON result lists exact paths. This validator does not generate or rewrite indexes; Codex owns the overview wording and links.

Strict verification

The final workflow verification runs:

mkdocs build --strict --site-dir <unique-temp-dir> -f <repo>/mkdocs.yml

Use a temp output so validation does not dirty the repository.

Development environment operations

Start

anuva dev start --with-docs --with-tunnel performs:

  1. doctor checks;
  2. database availability check (do not automatically create/reset data);
  3. Web and Python start-or-health-check;
  4. Unity Editor/EXE availability check;
  5. all four docs ensure operations;
  6. cloudflared tunnel run --token-file <configured-token-file> if the configured tunnel is not already healthy;
  7. local health checks; and
  8. remote URL checks that distinguish Cloudflare Access redirects from origin failures.

Do not attempt to bypass email OTP. A remote 302/Access login page can prove the route is alive; authenticated content checks remain a user/browser action unless a safe service token is explicitly added later.

Stop

Stop only processes started and fingerprinted by the CLI, in this order: tunnel, Web/Python services, MkDocs. Leave PostgreSQL and Unity Editor running by default. Require --confirm for --all.

Port build-all-docs.ps1 to anuva docs publish

The existing script at C:\Anuva\dev\anuva-dev-docs\scripts\build-all-docs.ps1 currently builds all four MkDocs sites, copies output into anuva-dev-docs, generates a Material-styled root index and GitHub Project status page, and optionally commits/pushes the static site. Port that behavior into one command:

anuva docs publish
anuva docs publish --clean
anuva docs publish --skip-linear-status
anuva docs publish --push --confirm

Parameter parity

PowerShell parameter CLI replacement
-DevRoot --dev-root, default config devRoot
-OutputRoot --output-root, default configured anuva-dev-docs path
-MkDocsCommand --mkdocs-command, default mkdocs
-ProjectId Removed; Linear team/project/filter configuration replaces GitHub Project ID
-SkipProjectStatus --skip-linear-status
-Clean --clean
-PushToGitHub --push --confirm
-GitRemote --git-remote, default origin
-GitBranch --git-branch, default current branch
-CommitMessage --commit-message, default timestamped message

Required behavior parity

  1. Resolve and validate Dev Root and Output Root.
  2. Use the fixed four-repository registry and output folders.
  3. Build each repository independently with MkDocs strict mode into a unique temp directory; collect success/failure without losing earlier results.
  4. Copy generated output safely. --clean removes only the resolved destination under Output Root. Add bounded Windows retries for locked files; never weaken the root-containment checks.
  5. Discover the generated Material CSS/favicon assets and generate a root index containing repository cards and build results.
  6. Replace the GitHub Project page with a Linear status page grouped by repository and state, linking issues, Product Main change docs, and PRs. When credentials are missing or --skip-linear-status is used, generate a clear placeholder.
  7. Fail the command if any repository build fails. Do not push partial output.
  8. With --push, verify Output Root is exactly the anuva-dev-docs Git root, stage only generated publisher paths, skip commit when unchanged, commit, push the explicit branch, and return commit/remote/branch.
  9. Print a summary table in human mode and a stable result array in JSON mode.
  10. Clean temporary directories even on failure, without touching source docs.
  11. After a successful push, derive canonical URLs from the publisher mapping, verify the published pages, and idempotently synchronize the managed docs-link block on affected Linear parent and implementation issues. If publication succeeds but link synchronization fails, return a partial-failure receipt and an exact retry command; never conceal the published Git state.

Migration strategy

Keep build-all-docs.ps1 during parity development. Build a golden fixture from the current script, compare the four site trees/root index/status behavior, and run the new command manually on both development machines. After two successful manual publishes, replace the PowerShell script with a short deprecation message pointing to anuva docs publish, then remove it in a later reviewed change.

Security model

  • The command tree itself is the allowlist. No command accepts executable code, shell snippets, workflow YAML, arbitrary SDK method names, or arbitrary Linear state names.
  • Normalize repository names and issue IDs before use.
  • Resolve every filesystem mutation and prove containment under a configured root.
  • Reuse GitHub CLI authentication. Give cloudflared only the configured token-file path; never read, copy, print, or log the file contents.
  • Redact common token patterns and values sourced from secret environment names.
  • Log operation names, safe arguments, identifiers, outcomes, and recovery steps; do not log full issue descriptions when unnecessary.
  • Cloudflare Dashboard owns tunnels, routes, certificates, Access configuration, and token lifecycle. The CLI starts/checks only the configured remote-managed tunnel connector.
  • Use per-operation locks to prevent concurrent start/merge/publish races.

Test strategy

Unit tests

  • Commander parsing, required options, unknown-option rejection, help snapshots.
  • Config parsing, path containment, repository detection, branch slugging.
  • Linear normalization, readiness validation, transition table, manifest schema.
  • MkDocs path-to-URL mapping, directory URL behavior, and recursive index.md hierarchy validation.
  • JSON envelopes, exit-code mapping, redaction, and receipts.
  • Publisher root index/status HTML generation and asset selection.

Integration tests with fakes/temp repositories

  • Temp Git repositories for branch/start/dirty-worktree/idempotency cases.
  • Stub gh, mkdocs, and cloudflared executables capturing argv without a shell.
  • Fake Linear adapter for successful, rejected, duplicate, and partial mutations.
  • Real small MkDocs fixture for start/wait/strict-build behavior.
  • Process registry tests including stale/reused PID protection.
  • Publisher build/copy/clean/locked-file retry and no-change commit behavior.

Opt-in live smoke tests

Run only with explicit environment flags and test-safe Linear/GitHub artifacts:

  • doctor against the developer machine;
  • read an existing Linear issue and list ready issues;
  • inspect a known PR;
  • start/check/stop one fixture MkDocs process;
  • check the existing tunnel without changing Dashboard configuration; and
  • build canonical docs without --push.

Never run merge, completion, issue creation, service stop, or canonical push in automated tests against live systems.

Implementation phases

Phase 0: contracts and spike

  • Record the CLI ADR and command/output contracts.
  • Prove Bun can run Commander, @linear/sdk, Zod, YAML, and zx on both Windows machines.
  • Prove zx PowerShell configuration and argument interpolation with spaces and Unicode paths.
  • Capture current publisher golden output.

Exit: dependencies work on both machines and no design relies on arbitrary shell.

Phase 1: foundation and read-only operations

  • Command tree, config, errors/output/receipts, redaction, repository context.
  • doctor, context show, Linear issue get/list-ready, PR inspect/checks.

Exit: skills can discover and inspect work entirely through stable JSON.

Phase 2: docs preview

  • Process registry, docs ensure/status/wait/links/stop, strict build helper.
  • Validate exact URLs through the Product Main documentation-editing workflow.

Exit: every Markdown-changing skill can satisfy the preview contract.

Phase 3: issue handoff and work start

  • Implementation-issue manifest validation/creation and named Linear transitions.
  • work start, idempotency, locks, partial-failure receipts.

Exit: approved Product Main plans become ready repository issues, and selected issues start safely.

Phase 4: pull-request lifecycle

  • PR create/link/submit, inspect/check normalization, guarded merge, completion.

Exit: one test issue completes end to end without manual Linear/GitHub bookkeeping.

Phase 5: Development environment

  • Web/Python/Unity availability adapters, all docs servers, tunnel, health, logs, stop ordering, and machine-specific configuration.

Exit: $anuva-manage-development-environment start exposes healthy Development services and gated docs routes on either machine.

Phase 6: canonical docs publisher port

  • Build/copy/index/Linear status/manual Git publish parity.
  • Golden comparison and two-machine manual validation.

Exit: anuva docs publish --push --confirm replaces the PowerShell entry point.

Phase 7: skill rollout

  • Create/validate Product Main skills under .agents/skills/anuva/<skill-name>/SKILL.md and confirm Codex discovery from the repository root.
  • Update CMS and pilot the render-progress issue.
  • Roll learned contracts to Python and Unity.
  • Remove obsolete docs and PowerShell only after successful pilots.

Acceptance criteria

  • [ ] CLI runs on both Windows development machines from the same repository code.
  • [ ] anuva --help exposes only the reviewed named operations.
  • [ ] Every read operation has stable JSON and no secret leakage.
  • [ ] Every mutation validates state, supports dry-run where meaningful, requires confirmation, verifies the outcome, and emits a receipt.
  • [ ] Linear is the only issue/workflow control plane; no GitHub Project dependency remains.
  • [ ] GitHub PR operations reuse gh authentication and block unsafe merges.
  • [ ] All four MkDocs servers can be ensured, checked, linked, and stopped safely.
  • [ ] Documentation skills return exact machine-specific Cloudflare URLs.
  • [ ] Every directory and subdirectory under each repository docs_dir contains a non-empty index.md, enforced by anuva docs validate-indexes.
  • [ ] Development services and the named tunnel can be started/statused/logged/stopped without modifying Cloudflare Dashboard configuration.
  • [ ] anuva docs publish matches the safe build/copy/index/manual-push behavior of build-all-docs.ps1 and generates Linear status instead of GitHub Project status.
  • [ ] Unit/integration suites pass, strict Product Main MkDocs builds, and one pilot change completes through Product Main, an implementation repo, PR, and Linear.

References