A project as a repository
oto init --repolays a project out to live on GitHub. It adds an .mcp.json so Claude Code has
the query tools when it opens the repository, a CLAUDE.md saying what the repository is and what
the rule is, and six workflows:
| Workflow | Trigger | What it does |
|---|---|---|
oto-ingest |
a push to inbox/ |
claims the inbox into a run, extracts, commits the outcome, opens an issue for what it could not extract |
oto-author |
after a successful ingest | an agent, running the Claude Code Action with this engine's plugin, drafts the run's proposals on a branch oto/run-<id>, applies them through the curate gates with a ledger note, builds, evaluates, and writes runs/<id>.report.md; the workflow commits the branch and opens a pull request with that report as its description, labelled blocked if the agent stopped |
oto-checks |
a pull request | the gates as status checks: status, candidate check, pre-flight and build, vocabulary, gold set, provenance |
oto-review |
@claude in a pull request comment |
the same agent revises on the branch and pushes; the checks run again |
oto-deploy |
a merge to main |
builds the store and keeps it |
oto-actions |
a daily cron | invokes the due read-only actions through the script under .github/scripts/ (the caller, never Oto), records the responses, takes the proposals through the gates and opens a pull request |
The corpus under build/documents/ is committed in a repository, because it is an input to the build and to every review. Nothing reaches graph.json on main except through a pull request: that is the human gate in this mode, and every confirmation a playbook would ask a person for is a section of the report the pull request carries.
The unattended rules the agent follows are in pipeline-run.md. The authoring and review workflows need the repository secret ANTHROPIC_API_KEY; OTO_MODEL and OTO_ENGINE are optional repository variables.
Everywhere, the engine installs from its git repository rather than being assumed on a PATH: uvx
on a machine, pip in a workflow, one URL in repo.py overridable with --engine
or the repository variable OTO_ENGINE.
The deploy workflow has two targets. The self-hosted Neo4j is the production store (below). The query repository, when the repository variable OTO_QUERY_REPO names one and the secret OTO_QUERY_REPO_TOKEN can write to it (and the static site beside it when OTO_SITE_VIEW names a view), receives the built SQLite store on every merge through oto publish (publish.py): the database, the project's identity marked store_only, a manifest with the build sequence, hash and source commit, and a README.
Readers need access to that repository and not to the documents. oto sync --repo <it> clones or fast-forwards it into the store's cache directory (~/.<slug>-kg, or --dest), and oto serve, oto query and oto status recognise such a checkout and serve it under the project's own server name.
This is the offline and fallback path beside Neo4j: the two stores answer alike, so a reader who cannot reach the database loses freshness and nothing else. Git is the transport; the token lives in the environment for the length of the call and is never written or printed.