/client-new — a thin operator slash command over the control-plane CLI

0039-client-new-operator-command

decision read as Explain confidence verified status active 2026-06-16 owner forward-deployed-engineer
Reversibility
two-way door

DEC-0039 — /client-new operator command (thin wrapper over the control-plane CLI)

Reversibility: two-way door — the command is a thin convenience surface over the CLI (its conventions/defaults are swappable without touching the pipeline); the durable parts are the control-plane CLI it drives and the one-client-one-repo isolation it inherits.

Context

Extraction runtime architecture — the moat set the goal that "one command stands up a client's loop" (the Time-to-Live-Wiki metric), and Runtime orchestration & per-tenant control plane — the learning loop becomes a runnable system built the dossier-runtime control plane that realizes it (provision → ingest → extract → emit → commit, siloed per tenant). Subsequent work made that loop keyless and runnable on a subscription — extraction via the Claude Code CLI (Subscription-backed extraction is a first-class transport — ClaudeCodeClient (no API keys)), keyless web ingest via HttpConnector with Firecrawl as the keyed upgrade (Web ingestion — a keyless HttpConnector by default, Firecrawl wired as the premium path, and a first-class CLI web-ingest mode) — and protected its sovereignty guarantee under nesting (Fix git-per-tenant isolation when a tenant root is nested inside another repo). What was missing was an operator-facing entry point: standing up a client still meant remembering and assembling the right dossier-runtime invocation by hand. This decision adds the missing one-command surface.

The artifact is .claude/commands/client-new.md — a build-side Claude Code slash command. It is explicitly a thin wrapper: it derives a slug and dispatches to node packages/runtime/dist/cli.js (the dossier-runtime bin), which owns provisioning, ingest, extract, emit, and commit. It does not re-implement the pipeline and does not generate a bespoke per-client harness script — the CLI is the single source of truth.

Options considered

  1. A bespoke onboarding script generated per client — author a standalone harness each time a client is stood up. Rejected: it forks the pipeline logic out of the control plane, breaks single-source-of-truth, and re-creates by hand the exact manual-staging footgun Web ingestion — a keyless HttpConnector by default, Firecrawl wired as the premium path, and a first-class CLI web-ingest mode / Fix git-per-tenant isolation when a tenant root is nested inside another repo were built to retire.
  2. No command — keep invoking dossier-runtime by hand — rely on operators remembering the right flags. Rejected: the realistic agency motion ("point Dossier at a client's site") deserves a first-class, reproducible surface, not a remembered incantation; raw flags are error-prone (wrong root, forgotten --subscription, unbounded --pages).
  3. A thin slash command that drives the existing CLI (chosen). /client-new derives a deterministic slug and composes exactly the right provision / run invocation, branching on its argument. The CLI stays the single source of truth; the command is convenience + convention only.

Decision

Add /client-new as a thin operator command over dossier-runtime, with two branches on its argument.

  • Empty args → scaffold only (provision). Runs dossier-runtime provision --root clients/<slug>/tenants --client <slug> --vertical digital-experience-agency, standing up a siloed tenant: clients/<slug>/tenants/<slug>/{ okf/ (a git repo), dossier.tenant.json }.
  • A URL → scaffold AND learn (run). Runs dossier-runtime run --root clients/<slug>/tenants --client <slug> --vertical digital-experience-agency --url <URL> --pages 1 --subscription, which does an idempotent provision then the loop: keyless HttpConnector crawl (provenance = the live URL, no API key) → subscription extract (claude -p, no ANTHROPIC_API_KEY) → emit OKF → git commit into the tenant's own repo.
  • Conventions it establishes (the "why" worth capturing):
    • One client = one clients/<slug>/ workspace, tenant root at clients/<slug>/tenants/<slug>/ — a stable, legible layout for the dogfood and for real engagements.
    • Deterministic, filesystem-safe slug: slugify the client name for the empty case; for the URL case, slugify the host including the TLD (dropping the TLD would need a public-suffix list and wouldn't be deterministic). Lowercase; non-[a-z0-9] runs → a single -; trim. Idempotent on re-run (existing clients/<slug>/ is fine — provision/run re-affirm, never destroy).
    • Default vertical digital-experience-agency (the DXA reference vertical), overridable.
    • Keyless + subscription is the default web path (HttpConnector + claude -p); Firecrawl is reserved behind --connector firecrawl (needs a key) — the floor is free, the premium is opt-in (Web ingestion — a keyless HttpConnector by default, Firecrawl wired as the premium path, and a first-class CLI web-ingest mode).
    • --pages 1 default to keep the metered subscription extraction tight; raise only on request.

This operationalizes Extraction runtime architecture — the moat's "one command stands up a client's loop" into an operator-facing onboarding flow, without adding any new pipeline code.

Rationale

Consequences

  • Operator onboarding is now one command. /client-new (no args) scaffolds a tenant; /client-new <url> scaffolds and learns a site in a single step — the Time-to-Live-Wiki goal made operable.
  • No new pipeline code, no fork risk. The command adds zero extraction/ingestion/runtime logic; all behavior traces to dossier-runtime. Changing the loop changes the command for free.
  • Known caveat, documented in the command. The command's "next move" note flags that dossier-runtime site --build has a known dispatch bug and recommends run --site instead — see Fix dossier-runtime `site` subcommand dispatch (isSub omits 'site') (the isSub omission). /client-new itself drives only provision/run, so it is unaffected.
  • Two-way door. The command's conventions and defaults (workspace layout, slug rule, default vertical/pages, keyless default) are swappable without touching the pipeline; the durable commitments are the control-plane CLI it drives and the one-client-one-repo isolation it inherits.

Review

No scheduled revisit — this is a thin convenience surface. Revisit if the control-plane CLI's provision/run flag contract changes (the command's invocations would need to follow), if multi-page or non-DXA onboarding becomes the common case (defaults would shift), or if the slug convention needs a public-suffix list for real-world hosts. Confidence stays verified for the command's verified behavior; the underlying pipeline's broader validation is tracked by its own decisions.