rename claude.md to agents.md for agents and the repo
Claude Code (>= 2.1.277) and opencode both read AGENTS.md, but Claude
Code reads it only when no CLAUDE.md exists in its cwd or above. So
this is a plain rename with no CLAUDE.md stub left behind.
- hive-agent/src/agents_md_migrate.rs: new. At harness start, before
the first turn, renames state/CLAUDE.md to state/AGENTS.md when only
the former exists; logs an error naming both paths when both exist
and touches neither; does nothing otherwise. Idempotent.
- hive-agent/src/main.rs: calls it in serve_main; checkpoint prompt
and a comment name AGENTS.md.
- hive-agent/src/claude_md_watch.rs: the size watch reads AGENTS.md;
todo text, doc comments and tests follow. Module name, todo
subsystem key ("claude_md") and metric name
(hyperhive.agent.claude_md.lines) are unchanged so existing todo
rows and dashboard history carry over.
- hive-agent/src/turn.rs, hive-agent/prompts/system.md: prompts tell
the agent its file is AGENTS.md.
- hive-agent/src/{otel_turn_metrics,stats}.rs,
frontend/packages/agent/src/stats.js, hive-subagent-mcp/src/*.rs:
comments and a tool parameter description naming the agent's file.
- nix/host-modules/swarm-grafana/dashboards/agents.json: panel title
and description.
- claude-plugins skills claude-subagents, state-hygiene: they mean the
agent's own state file.
- CLAUDE.md -> AGENTS.md at the repo root; docs/crates/README.md link
(checked by check-doc-refs.sh), hive-c0re/README.md,
.prettierignore and the nix/sources.nix comment follow.
- docs/: every prose mention of the agent's file; persistence.md
documents the boot-time rename, claude-invocation.md the shadowing.
Fixes #5509
This commit is contained in:
parent
484a9fd4c1
commit
a429b30448
25 changed files with 217 additions and 45 deletions
219
AGENTS.md
Normal file
219
AGENTS.md
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
# hyperhive — claude entry point
|
||||
|
||||
Hey claude. This is your starting page. The detailed docs live in
|
||||
[`docs/`](docs/) and are written for humans + you both — read them
|
||||
when you need depth on a subsystem. This file is the index.
|
||||
|
||||
- High-level project intro: **[README.md](README.md)**.
|
||||
- Open work + backlog: the forge issue tracker at
|
||||
**`$HIVE_FORGE_URL/hyperhive/hyperhive/issues`**. Read the host out of
|
||||
the env var — inside an agent container `localhost` is the *agent*, not
|
||||
the forge, so a hardcoded loopback address fails to connect.
|
||||
- Operator/agent trust-boundary design:
|
||||
**[docs/trust-boundary/boundary.md](docs/trust-boundary/boundary.md)** (`area/ops` issues
|
||||
for the deployment/gateway/privsep work — the separator is a **slash**,
|
||||
and `--label area:ops` now fails with `did you mean "area/ops"?`).
|
||||
- Agent trust model (trust boundary, prompt-injection threat model,
|
||||
capability = accepted risk), credential isolation + sandbox threat model:
|
||||
**[docs/trust-boundary/security.md](docs/trust-boundary/security.md)**.
|
||||
- Odd-looking nspawn / container plumbing usually has a story:
|
||||
**[docs/process/gotchas.md](docs/process/gotchas.md)**.
|
||||
|
||||
## Build & check
|
||||
|
||||
Always through the devshell — a bare `cargo` fails (`failed to find tool
|
||||
"cc"`, `cannot find -lsqlite3`). Details:
|
||||
[`docs/process/conventions.md`](docs/process/conventions.md#building--local-checks).
|
||||
|
||||
```sh
|
||||
nix develop -c cargo clippy --all-targets -- -D warnings
|
||||
nix develop -c cargo test
|
||||
nix fmt # treefmt is the CI gate, NOT bare cargo fmt
|
||||
```
|
||||
|
||||
Changed a `hivectl` / `swarmctl` verb or flag? Regenerate its doc — only
|
||||
CI's `nix flake check` catches the drift:
|
||||
`nix develop -c cargo run --bin hivectl -- markdown-docs > docs/tools/hivectl-cli.md`
|
||||
(same for `swarmctl` → `docs/tools/swarmctl-cli.md`). CI red but local
|
||||
green → build the suspect check (e.g. `nix build
|
||||
.#checks.x86_64-linux.hivectl-docs`) before blaming the builder.
|
||||
|
||||
## Repo map
|
||||
|
||||
One line per crate / top-level dir. **Each module's authoritative,
|
||||
always-current description lives in its own `//!` doc-comment** —
|
||||
`grep`/read the module when you need detail. This index is kept
|
||||
deliberately lean: it auto-loads into every turn's context, and a
|
||||
hand-maintained per-file tree drifts out of sync with the code.
|
||||
|
||||
### Rust workspace (`Cargo.toml` members)
|
||||
|
||||
Per-hive (host + in-container):
|
||||
|
||||
- **`hive-c0re/`** — host daemon (runs as the unprivileged `hive-core`
|
||||
user), **daemon-only** — the operator CLI is `hivectl`. Owns the sqlite
|
||||
broker, reminder queue, meta flake, lifecycle (`nixos-container`
|
||||
shellouts), gateway wiring, per-container stats and the axum operator
|
||||
dashboard. Agent forge/matrix accounts are `swarm-controller`'s. Largest
|
||||
crate.
|
||||
- **`hivectl/`** — operator CLI; talks to `hive-c0re` over the host admin
|
||||
socket, does NOT link it. Verb reference (CI-enforced):
|
||||
[`docs/tools/hivectl-cli.md`](docs/tools/hivectl-cli.md).
|
||||
- **`hive-priv/`** — minimal root helper, socket-activated at
|
||||
`/run/hive/priv.sock`; the few root ops (bind-mount edits, nsenter)
|
||||
`hive-c0re` delegates. See `docs/trust-boundary/boundary.md`.
|
||||
- **`hive-agent/`** — the in-container serve loop: turn-loop *policy*
|
||||
(`turn.rs`) over `hive-runtime`, per-agent web UI, event + turn-stats
|
||||
sinks, system-prompt renderer, claude launch config (`mcp_config.rs`).
|
||||
With `hive-agent-mcp` it's what "hive-ag3nt" refers to — there is no
|
||||
such directory.
|
||||
- **`hive-agent-mcp/`** — the embedded MCP server (`hive-mcp-http` unit).
|
||||
- **`hive-runtime/`** — the `Runtime` interface an agent's turns run on:
|
||||
a `claude` backend (over `hive-claude`) and an `acp` backend whose stream
|
||||
is translated into claude's `stream-json` shape. Links no hyperhive
|
||||
binary crate, so the subagent daemon uses it too.
|
||||
- **`hive-bash-mcp/`**, **`hive-matrix-mcp/`**, **`hive-subagent-mcp/`** —
|
||||
per-agent MCP daemons serving streamable-http directly (no stdio
|
||||
bridge): background bash tasks, matrix-sdk tools, nested subagent
|
||||
sessions (optionally goal-driven over several turns; daemon state is
|
||||
in-memory, the claude session survives a restart).
|
||||
- **`hive-screen-mcp/`** — stdio MCP bridge for GUI agents: screenshot,
|
||||
keyboard, mouse. All userspace.
|
||||
- **`hive-forge/`** — `hive-forge` Forgejo CLI; one module per verb.
|
||||
- **`hive-forge-notify/`** — notification pollers → todos on the in-agent
|
||||
socket. Two binaries: `hive-forge-notify`, `hive-github-notify`.
|
||||
- **`hive-jobq/`** — the job-DAG scheduler library. **Runtime-only —
|
||||
nothing writes the graph to disk**, so node ids are stable within a run,
|
||||
not across restarts. `hive-c0re`'s `job_queue/` is being removed in its
|
||||
favour — new scheduler-shaped code goes here.
|
||||
- **`hive-jobq-wire/`** — presentation of a `hive-jobq` graph to viewers
|
||||
(`WireNode` / `WireResource`); kept out of `hive-jobq` on purpose.
|
||||
- **`hive-jobq-metrics/`** — OTEL export of a graph's state rollup on a
|
||||
timer.
|
||||
- **`hive-log/`** — the one log-sink chooser: journald *or* stdout, never
|
||||
both (under a unit, stdout already is the journal). Do not grow it into a
|
||||
utility crate.
|
||||
- **`hive-metric/`** — one-shot CLI pushing a labeled metric over OTLP.
|
||||
|
||||
Wire types + socket plumbing:
|
||||
|
||||
- **`hive-types/`** — leaf newtypes, chiefly the validated `Ident`.
|
||||
- **`hive-sh4re/`** — shared payload types (`Message`, `HelperEvent`, …).
|
||||
- **`hive-host-sock/`** (hivectl ↔ c0re), **`hive-priv-sock/`** (c0re ↔
|
||||
priv), **`hive-core-agent-sock/`** (harness ↔ c0re, `/run/hive/mcp.sock`)
|
||||
— per-socket wire types, split out so each client links only its protocol.
|
||||
- **`hive-agent-sock/`** — the *in-agent* socket the harness serves to
|
||||
in-container producers (todos, reminders); also holds the `extra_mcp`
|
||||
spec. ⚠️ **This socket never leaves the container** — `hive-c0re` is not
|
||||
in the path, unlike `hive-core-agent-sock`.
|
||||
- **`hive-sock-client/`** — the shared JSON-line unix-socket client; retry
|
||||
is a policy value (`Retry::None` / `Retry::RideOutRestart`). Also holds
|
||||
the bounded request-line reader (`read_request_line`) the socket servers
|
||||
use.
|
||||
|
||||
Swarm-level:
|
||||
|
||||
- **`swarm-controller/`** — owns what is true **across** hives; opt-in,
|
||||
one per swarm. Serves HTTP over a unix socket nginx proxies to — ⚠️
|
||||
**the socket's directory is its access control**; the crate README has
|
||||
the constraint and a unit test pins the path.
|
||||
- **`swarm-controller-api/`** — serde-only request and response bodies of
|
||||
the controller's HTTP API, shared with `swarmctl` (forge, schedules and
|
||||
the agent-create and forge-token responses).
|
||||
- **`swarmctl/`** — swarm operator CLI; runs as **root and acts directly**
|
||||
(README says why). Doesn't link `swarm-controller`: the forge and
|
||||
schedule bodies and the agent responses come from
|
||||
`swarm-controller-api`; the agent-create request, inference and
|
||||
permissions ones are a local mirror. ⚠️ Edits authelia's
|
||||
**`users.yml` in place**, shared with `swarm-authelia-bridge`; that
|
||||
crate's README says what both writers must uphold. Verb reference
|
||||
(CI-enforced):
|
||||
[`docs/tools/swarmctl-cli.md`](docs/tools/swarmctl-cli.md).
|
||||
- **`swarm-authelia-bridge/`** (+ **`swarm-authelia-bridge-sock/`** wire
|
||||
types) — the other writer of authelia's users DB; runs inside
|
||||
`swarm-authelia`.
|
||||
- **`swarm-secret-client/`** — OpenBao client over `vaultrs`. ⚠️ Reads
|
||||
the **`BAO_`** env spellings explicitly — `vaultrs`'s `VAULT_*` defaults
|
||||
are set by no unit here, and falling through to them yields a client
|
||||
with **no identity** and a TLS failure that names no cause.
|
||||
- **`swarm-queue-client/`** — the one authenticated connect to the swarm
|
||||
NATS queue.
|
||||
- **`swarm-nats-auth/`** — NATS auth-callout responder; without it the
|
||||
queue is fail-closed and admits nobody.
|
||||
- **`swarm-agent-verify/`** — checks a `swarm-agent.<agent>.<secret>`
|
||||
token against the store; shared by `swarm-nats-auth` and
|
||||
`swarm-logs-auth`.
|
||||
- **`swarm-logs-auth/`** — nginx `auth_request` responder for agent access
|
||||
to the log store, and to the metrics store as `swarm-metrics-agent-auth`.
|
||||
- **`swarm-metrics-auth/`** — nginx `auth_request` responder for Grafana's
|
||||
bearer on the metrics store's query API.
|
||||
- **`swarm-logs/`** — agent CLI: a LogsQL query in, log lines out.
|
||||
- **`swarm-metrics/`** — agent CLI: a MetricsQL query in, the store's JSON out.
|
||||
- **`swarm-matrix-client/`** — appservice calls against the swarm
|
||||
homeserver, shared by `swarm-controller` and `swarm-matrix-ctl`.
|
||||
- **`swarm-matrix-ctl/`** — the one binary run inside
|
||||
`containers.hive-matrix`; new in-container jobs are verbs here, not
|
||||
crates.
|
||||
- **`swarm-builder/`** — builds agent config PR heads for commit status,
|
||||
and evaluates the agent archetypes the create form lists.
|
||||
Design: [`docs/swarm/builder.md`](docs/swarm/builder.md).
|
||||
- **`swarm-ci-metrics/`** — polls the forge's Actions runs and pushes each
|
||||
finished run's duration and queue wait to the metrics store. Design:
|
||||
[`docs/swarm/ci-metrics.md`](docs/swarm/ci-metrics.md).
|
||||
- **`swarm-claude-login/`** — runs `claude auth login` for one agent and
|
||||
stores the credentials at `swarm/agents/<agent>/claude-credentials`.
|
||||
Design: [`docs/swarm/claude-login.md`](docs/swarm/claude-login.md).
|
||||
- **`swarm-review-classifier/`** — one `claude --print` per PR
|
||||
classification, no tools, no forge credential. Design:
|
||||
[`docs/swarm/review-classifier.md`](docs/swarm/review-classifier.md).
|
||||
|
||||
### External dependencies with no directory here
|
||||
|
||||
- **`hive-claude`** — app-agnostic driver for headless `claude --print`
|
||||
(stream-json, `Telemetry`, the self-compacting `InfiniteSession`).
|
||||
⚠️ **Its own repo, not a workspace member** — there is no
|
||||
`hive-claude/` directory and `grep` here will not find it.
|
||||
|
||||
### Other top-level dirs
|
||||
|
||||
- **`frontend/`** — npm workspaces built hermetically by
|
||||
`nix/packages/frontend.nix`: `shared`, `dashboard` (operator SPA),
|
||||
`agent` (per-container UI), `swarm-ui` (Preact; packaged separately by
|
||||
`nix/packages/swarm-ui.nix`, not in `packages.default`'s closure).
|
||||
- **`nix/`** — `host-modules/` (the host stack), `agent-modules/`
|
||||
(per-agent harness features), `container-modules/` (guest side of
|
||||
service containers), `templates/agent.nix` (the container entry
|
||||
point), `archetypes/` (the built-in agent archetypes), `packages/`,
|
||||
`docs/` (options doc), `module-eval/` (NixOS
|
||||
module-eval tests), `builder/` (`check-flake`), `script-tests/`, plus
|
||||
`sources.nix` / `rust.nix` / `checks.nix` / `devshell.nix` /
|
||||
`treefmt.nix` behind the thin `flake.nix`.
|
||||
- **`docs/`** — subsystem reference docs (see *Reading paths* below).
|
||||
- **`branding/`**, **`scripts/`** — static assets + helper scripts.
|
||||
|
||||
## Reading paths
|
||||
|
||||
**[`docs/README.md`](docs/README.md) is the single index**, grouped by
|
||||
topic. Don't add a second copy of it here — a parallel list used to live
|
||||
in this file and drifted.
|
||||
|
||||
## Conventions & process
|
||||
|
||||
- **Never add `#[allow(clippy::…)]`** — fix the lint instead (extract a
|
||||
helper, add backticks, etc.). Worked examples:
|
||||
[`docs/process/conventions.md`](docs/process/conventions.md#building--local-checks).
|
||||
- **Pre-push lint hook** (catches tracker-tag and comment-block failures
|
||||
before CI does — install once per clone):
|
||||
`ln -sf ../../scripts/pre-push .git/hooks/pre-push`
|
||||
- **Comment/PR-description length**: size it to how non-obvious the
|
||||
thing is, not to how much investigation it took to find it — a
|
||||
mechanical fix gets a one-line comment, a genuinely non-obvious
|
||||
invariant or decision earns real prose. Don't restate a module's `//!`
|
||||
doc in a comment further down the same file.
|
||||
- **Operator-facing doc with real implementation detail mixed in**: wrap
|
||||
the implementation part in a `<details><summary>…</summary>` block
|
||||
(blank line after `<summary>` so the markdown inside renders) rather
|
||||
than a sibling page — see `docs/integrations/github.md`'s
|
||||
"Implementation" section. It only collapses in a rendered browser, and
|
||||
the `<summary>` line isn't markdown-processed, so keep it plain prose
|
||||
with no backticks.
|
||||
Loading…
Reference in a new issue