# Agent ID repository guide
## Documentation boundaries
Keep `README.md` human-facing: what the project does, installation, normal use, and project origins. Keep implementation details and complete command references in this file. Instructions for a running agent belong in the output generated by `src/prime.rs` (`agent-id prime`).
## CLI reference
The binary is installed as `agent-id`; the Rust crate is `agent-id-cli`.
### `agent-id register [SESSION_ID]`
Allocates a permanent identity. Registration is idempotent: an existing session keeps its identity and receives a new `updated_at`.
```text
--family NAME Prefer a family name, useful for child agents
--realm NAME Select the computer realm
--session-id ID Provide the session ID explicitly
--json Print the complete assignment as JSON
```
### `agent-id lookup [IDENTIFIER]`
Reads an existing identity by session ID, canonical name, or slug. Without an explicit identifier, lookup uses `AGENT_ID_SESSION_ID`.
```text
--session-id ID Provide the session ID explicitly
--json Print the complete assignment as JSON
```
### `agent-id current`
Reads the identity for `AGENT_ID_SESSION_ID` without registering a missing session. Use `--json` to print the complete assignment.
```text
--json Print the complete assignment as JSON
```
### `agent-id annotate [SESSION_ID]`
Updates summary, OMP lifecycle state, working-directory metadata, or namespaced extension metadata independently; omitted fields remain unchanged. The `--state` option writes the OMP signal under `extensions.omp`.
```text
--summary TEXT Set a concise summary (maximum 240 characters)
--clear-summary Remove the summary
--state VALUE Set the OMP lifecycle state signal
--clear-state Remove the OMP lifecycle state signal
--cwd PATH Set the current working directory
--clear-cwd Remove the current working directory
--extension OWNER=JSON Set namespaced unstructured JSON metadata; repeatable
--clear-extension NAME Remove one extension namespace; repeatable
--session-id ID Provide the session ID explicitly
--json Print the complete assignment as JSON
```
### `agent-id discover`
Lists non-stopped assignments by `updated_at`, newest first. Use `--all` to include stopped assignments. Outside Herdr, discovery includes all matching non-stopped registry assignments. Inside Herdr, default discovery is limited to assignments matched to live Herdr agents; `--all` retains all registry assignments while adding runtime projections. The top-level state is materialized from Herdr runtime state first, then the OMP extension state, and otherwise `unknown`. Human-readable results include available summaries, materialized states, and working directories; JSON includes the complete assignments. Herdr runtime matching uses exact OMP session-file metadata.
```text
--limit N Maximum records (default 20; zero means all)
--recent HOURS Only records updated within this many hours
--realm NAME Only records in this realm
--all Include stopped assignments
--json Print the complete assignments and available runtime projections as JSON
```
### `agent-id prune`
Removes assignments older than an RFC 3339 cutoff, including their name claims.
```text
--before TIMESTAMP Delete records updated before this timestamp
--dry-run Preview matches without deleting
--json Print the prune report as JSON
```
### `agent-id prime`
Prints the agent-facing workflow and command contract. `--prelude` omits the command reference; `--json` wraps the documentation in a JSON object.
## OMP extension implementation
`extensions/agent-id.ts` is the companion adapter. It reads the authoritative session ID and working directory from OMP, invokes the `agent-id` binary from `PATH` with explicit arguments, parses the returned assignment, and manages session lifecycle and summaries. OMP lifecycle signals are stored under the `extensions.omp` namespace.
| OMP event | Extension behavior |
|---|---|
| Session start, switch, branch, or tree navigation | Looks up or registers the identity, records the OMP session file and working directory, and publishes `idle` under `extensions.omp`. |
| Agent turn starts | Refreshes the OMP session file and publishes `working` under `extensions.omp`. |
| Agent turn ends | Publishes `idle` under `extensions.omp` and may refresh its current-work summary. |
| Tool call | Injects `AGENT_ID_SESSION_ID` only into matching `agent-id current` invocations through OMP's Bash tool. |
| Session shuts down | Publishes `stopped` under `extensions.omp`. |
The plugin bundles `skills/agent-id/SKILL.md` for on-demand identity and neighbor-selection guidance. The extension does not insert instructional context into session branches.
The extension does not register an identity tool. For matching `agent-id current` invocations through OMP's Bash tool, the extension injects the current session ID as `AGENT_ID_SESSION_ID`. It preserves a caller-provided value and does not modify the parent shell or unrelated Bash commands.
After completed turns, the extension can derive up to three successful summaries. Each completion receives only the previous summary, latest request, and latest reply; it uses the `@tiny` model role with `@smol` as fallback, caps output at 80 characters, and persists through `agent-id annotate`. Summary generation state is stored as a session entry and restored across resume, branch, and tree navigation. Missing model access does not prevent registration or lifecycle updates.
Lifecycle signals are `working`, `idle`, `waiting`, `blocked`, and `stopped`; `unknown` is the materialized fallback when no signal is available. Agent ID generates signal timestamps. The top-level `state` is not persisted as a source field.
## Registry implementation
The registry root is `$AGENT_ID_HOME` when set, otherwise `$XDG_DATA_HOME/agent-id`, or `$HOME/.local/share/agent-id` when `XDG_DATA_HOME` is unset.
Session records live at `by-session/<session-id>.json`; session IDs must be filename-safe. Name claims live under `by-name/`. The assignment stores the permanent name and slug, realm, optional timestamped summary, working-directory metadata, and optional timestamped extension-owned JSON metadata. OMP lifecycle state is stored in `extensions.omp.data.state`.
Realm resolution order is `--realm`, `AGENT_REALM` for tests or overrides, then `$XDG_CONFIG_HOME/agent-id/realm` with `$HOME/.config/agent-id/realm` as fallback. If no configuration exists, registration selects a realm and persists it for future sessions on the machine.
Summary, working-directory, and extension fields update independently of the permanent name. Extension owners are bounded lowercase namespaces; each update atomically replaces one owner's JSON value. The OMP extension writes its absolute session file and lifecycle state under `extensions.omp`; discover materializes the top-level state from the Herdr runtime projection when present, then the OMP signal, then `unknown`.
## Release workflow
When the user says “Let's do the release workflow,” drive the release through publication:
1. Confirm the worktree contains only the intended release changes, the branch is `main`, and the `v<version>` tag does not already exist.
2. Update the version in `Cargo.toml` and `package.json`, then run Cargo without `--locked` once to refresh the root `agent-id-cli` entry in `Cargo.lock`.
3. Run `cargo fmt --all -- --check`, `cargo test --all --locked`, `bun test extensions/agent-id.test.ts`, and `cargo package --locked --allow-dirty`.
4. Commit all release changes with a Conventional Commit message, the relevant `SQ-Task` trailer, and the required OMP/model co-author trailers.
5. Push `main`, create and push the annotated `v<version>` tag, then publish a GitHub release for that existing tag with generated notes. A tag push runs only the version check; publishing the GitHub release triggers macOS artifacts, crates.io publishing, and the Homebrew tap update.
6. Watch the release-triggered `Publish` workflow until every required job succeeds. Verify the GitHub release has both macOS archives and checksums; report whether crates.io and the Homebrew tap published successfully.
Required repository secrets are `CARGO_REGISTRY_TOKEN` and `HOMEBREW_TAP_TOKEN`.