reference

cogyard documentation

The complete technical reference for cogyard, the task system that takes you from AI chats to shipped products across every project. This page answers what it is, how it’s built, how to install and run it, and what every CLI command, task-file field, and subsystem does. Source of truth is the README and the docs/ it links.

01 What cogyard is

cogyard takes you from AI chats to shipped products — across every project you’re running at once. The agent is the worker; you are the reviewer. Tasks in, checkmarks out.

Each project gets a _tasks/ directory of markdown task files. A Node engine parses them, tracks git and worktree state, and allocates ports. An Angular portal gives you one cross-project view of what every agent is doing: backlog, claims, and which worktree owns which task.

Claude Code is the first-class driver, but the engine is agent-agnostic: the core/ data layer and the cli/ are plain Node. Anything that can call the CLI works the same way: another agent, a script, or a human. The four ideas that make parallel agents safe to run:

  • Task files: _tasks/NNN-<slug>.md, YAML frontmatter (status, deps, scope, claims) over a markdown body. The source of truth for one unit of work.
  • Collision-free claims: parallel sessions claim a task atomically before touching it, so two agents never race on the same work.
  • Worktree-aware: each agent worktree gets its own port pair and dev environment; the portal shows which worktree owns which task.
  • AI-agnostic engine: Claude Code drives it through thin skills, but the CLI is the only contract.

02 Architecture

cogyard is one repo with a clean layering: a single data layer with two thin front ends over it, plus the agent-facing hooks and integrations.

core/          data layer: frontmatter parse, registry, git, worktree, ports
cli/           cogyard.mjs · tasks.mjs · env.mjs · tunnel.mjs · usage.mjs
server/        read-only /api over core/
frontend/      Angular + PrimeNG portal (consumes /api/*)
hooks/         worktree session setup (port allocation, _tasks mount, supervisor)
integrations/  agent drivers; claude/ is the reference adapter + plugin
docs/          design notes + worktree-port, tunnel, deploy, init references

The cli/ and the HTTP API in server/ are two thin front ends over one source of truth. Both call into core/; neither reimplements its logic.

Load-bearing invariant: server/ owns no task or git logic; it imports core/. The same parse/claim/git code answers a CLI command and an API request, so they can never drift.
Architecture, local setup & invariants · docs/DEVELOPMENT.md

03 Install

cogyard has two halves you install independently: the engine (the cogyard CLI + portal, agent-agnostic) and the Claude driver (skills, commands, and hooks that let Claude Code drive the engine). You can run the engine with no agent at all.

1. The engine

$ npm i -g cogyard    # puts the `cogyard` command on your PATH
$ cogyard serve       # the portal → http://localhost:7440

Or try it without installing anything: npx cogyard serve. The published package ships the portal UI prebuilt: no build step, no clone. Verify with cogyard --help. (Hacking on cogyard itself? Clone the repo, then npm install && npm link.)

Per-machine state (the project registry, worktree port allocations, and the usage ledger) lives in ~/.cogyard/. Override the location with the COGYARD_HOME environment variable.

2. The Claude driver (optional)

The Claude Code integration ships in-repo as a plugin; the repo is its own marketplace.

  • Plugin marketplace: add this repo as a marketplace and install the cogyard plugin via the /plugin flow in Claude Code.
  • Manual install: for environments without the marketplace flow:
$ cogyard claude install          # symlink skills + commands into ~/.claude
$ cogyard claude install --rules  # also write cogyard's rules into CLAUDE.md
$ cogyard claude uninstall         # remove what install added

The install prints the settings.json SessionStart-hook block to paste in. A plugin can’t deliver always-on rules itself. Other agents (or a human) drive the same engine by calling the CLI directly; see Driving cogyard with any agent.

04 Quick start

# Turn a directory into a cogyard project (creates it + git + skeleton + wiring):
$ cogyard init my-app --kind fullstack

# …or adopt an existing folder you already have (additive-only, never overwrites):
$ cd existing-project
$ cogyard onboard . --kind single

# Confirm it's wired and portal-visible:
$ cogyard tasks doctor
$ cogyard tasks projects list

# Run the portal (API + SPA on one origin):
$ cogyard serve            # http://localhost:7440

init and onboard differ only on precondition: init for a greenfield directory (nothing on disk), onboard to adopt an existing folder. Both are:

  • Idempotent: safe to re-run; a half-wired project is repaired by running onboard again.
  • Additive-only: an existing package.json is never modified.
Full init/onboard reference · docs/PROJECT-INIT.md

05 CLI reference

One command, dispatched to per-concern modules. Each subcommand keeps its own --help.

cogyard <command> [...]

  init   <name>     create a NEW project (dir + git + skeleton + full wiring)
  onboard [path]    adopt an EXISTING folder as a project (additive-only)
  tasks  <…>        task store: sync, projects, doctor, next-id, current, analyze, mount
  env    <…>        environment + claims: detect, port-owner, claim, release
  tunnel <…>        expose a worktree's dev server at a stable hostname
  usage  <…>        token/cost ledger: collect, report, backfill
  serve  [--port N] run the portal (API + SPA) on one origin (default PORT 7440)
  claude <install|uninstall>  install the Claude driver into ~/.claude
  hook   <name>     engine hook entrypoint (session-start | validate-frontmatter)

Run cogyard <command> --help for a command’s own options.

init / onboard flags

FlagDefaultNotes
--kindrequiredsingle · fullstack · static · library; drives the skeleton + version stamping.
--storesharedshared moves _tasks/ to the ~/gitroot/_tasks/<slug> store (portal default); normal keeps _tasks/ tracked in the repo.
--remotenonegit remote for the shared task store.
--no-wiringoffskip .claude/worktree-config.json (auto-skipped for kind=library).

cogyard tasks

SubcommandWhat it does
sync pullRebase _tasks/ from the canonical’s git remote (cross-machine stores only).
sync push "<msg>"Commit (and push, if a remote exists) task edits. Use this instead of git add _tasks/: shared stores are gitignored symlinks.
projects [list]Show registered projects.
projects register / remove <slug>Manage the registry (remove never deletes files).
next-id <slug>Atomically reserve the next id and create _tasks/NNN-<slug>.md (race-safe across clones).
currentJSON of currently-claimed tasks in this repo (the /commit skill uses it to auto-tag commits).
convert [--store <p>] [--remote <u>]Convert a repo’s tracked _tasks/ to a shared store.
mountIn a worktree, recreate the base checkout’s _tasks symlink (the SessionStart hook does this automatically).
doctorAudit every registered project’s storage health.
staleness / drift <id>Drift gates: is this checkout behind the default branch / have a task’s paths changed since it was last reviewed.
analyze [--apply]Heuristic backfill for unknown-frontmatter tasks.

cogyard env

SubcommandWhat it does
detectJSON of the current environment (ports, worktree, branch).
port-owner <port>Which worktree owns a TCP port.
claim <task-file> <session-id>Atomically claim a task (refuses if claimed by another session).
release <task-file>Clear the claim (the worked-in worktree/branch record survives).
Two hard rules. Never hand-edit claimed_at / claimed_by_session in a task file; use claim/release for atomicity. Never git add _tasks/ when it’s a symlink; use tasks sync push.

Other groups

CommandWhat it does
serve [--port N]Run the portal (API + built SPA) on one origin. Default PORT 7440.
tunnel <…>Expose a worktree’s dev server at a stable Cloudflare hostname (see Tunnels).
usage <…>Token/cost ledger: collect, report, backfill (see Usage ledger).
claude <install|uninstall>Install/remove the Claude driver (skills + commands) into ~/.claude.
hook <name>Engine hook entrypoint: session-start (worktree setup) or validate-frontmatter.

06 Task files

Each project keeps a _tasks/ directory of NNN-<slug>.md files: a YAML frontmatter block over a markdown body. The file is the source of truth for one unit of work: core/ parses it, the portal renders it, the CLI claims and syncs it.

Status vocabulary

statusmeaningbacklog?done_date
OPENactive backlog; pickable now (or waiting on an unmet dep)yesnull
PARKEDdeliberately shelved; not being worked, not abandonedyes (parked)null
ENOUGHa version of done: shipped, leftovers recorded in the bodynoset
DONEfully complete; nothing leftnoset
OBSOLETEabandoned / superseded; will not be donenon/a

There is no blocked status. Blocked on another task: list it in depends_on and stay OPEN; the portal derives the waiting state and clears it the moment the dependency closes. Blocked on something external: PARKED. Legacy files still carrying status: BLOCKED_ON parse with a validator warning, never an error.

ENOUGH is treated as a done-family state everywhere DONE is (excluded from backlog, satisfies dependencies, never flagged stale), but signals “satisfied for now, leftovers worth harvesting later.”

Full status notes · docs/TASK-STATUS-VOCABULARY.md

Storage

_tasks/ is either a normal tracked directory in the repo (--store normal) or a shared store (--store shared, the default): a gitignored absolute symlink into ~/gitroot/_tasks/<slug>, its own git repo on a tasks branch. The shared model lets every worktree see the same task files instantly and survives across clones.

Commit shared-store edits with cogyard tasks sync push, never git add. The symlink is gitignored, so a git add _tasks/ silently does nothing.

07 Collision-free claims

The whole point of cogyard is running several agents at once without them stepping on each other. Before any session touches a task, it claims it atomically. A second session that reaches for the same task is refused, not silently doubled up, so no two sessions ever do the same work.

$ cogyard env claim _tasks/037-thing.md <session-id>   # refuses if already claimed
$ cogyard env release _tasks/037-thing.md             # clear when done

The claim writes claimed_at and claimed_by_session into the task’s frontmatter atomically. The worked-in worktree and branch are recorded too, and survive a release, so the portal can show where a task was done even after the claim is cleared.

Never hand-edit the claim fields. Two sessions racing to edit frontmatter by hand can corrupt it; claim/release are atomic and are the only safe path.

08 Teams & multi-user v1

Everything above assumes one developer directing many agents. Multi-user v1 extends the same machinery to a team of humans: N developers share one project’s task store via a git remote (branch tasks). Nothing else is shared: each member keeps their own machine, worktrees, ports, and their own localhost portal reading the same synced store. No server, no accounts. git is the backbone.

# Team lead, one-time: publish the store to a remote the team can push to:
$ cogyard tasks convert --remote git@github.com:you/yourproject-tasks.git

# Every other member, one command (clones the store, mounts the symlink, registers):
$ cogyard tasks join git@github.com:you/yourproject-tasks.git

Claims become named: on a remote-backed store, cogyard env claim pulls first, records who claimed (claimed_by: $COGYARD_USER, else your git name), and pushes the claim commit immediately, so teammates see it without waiting for a sync. A lost race comes back as a clean refusal (claimed by Alice since <date>), never a rebase conflict and never two people silently on the same task. Task-id reservations (tasks next-id) are race-safe across machines the same way.

v1’s limits, by design: claims are advisory (no auth; fine for a trusting team, not a security boundary), consistency is git consistency, and each member’s portal shows the store as of their last sync. There is no shared dashboard.

vNext, not shipped yet. Real user accounts and auth, one shared team portal (who’s on what, across everyone), and an authoritative claim service are spec’d as the next step. No dates.
The full v1 team model · docs/MULTI-USER.md

09 Worktree ports

Run npm run dev in two agent worktrees of the same repo and they’d both grab the same port. cogyard’s machine-wide SessionStart hook reserves a unique port pair per worktree. Universal, no opt-in. The reservation is just a registry row plus a briefing injected into the new session’s context, so the session knows its ports.

If a project additionally commits a .claude/worktree-config.json, the hook goes further: it writes .planet / env files / launch.json so dev servers bind the reserved ports automatically, and an optional launchd supervisor keeps those dev servers up across crashes. Allocations live in ~/.cogyard/ports.json.

Schema, supervisor tunables & debugging · docs/WORKTREE-PORTS.md

10 The portal

One cross-project view of what every agent is doing: backlog, claims, which worktree owns which task, and a token/cost usage tab.

$ cogyard serve              # API + built SPA on one origin, http://localhost:7440
$ cogyard serve --port 7437  # pick a port

The portal is read-mostly: it’s a viewer, not an editor. The only write endpoints are the usage-refresh button and the New/Adopt-project action, both same-origin-gated. For a clean hostname (http://cogyard) put a reverse proxy in front.

Reverse-proxy & TLS notes · docs/DEPLOY.md

11 Tunnels

Expose a project’s current worktree dev server at a stable public Cloudflare hostname. The tunnel follows whichever worktree you’re working in.

$ cloudflared tunnel login                      # one-time, interactive (you do this)
$ cogyard tunnel enable <project> <hostname>    # one-time per project
$ cogyard tunnel here                           # repoint at the active worktree
$ cogyard tunnel status | list
$ cogyard tunnel disable [--delete]

cogyard gives each worktree a different dynamic port; tunnel here rewrites the tunnel’s ingress to the active worktree’s port so one hostname tracks your work (it runs automatically on session start). Uses cloudflared local-config mode plus a per-project LaunchAgent. macOS-only today.

Full reference + gotchas · docs/TUNNELS.md

12 Usage ledger

cogyard harvests token/cost data from agent session transcripts into a per-machine ledger under ~/.cogyard/usage/, surfaced in the portal’s usage tab.

$ cogyard usage collect           # harvest new transcript content (idempotent)
$ cogyard usage backfill          # harvest all existing transcripts once
$ cogyard usage report [project]  # cost/token rollup, all projects or one in detail

Cost is computed from the active integration’s price table. With no agent active (the no-op adapter) tokens are still recorded, but cost stays null rather than invented.

13 Chats behind a task

A chat is the record of how a task got built — the reasoning, the dead ends, the decisions. cogyard answers “which chats made this task?”: give it a task id and it finds the agent chats that touched it, and lets you read the transcript without leaving the portal.

It sorts the chats into three buckets by how they touched the task:

  • Created — the chat that authored the task file.
  • Implemented — chats that claimed the task, or committed against it ([#N]).
  • Mentioned — chats that referenced it without claiming or committing.

Three places to ask, same answer behind all of them:

$ cogyard sessions chats <task-id>   # CLI: the three buckets, with transcript paths
$ /task-chats <task-id>              # in Claude Code: list, then read a chosen transcript
# portal: a “Chats” box in a task’s expanded row — click a chat to read its transcript in a popup

The lookup reads the durable usage ledger, not the live worktree, so archiving a chat or deleting its worktree never blanks the answer — exactly the finished tasks you most want to look back on stay findable. It’s read-only: it finds and shows the transcript, it never resumes the chat.

14 Driving cogyard with any agent

The engine (core/) and CLI (cli/) are agent-agnostic. Three things are inherently agent-specific (worktree layout, where transcripts live, and the model price table) and live behind a small adapter interface (integrations/<name>/adapter.mjs).

The engine resolves the active adapter once at import, in this order:

  1. the COGYARD_INTEGRATION environment variable,
  2. ~/.cogyard/config.json,
  3. auto-detect.

If none resolves, it falls back to a built-in no-op adapter so the CLI and portal run with no agent at all. Adding an agent means writing one adapter.mjs against the contract; the engine never imports it by name. integrations/claude/ is the reference driver (and a Claude Code plugin).

Doing it by hand (any agent, no driver):

$ cogyard tasks next-id <slug>            # create a task file
$ cogyard env claim <file> <session-id>   # claim before you touch it
$ cogyard env release <file>              # release when done
$ cogyard tasks sync push "<msg>"         # persist
Full adapter contract · docs/INTEGRATIONS.md