Quick start

This walkthrough takes you from an empty (or existing) project to a graph the engine can drive. It assumes you have the ubc CLI installed and an AI coding assistant available — GitHub Copilot or Claude Code.

Note

The ubc agent command is experimental and hidden: it works, but it does not appear in ubc --help and its behaviour may change between releases. Run ubc agent --help to see the subcommands.

Start a new project

ubc agent install bootstraps a project into the loop from a named profile (the default profile, vmodel, is the V-model described in the overview):

ubc agent install                 # scaffold the default `vmodel` profile
ubc agent install --profile vmodel

In one non-destructive pass this:

  1. writes the [workflow] process model and the need-type/link ontology into ubproject.toml (existing files are never clobbered without --overwrite);

  2. installs the profile’s AI-asset bundle into the host integration directories — authoring and review skills plus a driver command under .claude/, and a custom agent at .github/agents/workflow-author.agent.md;

  3. records every file it owns in an install manifest at .pharaoh/agent/install-manifest, so a later update can tell your edits from the profile’s.

Tip

Commit .pharaoh/ to version control. It holds ubc’s per-project agent state — the install manifest above, and (once you start reviewing) the review verdicts under .pharaoh/verdicts/. Both are durable, shared records, so commit the folder like any other source. A leading-dot directory is easy to overlook, but leaving it untracked — or gitignoring it — loses your team’s review history and makes ubc agent update and ubc agent doctor report the install as missing. Nothing rebuildable lives there: the build cache is the separate .ub_cache/ directory, which should stay gitignored.

Before you spend any tokens driving the loop, run the pre-flight check:

ubc agent doctor          # config validity + required-tool probes, as JSON

doctor fails closed on a misconfiguration (an invalid [workflow], a missing diagram renderer, a mis-wired code-trace gate) so you catch setup problems before the first authoring run.

Drive the loop

Ask the engine what to do next, author that one artefact, then confirm it closed its obligation. Repeat until next reports done.

$ ubc agent next          # no --id: infer the active stream from your git diff

It names at most one stage as JSON. Here the engine picked the reqs stage and resolved its route for the login stream it inferred from your working tree:

{
  "ok": true,
  "stage": {
    "id": "reqs",
    "produces": "req",
    "skill": "draft-requirement",
    "review": "review-requirement",
    "route": {
      "scope": "stream",
      "granularity": "per-root",
      "path": "specs/{stream}/requirements.rst",
      "feature": "login",
      "id_prefix": "REQ_",
      "resolved_path": "specs/login/requirements.rst"
    },
    "gates_to_pass": ["trace"],
    "gate": {
      "link": "traces_to",
      "up_type": "user_story",
      "min": 1,
      "direction": "both"
    },
    "id_prefix": "REQ_",
    "verdicts_dir": "/work/acme/.pharaoh/verdicts"
  }
}

So the next step is concrete: author req needs (ids prefixed REQ_) with the draft-requirement skill at the resolved_path, and the gate still to close is the trace link up to the story. The overview breaks this payload down field by field.

There are three ways to author the stage the engine names:

With your AI assistant (recommended).

In Copilot or Claude Code, invoke the driver — the installed drive-workflow skill (or the /ubc-agent-next command). It runs ubc agent next, reads the recommended skill, and authors the artefact at the reported route with the trace links the stage requires. The result is left uncommitted for you to review.

Headless, engine-driven.

ubc agent run assembles a prompt (the recommended skill + the anchor need’s context briefing + the resolved route) and executes it through the configured runner, then rebuilds and reports what was produced. Use --id <NEED_ID> to pick a stream on a clean tree:

ubc agent run --id US_LOGIN     # author the next stage for this stream
By hand.

Nothing stops you writing the .rst directive (or the one-line code marker) yourself. The engine only cares about the resulting graph.

After each step, confirm the gap closed and watch the heartbeat:

ubc agent gaps --scope US_LOGIN   # structural gaps for one stream (exits non-zero if any)
ubc agent status                  # one row per stage: done / ready / blocked

When every stage is done, the feature is finished only once the combined gate is green:

ubc agent release-check --with-verdicts

Onboard an existing project

If you already have a Sphinx-Needs graph, --detect (brownfield mode) derives a drivable [workflow] from the graph you already have — the links your needs actually use, the schema, and your declared [needs.links] — instead of the blank profile defaults:

ubc agent install --detect

Each structural edge it finds becomes a trace gate; what it cannot infer from the structure alone it raises as an open question carrying the evidence — whether a metadata-only type is a real stage or just a label, which parent types a fan-in should gate on, or whether a low-coverage backward edge is a genuine gap or noise. Preview the proposal as JSON without writing anything:

ubc agent install --detect --plan

Apply your choices with --answers <file> (an id-to-choice map); the recommended default resolves every question, so answering always converges. The derived [workflow] is appended to your project’s ubproject.toml — a provenance marker keeps re-runs idempotent, and an existing config is never clobbered. --detect exits non-zero on a project with no introspectable graph, so build your needs first.

Tip

The pharaoh-onboard skill completes this for you: an AI runs the plan, answers each open question from the structural signal, spot-checks a suspiciously empty result, and iterates to a clean, drivable workflow — onboarding interactively instead of hand-answering each question.

From there the loop is identical: ubc agent next points at whatever your graph is missing (an arch with no test, a requirement with no parent) rather than starting from an empty tree.

Keeping the profile in sync

When a new ubCode release ships an updated profile, reconcile your project against it with:

ubc agent update

For each file the manifest records as install-owned it does a three-way compare (current preset vs. recorded baseline vs. on-disk): an unedited file is updated in place, while a file you edited is preserved and reported as a conflict rather than blindly overwritten. Pass --overwrite to resolve conflicts preset-wins.