# Workgraph — full documentation (generated) This file concatenates the README and every doc for one-shot LLM ingestion. Source of truth: https://github.com/moul/workgraph ================================================================ # FILE: README.md ================================================================ # Workgraph > A Git-native work graph for humans and agents. Durable tasks, decisions, and > cross-repo agent handoff — as plain Markdown + JSON in a Git repo, no daemon. Workgraph is **not where agents think**. It is **where humans and agents agree on durable work state**. ## Getting started Paste this to your coding agent: ```text Hey Claude, let's start using https://moul.github.io/workgraph/llms.txt ``` It installs the CLI, creates your private git-backed control repo, and starts using it. Prefer to drive it yourself? The docs below cover every path. ## Docs - **[How it works](docs/how-it-works.md)** — the model in five minutes (start here). - **[Getting started](docs/getting-started.md)** — run your own private instance, step by step. - **[Usage](docs/usage.md)** — CLI / HTTP API / MCP, copy-paste for humans and agents. - **[Web interface](docs/web-interface.md)** — the read-only dashboard (`workgraph ui --serve`). - **[Spec](docs/spec.md)** — the file format and protocol. - **[HTTP API](docs/api.md)** · **[MCP](docs/mcp.md)** — the gateway surfaces in detail. - **Agents:** [`llms.txt`](https://moul.github.io/workgraph/llms.txt) — the entry point. - [`AGENTS.md`](AGENTS.md) / [`CLAUDE.md`](CLAUDE.md) — the operating contract `workgraph init` scaffolds into every control repo. Jump straight to the common tasks: - [Install](docs/getting-started.md#install) · [Run with Docker, no Go](docs/getting-started.md#run-with-docker-no-go) - [Create your private control repo](docs/getting-started.md#create-your-private-control-repo) - [Serve for cloud & mobile agents](docs/getting-started.md#serve-for-cloud--mobile-agents) - [Adopt an existing project](docs/getting-started.md#adopt-an-existing-project) ## License Apache-2.0 OR MIT (see [`LICENSE`](LICENSE)). ================================================================ # FILE: docs/getting-started.md ================================================================ # Getting started — run your own private instance ## Mental model: three kinds of repo Workgraph deliberately keeps **the tool**, **your work graph**, and **the code you work on** in separate repositories. Don't put them in one place. ```text moul/workgraph the tool + reference (install the binary from it) your control repo your durable work state (private; workgraph init creates it) target repos the code you change (capsules only, never rewritten) ``` - **`moul/workgraph`** (this repo) is the **reference**: source, tests, docs, example. You install the binary from it — you don't put your tasks here. - **Your control repo** is a **separate, private** repo holding your projects, items, decisions, and event log. `workgraph init` creates it; every mutation commits and pushes to it. - **Target repos** are the codebases you work on. Workgraph never rewrites their `CLAUDE.md`/`AGENTS.md`; it only drops a task-scoped run capsule under `.workgraph/runs/` when you launch a run there. ## Install Requires **Go 1.23+** and **git**. ```bash go install github.com/moul/workgraph/cmd/workgraph@latest # or from a clone of this repo: make install (stamps the version from git) workgraph version ``` Ensure `$(go env GOPATH)/bin` is on your `PATH`. ## Run with Docker (no Go) Prefer a container? Mount your control repo as a volume — no Go toolchain needed: ```bash docker run --rm -v "$PWD":/workspace ghcr.io/moul/workgraph ready docker run --rm -p 8080:8080 -v "$PWD":/workspace ghcr.io/moul/workgraph serve --addr :8080 ``` The image bundles `git`. For mutations, pass your identity so commits are attributed: ```bash docker run --rm -v "$PWD":/workspace \ -e GIT_AUTHOR_NAME=you -e GIT_AUTHOR_EMAIL=you@example.com \ -e GIT_COMMITTER_NAME=you -e GIT_COMMITTER_EMAIL=you@example.com \ ghcr.io/moul/workgraph new task "Try it" --project demo --ready ``` ## Create your private control repo Initialize locally, then create the private GitHub repo from it in one step: ```bash workgraph init ~/p/workgraph-state cd ~/p/workgraph-state git add -A && git commit -m "init workgraph workspace" gh repo create /workgraph-state --private --source=. --remote=origin --push ``` From here, every `workgraph` mutation auto-commits **and pushes** to your private repo: ```bash workgraph new project "My Stuff" --target-repo git@github.com:/hermes.git workgraph new task "Try workgraph" --project my-stuff --ready workgraph ready ``` ### Alternative: start from an empty GitHub repo ```bash gh repo create /workgraph-state --private git clone git@github.com:/workgraph-state ~/p/workgraph-state cd ~/p/workgraph-state git checkout -B main workgraph init . # detects the existing git repo, skips git init git add -A && git commit -m "init workgraph workspace" && git push -u origin main ``` ## Local-only (no GitHub) Workgraph needs no remote. `workgraph init` runs `git init` for you; mutations commit locally. Add a remote whenever you want. ```bash workgraph init ~/p/workgraph-state cd ~/p/workgraph-state git add -A && git commit -m init # first commit; mutations commit after this workgraph new project "Solo" ``` Use `--no-push` (or `--offline`) on mutations until you add a remote. ## Daily use ```bash cd ~/p/workgraph-state workgraph ready # next actionable items (the daily command) workgraph attention # where you must intervene workgraph show # inspect one object workgraph run --repo ../hermes --agent claude --print # start a round + capsule workgraph finish RUN-... --status review --pr 123 workgraph validate # deterministic checks ``` Run from anywhere with `-C ~/p/workgraph-state`, or set `WORKGRAPH_DIR=~/p/workgraph-state`. Full command reference and the HTTP/MCP surfaces: [usage.md](usage.md). ## Serve for cloud & mobile agents Run the gateway against your control repo so cloud agents reach it over HTTPS/MCP without cloning anything: ```bash cd ~/p/workgraph-state workgraph serve --addr :8080 --base-url https://wg.example.com --bootstrap-admin-token workgraph token create --kind run --run RUN-... \ --scope runs:context,runs:event,runs:finish --worker agent:claude # -> paste http:///t/wg_tok_... into the agent ``` Put it behind TLS before exposing it. Tokens are hashed at rest and never stored in Git. See [api.md](api.md) and [mcp.md](mcp.md). ## Multi-machine Assume clones go stale. Every mutating command fetches first and requires a fast-forward. On divergence it refuses with a repair hint; pass `--branch-on-conflict` to write to a `workgraph/conflict/` branch instead of overwriting, or `--offline` to defer the sync. Never last-writer-wins. ## Adopt an existing project ```bash workgraph discover --repo ../hermes # non-invasive survey workgraph import github --repo moul/hermes --issues open # issues -> triage items ``` Imports are idempotent by `source_ref` and never mark work `ready` for you. ================================================================ # FILE: docs/spec.md ================================================================ # Workgraph file-format & protocol specification (v0.1) Workgraph's source of truth is a Git repository of Markdown + YAML + JSONL. Everything else is a projection. This document is the contract. ## Planes ```text source plane: Markdown objects + events JSONL (authoritative) index plane: deterministic JSONL indexes + optional SQLite cache access plane: HTTPS API + remote MCP + tokenized read page adapter plane: launch capsules + optional CLAUDE/AGENTS helpers ``` Only the source plane is authoritative. If current state (frontmatter) and event history disagree, **frontmatter wins** and validation reports the drift. Events are never replayed blindly to reconstruct truth. ## Repository contract ```text workgraph.yaml # workspace identity and defaults ontologies/workgraph.yaml # the ontology manifest (validation contract) projects//PROJECT.md # canonical project objects projects//items/*.md # canonical item objects projects//decisions/*.md inbox/*.md # project-less inbox items workers/*.md # worker profiles events/YYYY-MM.jsonl # append-only semantic event log indexes/*.jsonl # deterministic generated compact indexes .workgraph/ # ignored cache + local runtime state (tokens, sqlite) ``` ## Identity An ID is `-` (`ITM-01K4A2...`), immutable, creation-time-sortable, safe to mint concurrently. Prefixes: `PRJ`, `ITM`, `DEC`, `RUN`, `EVT`, `TOK`, `WKG`. Workers use the readable `worker:` form. Prefixes are cosmetic — parsers must not trust them for dispatch beyond a hint. Invariants: ```text filename starts with the id (except PROJECT.md and workers/.md) frontmatter id matches filename id links use ids, never paths indexes include both id and path ``` The CLI resolves references by full id, case-insensitive id fragment, filename slug, title slug, or project directory name — but always writes and prints the full id. ## Objects Four types: `project`, `item`, `decision`, `worker`. Required fields on every object: ```yaml id: ITM-01K... type: item title: Human title status: ready created_at: 2026-08-04T21:30:00+02:00 updated_at: 2026-08-04T21:30:00+02:00 ``` Object **version** is derived, never stored: it is the Git blob id of the file (`blob:`, identical to `git hash-object`), emitted into indexes and run capsules. Do not put `version` in frontmatter. Items add `kind`, `project`, `priority`, `owner`, `depends_on`, `blocked_by`, `target_repo`, `parallel_policy`, and more (all optional, all flat). Unknown frontmatter keys are preserved through a rewrite, never dropped. Body sections are canonical extraction points for capsules and summaries: ```text ## Goal ## Outcome ## Context ## Acceptance criteria ## Constraints ``` ## Status vocabulary (tiny by design) ```text inbox triage ready in_progress blocked review done cancelled archived ``` Extra status names are a tax on every agent. Nuance lives in derived attention reasons and events, not in new statuses. ## Rounds and events ```text item = the durable issue/problem round = one worker's bounded attempt to move the item forward (RUN-...) event = one immutable fact inside or around that attempt ``` An item can have many rounds without spawning new items. A `single` `parallel_policy` item must not have two active owners; the later claimant fails expected-version or commits to a conflict branch. Events are append-only JSONL facts: ```json {"id":"EVT-...","at":"...","actor":"agent:claude","action":"run.finished","object":"ITM-...","run":"RUN-...","status":"review","summary":"Opened PR #123."} ``` Actions come from the ontology (`item.*`, `run.*`, `decision.*`, `project.*`, `token.*`). Unknown actions are validation errors. ## Indexes Deterministic, diff-friendly, always rebuildable, committed by default: ```text indexes/objects.jsonl # one compact line per object, with version + summary indexes/links.jsonl # {from, rel, to} indexes/runs.jsonl # one line per work round indexes/attention.jsonl # derived human-attention queue ``` The validator warns when a committed index is stale (`workgraph index` fixes it). The human-debuggable bar: ```bash jq -r 'select(.status=="ready") | [.id,.title,.target_repo] | @tsv' indexes/objects.jsonl ``` ## Attention (mostly derived) Rules produce attention so stale manual flags cannot rot: ```text blocked_without_blocked_by review_assigned_to_human missing_dependency lease_expired new_triage_item proposed_decision blocked_by_human manual_override (honored until attention_until) ``` ## Launch capsules A run capsule is a task-scoped contract copied into the target repo at `.workgraph/runs/RUN-.../`: ```text RUN.json PROMPT.md TASK.md PROJECT.md LINKS.md RULES.md RESULT.md ``` Budgets keep it readable: `PROMPT.md ≤ 200` lines, `TASK.md ≤ 300`, `PROJECT.md ≤ 150`, `LINKS.md ≤ 100`. The capsule never copies the target repo's own CLAUDE.md/AGENTS.md — those say *how* to work there; the capsule says *what* and *why*. ## Git behavior Every mutating command: fetch → require fast-forward (unless `--offline` or `--branch-on-conflict`) → verify expected version → write object + event → rebuild committed indexes → commit → push. No silent last-writer-wins. ## Validation (stricter than search) `workgraph validate` detects duplicate IDs, missing required fields, unknown vocabulary (via the ontology), broken references, dependency and parent cycles, filename/id mismatches, malformed YAML, invalid dates, expired leases, stale indexes, and obvious secrets. Errors block; warnings inform. ## Permissions Worker profiles declare `capabilities` and `requires_review_for`. Enforcement is CLI-level in v0 — the point is to make dangerous operations visible and testable. Trust remains Git-based: a human can review every commit. Agent-created items default to `triage` unless created as a child of an active item with `--ready`. ## Secrets The control repo may be pushed to GitHub. Secret *values* never belong in source or capsules; secret *names*, env var names, and vault paths are fine. Validation includes a lightweight secret scan. ================================================================ # FILE: docs/api.md ================================================================ # Workgraph HTTP gateway API (v0) The gateway is a thin, Git-backed service served by the same `workgraph` binary. It owns the annoying parts (token auth, expected-version checks, context packet generation, event append) but never the source of truth — the Git repo does. ```bash workgraph serve --addr :8080 --repo /srv/workgraph/state --bootstrap-admin-token ``` Every write goes through the same core mutation package as the CLI. There is no UI-only, MCP-only, or CLI-only write path. ## Auth All `/api/v0/*` routes require a scoped bearer token: ```http Authorization: Bearer wg_tok_... ``` Worker identity comes from the authenticated token, never a caller-supplied field. A run-scoped token may only touch its own run. Token values are shown once and only hashes are stored (never in Git). ## Endpoints ```text GET /api/v0/items?status=ready&project=PRJ-... items:read POST /api/v0/items items:create body: {"Title","Project","Kind","Ready"} GET /api/v0/items/{id}?include_body=true items:read POST /api/v0/items/{id}/runs runs:create GET /api/v0/runs/{id}/context runs:context POST /api/v0/runs/{id}/events runs:event body: {"Action","Message"} POST /api/v0/runs/{id}/finish runs:finish body: {"Status","Summary","PR"} POST /api/v0/runs/{id}/block runs:block body: {"Reason"} GET /api/v0/search?q=... items:read ``` Pages (no auth): `/`, `/docs/api`, `/docs/mcp`, `/docs/subagents`, `/setup/mcp`. Tokenized page: `/t/{token}`. MCP: `POST /mcp`. Admin: `POST /admin/tokens`. ## Examples ```bash curl -H "Authorization: Bearer $TOK" http://localhost:8080/api/v0/items curl -H "Authorization: Bearer $TOK" \ http://localhost:8080/api/v0/runs/RUN-01K.../context curl -H "Authorization: Bearer $TOK" -X POST \ -d '{"Status":"review","Summary":"Opened PR","PR":"github:moul/hermes#123"}' \ http://localhost:8080/api/v0/runs/RUN-01K.../finish ``` ## Tokens Mint from the CLI or the admin endpoint. Kinds map to default TTLs: ```text run token 24h scoped to one run/context/update flow item token 7d scoped to one item workspace — broad coordinator access, explicit expiry required ``` ```bash workgraph token create --kind run --run RUN-01K... \ --scope runs:context,runs:event,runs:finish --worker agent:claude workgraph token list workgraph token revoke TOK-01K... ``` ```bash curl -H "Authorization: Bearer $ADMIN" -X POST \ -d '{"kind":"run","run":"RUN-01K...","scopes":["runs:context","runs:event","runs:finish"],"worker":"agent:claude"}' \ http://localhost:8080/admin/tokens ``` The response includes `token` (shown once) and a copy-paste `url` (`/t/{token}`). ## Security properties ```text expired token is rejected revoked token fails immediately read token cannot append event run token cannot touch another run token value is never stored in Git every token has scopes + expiry worker identity comes from the token, not the request body ``` ================================================================ # FILE: docs/mcp.md ================================================================ # Workgraph MCP surface MCP is a compact API over the same core, not a richer protocol. The same JSON-RPC 2.0 handler serves the remote HTTP endpoint (`POST /mcp`) and the local stdio server (`workgraph mcp`). ## Install Local stdio server: ```bash workgraph mcp install claude # prints: claude mcp add workgraph -- mcp workgraph mcp install codex ``` Remote (via the gateway) — see `/setup/mcp?token=...`: ```bash claude mcp add --transport http workgraph https://host/mcp \ --header "Authorization: Bearer wg_tok_..." ``` ## Tools Fewer than ten, by design — too many tools hurt tool selection. ```text init workspace info + first-call hint list_items compact list; filter status/project get_item one item; include_body for full markdown create_item create (defaults to triage) create_run start a work round against an item get_run_context task-scoped context packet for a run append_run_event append an operational event finish_run finish a run, set resulting status block_run block a run with a reason search substring search over items ``` Tool results are compact by default. Full bodies require `include_body: true`. Worker identity comes from the authenticating token; in stdio mode it comes from `--actor`. ## Resources ```text workgraph://indexes/objects the objects index (jsonl) workgraph://indexes/attention the attention queue (jsonl) ``` ## Example (stdio) ```bash printf '%s\n' \ '{"jsonrpc":"2.0","id":1,"method":"initialize"}' \ '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"list_items","arguments":{"status":"ready"}}}' \ | workgraph mcp ``` ================================================================ # FILE: AGENTS.md ================================================================ # AGENTS.md — how to work in a Workgraph repository This repo is a **Workgraph control repo**. It records durable work state for humans and agents. It is not where you think; it is where you record what you did and what is true now. ## Golden rules 1. **Current state = object frontmatter.** Events explain *how* the repo got there; frontmatter wins for *what is true now*. 2. **IDs are identity.** Filenames and paths are aliases. Never trust a path as an identity; resolve by ID. 3. **Every mutation writes an event.** Prefer the CLI/MCP so the event and the object change land in one commit. Manual edits are valid but must keep `workgraph validate` green. 4. **Never invent vocabulary.** Object types, item kinds, statuses, relation types, event actions, and attention reasons all come from `ontologies/workgraph.yaml`. Unknown values are validation errors. 5. **No secrets in source.** API keys, tokens, credentials, raw production logs, private customer data — never. Secret *names*, env var names, and vault paths are fine. 6. **Deletion is rare.** Prefer `cancelled`, `archived`, `duplicate_of`, or `superseded`. Physical deletion is for scaffold-never-committed, secrets, and generated caches only. ## Choosing and starting work ```bash workgraph ready --json # compact next-actionable items workgraph show # one item, standard context workgraph run --repo --agent claude --print ``` `workgraph run` creates a run, appends `run.created`/`run.started`, and writes a **launch capsule** into the target repo at `.workgraph/runs/RUN-.../`. Read `PROMPT.md` in that capsule and complete the task. Preserve the target repo's own `CLAUDE.md`/`AGENTS.md` rules — Workgraph tells you *what* and *why*; the target repo tells you *how* to work there. ## Reporting back ```bash workgraph finish RUN-... --status review --summary .workgraph/runs/RUN-.../RESULT.md --pr 123 workgraph block RUN-... "Need production API token" ``` ## Creating work Agents may create items, but new items default to `triage` unless created as a direct child of an active item with `--ready`. Small checkboxes inside an item body are fine and need no permission — they are local implementation detail, not durable work rounds.