Watch
0
0
Fork
You've already forked hyperhive
0

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:
atlas 2026-10-18 01:06:47 +02:00 • committed by mara
commit a429b30448
25 changed files with 217 additions and 45 deletions

View file

@ -14,7 +14,7 @@ docs/tools/swarm-metrics-cli.md
# prettier's `proseWrap: "preserve"` prevents prose reflow but not list-item
# indentation normalisation, so these files need manual re-wrap before
# adding them back to the formatter scope.
CLAUDE.md
AGENTS.md
docs/agent-lifecycle/config-changes.md
docs/process/conventions.md
docs/networking/gateway.md

View file

@ -37,7 +37,7 @@ actually attached, so a `continue` naming a session that isn't there
fails the tool call outright instead of looking like it worked; the error
says which directory it searched, which is usually the fix (pass `dir`).
`dir` defaults to your work dir, `/agents/<you>/work`, which has no
`CLAUDE.md` above it, so a subagent started there does not load yours
`AGENTS.md` above it, so a subagent started there does not load yours
(until that directory exists, the daemon's cwd is used).
Use `status` for a
zero-cost "is it still going" check — for a running subagent it also

View file

@ -5,7 +5,7 @@ description: Enforces safe handling of an agent's own durable state/notes files
# State Hygiene
Durable notes/state files (your `CLAUDE.md`, `state/notes.md`, `state/TODO.md`,
Durable notes/state files (your `AGENTS.md`, `state/notes.md`, `state/TODO.md`,
and anything else under `state/`) are your memory across container resets and
context compactions. They only work if you actually read them before you
change them - writing blind is how history gets silently destroyed or

View file

@ -360,7 +360,7 @@ The system prompt (`hive-agent/prompts/system.md`, rendered by
varies is which MCP tools it surfaces (gated by the agent's permissions,
which the swarm sets). No `role:manager` block renders only
for the root agent. The root agent's role-specific
behaviour comes from its CLAUDE.md / agent-specific instructions, not
behaviour comes from its AGENTS.md / agent-specific instructions, not
the system prompt template.
## Helper events

View file

@ -270,6 +270,13 @@ Under `/var/lib/hyperhive/agents/<name>/`:
- `hyperhive-harness.json` — rate-limited / needs-login flags read
by the dashboard's async container-state fetch. See
`docs/web-ui/dashboard.md::Container row`.
The agent writes its own instructions to `AGENTS.md` here; claude and
opencode load it automatically from their cwd, `state/`. At boot,
`agents_md_migrate::run` renames a `state/CLAUDE.md` to `AGENTS.md`
when no `AGENTS.md` exists. When both exist it renames neither and
logs an error naming both paths: claude loads only `CLAUDE.md` while
one exists in its cwd or above.
- `harness/` — harness-internal ephemeral state; not intended for
agent consumption. Bind-mounted to `/agents/<name>/harness`
inside the container (`$HYPERHIVE_HARNESS_DIR`). Contents:
@ -321,7 +328,7 @@ Under `/var/lib/hyperhive/agents/<name>/`:
and other large working data. Bind-mounted RW to
`/agents/<name>/work` inside the container and owned by the agent
user. It sits outside `state/` so a claude or subagent started under
`work/` doesn't walk up into `state/CLAUDE.md` and load the agent's
`work/` doesn't walk up into `state/AGENTS.md` and load the agent's
own identity. Survives `destroy`/recreate, gone on `--purge`. Counted
in the per-agent disk metric (`measure_agent_disk`) together with
`state/` and the container rootfs. The dashboard doesn't serve it:

View file

@ -9,5 +9,5 @@ drift out of sync the way a hand-copied mirror would — edit the crate's
own README to change what shows up here.
For the one-line-per-crate index (which crate does what, at a glance)
see the main [`CLAUDE.md`](../../CLAUDE.md#repo-map) repo map instead;
see the main [`AGENTS.md`](../../AGENTS.md#repo-map) repo map instead;
this section is each crate's own, longer word on itself.

View file

@ -210,7 +210,7 @@ alongside the claude dir.
`/var/lib/hyperhive/agents/<name>/work/` bind-mounts to
`/agents/<name>/work` (RW, owned by the agent user). It's the place for
git worktrees and build dirs: a claude started under `state/` walks up
into `state/CLAUDE.md` and takes on the agent's identity, and one
into `state/AGENTS.md` and takes on the agent's identity, and one
started under `work/` doesn't. `/home/<name>` lives in the container
rootfs, which `destroy` deletes; `work/` survives `destroy`/recreate
and goes on `--purge`. The per-agent disk metric counts it; the

View file

@ -383,7 +383,7 @@ of their own — see [ACP-reported cost](#acp-reported-cost).
| `hyperhive.agent.session.count` | — | counter | `model` (incremented once per fresh, non-`--continue`'d session) |
| `hyperhive.agent.loose_ends.threads` | — | gauge | none |
| `hyperhive.agent.loose_ends.reminders` | — | gauge | none |
| `hyperhive.agent.claude_md.lines` | — | gauge | none — recorded from the `CLAUDE.md`-size watch's own ~15-minute tick, **not** per turn like the rows above |
| `hyperhive.agent.claude_md.lines` | — | gauge | none — recorded from the `AGENTS.md`-size watch's own ~15-minute tick, **not** per turn like the rows above |
| `hyperhive.agent.subagent_role.lines` | — | gauge | `role` (the file stem) — one series per role file in `subagent_roles/`, on the same ~15-minute tick |
| `hyperhive.agent.claude_usage.percent` | `%` | gauge | `window` (`five_hour`, `seven_day`, … as the usage endpoint names them) — polled every 5 minutes, **not** per turn |
| `hyperhive.agent.claude_usage.resets_at` | `s` | gauge | `window` — unix seconds at which that window resets; same 5-minute poll |

View file

@ -162,7 +162,7 @@ lands in a faithful copy of the agent's environment:
agent's `/home/<name>/.claude` where its OAuth credentials live. choom
prefixes the machine with `<name>@` (the meta-flake sets the agent's
unix user name to its label).
- **from `/agents/<name>/state`**: the session and `CLAUDE.md` (the
- **from `/agents/<name>/state`**: the session and `AGENTS.md` (the
persona) resolve against the right project dir.
- **with the harness flags**: `--settings`, `--mcp-config`, and
`--system-prompt-file` from `/run/hive-config/` — the same files the

View file

@ -210,9 +210,12 @@ still applies.
The child runs with `cwd = /state` (when the bind exists; falls
back to the parent's cwd in dev), so any relative path in a tool
call (`Read foo.md`, `Bash ls`, `Write notes.md`) lands in the
agent's durable bind-mounted dir. CLAUDE.md autoload walks
upward from `/state` — drop a per-agent CLAUDE.md there if you
want long-term hints that survive destroy/recreate.
agent's durable bind-mounted dir. AGENTS.md autoload walks
upward from `/state` — drop a per-agent AGENTS.md there if you
want long-term hints that survive destroy/recreate. A `CLAUDE.md`
in `/state` or above it shadows `AGENTS.md`: claude then loads only
the `CLAUDE.md` (see `docs/agent-lifecycle/persistence.md` for the
boot-time rename).
The wake prompt is intentionally minimal: the popped message's
`from`/`body`, prefixed with a `[msg #<id>]` broker-row-id marker

View file

@ -427,7 +427,7 @@ hit-rate** (`cache_read` over all input-side tokens) and
scheduled / delivered / pending** for the window. When the
per-session capture has data, a **first-turn ctx** chip shows the
input tokens of the most recent fresh claude session's first turn —
a proxy for system-prompt + CLAUDE.md sprawl (a fresh session's first
a proxy for system-prompt + AGENTS.md sprawl (a fresh session's first
turn pays the full static prefix uncached). It's derived in `stats.rs`
(`first_turn_ctx`: the first turn, `ORDER BY started_at LIMIT 1`, of
the latest `sessions` row in the window) and stays out of the JSON

View file

@ -147,7 +147,7 @@ window.Chart = Chart;
chips.push(["sessions", fmtInt(s.session_count)]);
}
// First-turn ctx: input tokens of the most recent fresh session's
// first turn — the cold system-prompt + CLAUDE.md cost, a sprawl
// first turn — the cold system-prompt + AGENTS.md cost, a sprawl
// proxy. Omitted from the JSON (and so absent here) until the
// per-session capture has data.
if (typeof s.first_turn_ctx === "number") {

View file

@ -33,7 +33,7 @@ Durable knowledge:
- write to `/agents/{label}/state/notes.md` (free-form) or any other path under `/agents/{label}/state/`. That directory is bind-mounted from the host and persists across container destroy/recreate — claude's `--continue` session only carries short-term context, but `/agents/{label}/state/` is forever. Read it back at the start of relevant turns to remember things across resets.
**Work dir**: `/agents/{label}/work/` is the place for git worktrees, clones, build trees and other bulky scratch. It is bind-mounted from the host, persists across container destroy/recreate and is backed up. Keep `state/` for notes and small durable files. Don't keep work under `/home`, `/tmp` or other container paths — they are outside what's backed up. Start subagents with their `dir` under `work/` (that is also the default): a claude started under `state/` walks up into `state/CLAUDE.md` and takes on your identity, one under `work/` doesn't.
**Work dir**: `/agents/{label}/work/` is the place for git worktrees, clones, build trees and other bulky scratch. It is bind-mounted from the host, persists across container destroy/recreate and is backed up. Keep `state/` for notes and small durable files. Don't keep work under `/home`, `/tmp` or other container paths — they are outside what's backed up. Start subagents with their `dir` under `work/` (that is also the default): a claude started under `state/` walks up into `state/AGENTS.md` and takes on your identity, one under `work/` doesn't.
Claude session (OAuth credentials) lives at `/root/.claude/` and persists across restarts.

View file

@ -0,0 +1,143 @@
//! One-time on-boot rename of the agent's instructions file from
//! `state/CLAUDE.md` to `state/AGENTS.md`. Runs in `main.rs` before the
//! first turn. Idempotent: once the file is renamed, later boots find no
//! `CLAUDE.md` and do nothing.
//!
//! Claude Code reads `AGENTS.md` only when no `CLAUDE.md` exists in its cwd
//! or above, so a `CLAUDE.md` left next to an `AGENTS.md` shadows it. When
//! both exist this module refuses to choose: it logs an error naming both
//! paths and leaves the files alone for the agent or operator to merge.
use std::path::{Path, PathBuf};
use anyhow::{Context, Result};
/// What [`rename_claude_md`] found and did.
#[derive(Debug, PartialEq, Eq)]
pub enum Outcome {
/// `CLAUDE.md` existed without an `AGENTS.md`, and is now `AGENTS.md`.
Renamed,
/// Neither file, or only `AGENTS.md`: nothing to do.
NothingToDo,
/// Both files exist; neither was touched.
BothExist {
claude_md: PathBuf,
agents_md: PathBuf,
},
}
/// Rename `<state_dir>/CLAUDE.md` to `<state_dir>/AGENTS.md` if only the
/// former exists. Logs the outcome; never fatal to boot.
pub fn run(state_dir: &Path) {
match rename_claude_md(state_dir) {
Ok(Outcome::Renamed) => {
tracing::info!(dir = %state_dir.display(), "renamed CLAUDE.md to AGENTS.md");
}
Ok(Outcome::NothingToDo) => {}
Ok(Outcome::BothExist {
claude_md,
agents_md,
}) => tracing::error!(
claude_md = %claude_md.display(),
agents_md = %agents_md.display(),
"both CLAUDE.md and AGENTS.md exist; claude loads only CLAUDE.md while it exists. \
Merge them into AGENTS.md and delete CLAUDE.md"
),
Err(e) => tracing::error!(error = ?e, "CLAUDE.md to AGENTS.md rename failed"),
}
}
/// Decide and apply the rename.
///
/// # Errors
///
/// Propagates a failed `rename`; both files are left as they were.
pub fn rename_claude_md(state_dir: &Path) -> Result<Outcome> {
let claude_md = state_dir.join("CLAUDE.md");
let agents_md = state_dir.join("AGENTS.md");
match (claude_md.exists(), agents_md.exists()) {
(true, false) => {
std::fs::rename(&claude_md, &agents_md).with_context(|| {
format!("rename {} -> {}", claude_md.display(), agents_md.display())
})?;
Ok(Outcome::Renamed)
}
(true, true) => Ok(Outcome::BothExist {
claude_md,
agents_md,
}),
(false, _) => Ok(Outcome::NothingToDo),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn claude_md_alone_is_renamed_once() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("CLAUDE.md"), "me\n").expect("write");
assert_eq!(rename_claude_md(dir.path()).expect("run"), Outcome::Renamed);
assert!(!dir.path().join("CLAUDE.md").exists());
assert_eq!(
std::fs::read_to_string(dir.path().join("AGENTS.md")).expect("read"),
"me\n"
);
assert_eq!(
rename_claude_md(dir.path()).expect("second run"),
Outcome::NothingToDo
);
assert_eq!(
std::fs::read_to_string(dir.path().join("AGENTS.md")).expect("read"),
"me\n"
);
}
#[test]
fn both_present_touches_neither() {
let dir = tempfile::tempdir().expect("tempdir");
let claude_md = dir.path().join("CLAUDE.md");
let agents_md = dir.path().join("AGENTS.md");
std::fs::write(&claude_md, "old\n").expect("write");
std::fs::write(&agents_md, "new\n").expect("write");
assert_eq!(
rename_claude_md(dir.path()).expect("run"),
Outcome::BothExist {
claude_md: claude_md.clone(),
agents_md: agents_md.clone(),
}
);
assert_eq!(std::fs::read_to_string(&claude_md).expect("read"), "old\n");
assert_eq!(std::fs::read_to_string(&agents_md).expect("read"), "new\n");
}
#[test]
fn neither_present_creates_nothing() {
let dir = tempfile::tempdir().expect("tempdir");
assert_eq!(
rename_claude_md(dir.path()).expect("run"),
Outcome::NothingToDo
);
assert_eq!(std::fs::read_dir(dir.path()).expect("ls").count(), 0);
}
#[test]
fn agents_md_alone_is_left_alone() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("AGENTS.md"), "me\n").expect("write");
assert_eq!(
rename_claude_md(dir.path()).expect("run"),
Outcome::NothingToDo
);
assert_eq!(
std::fs::read_to_string(dir.path().join("AGENTS.md")).expect("read"),
"me\n"
);
}
}

View file

@ -1,5 +1,5 @@
//! `CLAUDE.md` size watch: raises a loose-ends-v2 todo when the agent's
//! own `CLAUDE.md` grows past 500 lines, and feeds the same line count
//! `AGENTS.md` size watch: raises a loose-ends-v2 todo when the agent's
//! own `AGENTS.md` grows past 500 lines, and feeds the same line count
//! into an OTEL gauge every tick regardless of threshold. Per the
//! operator's own framing of the ask — "claude md is personality and
//! how you organize yourself, not a work log" — the prompt is asked to
@ -11,7 +11,7 @@
//! summary) — a third instance of the same anti-nag pattern rather than
//! a new one.
//!
//! `CLAUDE.md` lives at the top of the agent's own state dir — the same
//! `AGENTS.md` lives at the top of the agent's own state dir — the same
//! directory `claude --print` runs with as its cwd (`turn::session_cwd`),
//! which is how the CLI's own auto-load discovers it.
//!
@ -40,20 +40,24 @@ const WARN_LINES: u64 = 500;
const BUCKET: u64 = 50;
/// Producing subsystem marker for the todo row.
const SUBSYSTEM: &str = "claude_md";
/// Fixed dedup key — there is only ever one `CLAUDE.md`-size todo per
/// Fixed dedup key — there is only ever one `AGENTS.md`-size todo per
/// agent.
const TODO_KEY: &str = "size";
/// Background loop: periodically reconcile the `CLAUDE.md`-size todo and
/// Background loop: periodically reconcile the `AGENTS.md`-size todo and
/// feed the OTEL gauge. Detached task — runs for the harness's lifetime;
/// errors are logged, never fatal.
pub async fn run(todos: Arc<Todos>, wake: Arc<Notify>) {
loop {
tokio::time::sleep(CHECK_INTERVAL).await;
let lines = match tokio::task::spawn_blocking(|| line_count(&claude_md_path())).await {
let lines = match tokio::task::spawn_blocking(|| {
line_count(&agents_md_path(&crate::paths::state_dir()))
})
.await
{
Ok(l) => l,
Err(e) => {
tracing::warn!(error = %e, "claude.md watch probe panicked");
tracing::warn!(error = %e, "agents.md watch probe panicked");
continue;
}
};
@ -72,25 +76,25 @@ fn reconcile(todos: &Todos, wake: &Notify, summary: Option<&str>) {
Some(summary) => match todos.upsert(SUBSYSTEM, Some(TODO_KEY), summary, None, false) {
Ok((_, true)) => wake.notify_one(),
Ok((_, false)) => {}
Err(e) => tracing::warn!(error = ?e, "claude.md todo upsert failed"),
Err(e) => tracing::warn!(error = ?e, "agents.md todo upsert failed"),
},
None => {
if let Err(e) = todos.clear(SUBSYSTEM, Some(TODO_KEY)) {
tracing::warn!(error = ?e, "claude.md todo clear failed");
tracing::warn!(error = ?e, "agents.md todo clear failed");
}
}
}
}
/// `CLAUDE.md`'s path: the top of the agent's own state dir, matching
/// `AGENTS.md`'s path: the top of the agent's own state dir, matching
/// where `claude --print` runs (`turn::session_cwd`) and therefore where
/// its own auto-load discovers the file.
fn claude_md_path() -> std::path::PathBuf {
crate::paths::state_dir().join("CLAUDE.md")
fn agents_md_path(state_dir: &Path) -> std::path::PathBuf {
state_dir.join("AGENTS.md")
}
/// Line count of the file at `path`. `None` when it can't be read — no
/// `CLAUDE.md` yet is not a warning, and a transient read failure isn't
/// `AGENTS.md` yet is not a warning, and a transient read failure isn't
/// either.
fn line_count(path: &Path) -> Option<u64> {
let contents = std::fs::read_to_string(path).ok()?;
@ -108,9 +112,9 @@ fn summary_for(lines: u64) -> Option<String> {
}
let bucket = lines / BUCKET * BUCKET;
Some(format!(
"your CLAUDE.md is {bucket}+ lines. CLAUDE.md is personality and how you organize \
"your AGENTS.md is {bucket}+ lines. AGENTS.md is personality and how you organize \
yourself, not a work log — if it's grown past that, moving detail into separate files \
(linked from CLAUDE.md) or an archive is what actually shrinks this count. It \
(linked from AGENTS.md) or an archive is what actually shrinks this count. It \
auto-loads into every turn, so a smaller file is a fixed cost saved on every turn. \
Nothing here is a hard limit, and deleting stale content outright is fine too if \
that's genuinely what it is — no obligation either way. No need to act on this now — \
@ -175,16 +179,28 @@ mod tests {
#[test]
fn line_count_matches_editor_expectations() {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("CLAUDE.md");
let path = dir.path().join("AGENTS.md");
// Three lines, trailing newline — an editor shows 3 lines, not 4.
std::fs::write(&path, "one\ntwo\nthree\n").expect("write");
assert_eq!(line_count(&path), Some(3));
}
/// The watch counts `AGENTS.md`, and a leftover `CLAUDE.md` beside it
/// is not what it reads.
#[test]
fn watch_reads_agents_md_not_claude_md() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("CLAUDE.md"), "one\n").expect("write");
assert_eq!(line_count(&agents_md_path(dir.path())), None);
std::fs::write(dir.path().join("AGENTS.md"), "one\ntwo\n").expect("write");
assert_eq!(line_count(&agents_md_path(dir.path())), Some(2));
}
#[test]
fn missing_file_is_silent_not_an_error() {
assert_eq!(
line_count(Path::new("/definitely/does/not/exist/CLAUDE.md")),
line_count(Path::new("/definitely/does/not/exist/AGENTS.md")),
None
);
}

View file

@ -9,6 +9,7 @@
//! Single bin crate: the module tree below (formerly this crate's `lib.rs`,
//! before lib + bin were collapsed into one) plus the serve loop.
mod agents_md_migrate;
mod boot_announce;
mod claude_credentials;
mod claude_md_watch;
@ -215,7 +216,7 @@ fn graceful_stop_message() -> hive_sh4re::inbox::DeliveredMessage {
body: "You are being gracefully stopped — the container will shut down after this turn, \
and new inbound messages are already fenced. This is your one checkpoint turn: \
flush anything worth keeping into your durable /state files now — update your \
notes / CLAUDE.md / TODO.md with in-flight task state, decisions made, important \
notes / AGENTS.md / TODO.md with in-flight task state, decisions made, important \
file paths, and whatever you'd need to resume cleanly later with only a summary \
of this conversation to go on. Do not start new work or reply to anyone; just \
write your notes and end your turn. The session may be compacted after this turn \
@ -450,7 +451,7 @@ fn spawn_todo_socket(
// top level instead of disk pressure.
tokio::spawn(state_entry_watch::run(store.clone(), todo_wake.clone()));
// Same shape again: nudge (and feed an OTEL gauge) on a
// grown CLAUDE.md instead of a grown state dir.
// grown AGENTS.md instead of a grown state dir.
tokio::spawn(claude_md_watch::run(store.clone(), todo_wake.clone()));
// Swarm-scheduled prompts fire as todos too, from the list the
// swarm keeps for this agent.
@ -553,6 +554,8 @@ async fn serve_main<S: Surface>(socket: &Path, poll_ms: u64) -> Result<()> {
tracing::error!(error = %e, "web_ui::serve exited with error");
}
});
// Before the first turn, so claude's own auto-load finds `AGENTS.md`.
agents_md_migrate::run(&paths::state_dir());
// Harness-local reminders: a due reminder fires
// straight into an mpsc channel the serve loop races against the
// broker long-poll (unlike todos, a fire carries real per-row data,

View file

@ -53,7 +53,7 @@ struct Instruments {
open_threads: Gauge<u64>,
open_reminders: Gauge<u64>,
/// Recorded from [`crate::claude_md_watch`]'s own tick, not from
/// [`record`] — `CLAUDE.md` size is a continuously-live value (like
/// [`record`] — `AGENTS.md` size is a continuously-live value (like
/// hive-c0re's container gauges), not a once-per-turn one, so it has
/// its own entry point rather than riding `record`'s per-turn call.
claude_md_lines: Gauge<u64>,
@ -110,7 +110,7 @@ pub fn record(row: &TurnStatRow, fresh_session: bool) {
}
}
/// Record the current `CLAUDE.md` line count. Called from
/// Record the current `AGENTS.md` line count. Called from
/// [`crate::claude_md_watch`]'s periodic tick (every ~15 minutes, not
/// per turn) — see the field doc on [`Instruments::claude_md_lines`] for
/// why this doesn't ride [`record`]. No-op when OTEL isn't configured,

View file

@ -142,7 +142,7 @@ pub struct Snapshot {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reminder_stats: Option<ReminderStats>,
/// First-turn input tokens of the most recent fresh claude session
/// that started in the window — a proxy for system-prompt + CLAUDE.md
/// that started in the window — a proxy for system-prompt + AGENTS.md
/// sprawl (a fresh session's first turn pays the full static prefix
/// uncached, so this is the current "cold context" cost). `None` until
/// the sessions capture (per-session `session_id`) has data; every
@ -379,7 +379,7 @@ fn snapshot(path: &Path, window: Window) -> Result<Snapshot> {
}
/// First-turn input tokens of the most recent fresh claude session that
/// started in `[from, now]`. Tracks system-prompt + CLAUDE.md sprawl:
/// started in `[from, now]`. Tracks system-prompt + AGENTS.md sprawl:
/// the first turn of a fresh session (`--continue` suppressed) pays the
/// full static prefix as uncached input, so watching this over time
/// surfaces creep. Uses the agreed per-session derive — the first turn

View file

@ -81,7 +81,7 @@ Your conversation context has grown large and the harness is about to run `/comp
which collapses the detailed turn-by-turn history into a short summary. Anything you \
do not persist now is effectively lost after the next turn.\n\n\
Use THIS turn to flush anything worth keeping into your durable `/state` files: update \
your notes / CLAUDE.md / TODO.md with in-flight task state, decisions made, important \
your notes / AGENTS.md / TODO.md with in-flight task state, decisions made, important \
file paths, and whatever you would need to resume cleanly with only a summary of this \
conversation to go on. Do not start new work or reply to anyone — just write your notes \
and end the turn.";

View file

@ -47,5 +47,5 @@ to track it:
matrix provisioning, gateway vhosts, and the `hive-priv` client
respectively.
See the top-level `CLAUDE.md`/`docs/` index for the full reading-path
See the top-level `AGENTS.md`/`docs/` index for the full reading-path
map.

View file

@ -80,7 +80,7 @@ struct StartArgs {
/// Working directory for the subagent's session — e.g. a git worktree
/// you've already prepared for it, so a parallel batch of subagents
/// never race on the same working tree. Must exist. Omit to use your
/// work dir, `/agents/<you>/work` (it has no `CLAUDE.md` above it, so the
/// work dir, `/agents/<you>/work` (it has no `AGENTS.md` above it, so the
/// subagent does not load yours); until that directory exists (a container
/// that predates its bind) the daemon's cwd is used. The daemon
/// remembers whichever `dir` you give here against `name`, so a later

View file

@ -31,7 +31,7 @@ pub fn state_dir() -> PathBuf {
}
/// The agent's persistent work dir, a sibling of [`state_dir`]
/// (`/agents/<name>/work`). It has no `CLAUDE.md` above it, so a subagent
/// (`/agents/<name>/work`). It has no `AGENTS.md` above it, so a subagent
/// started here does not load the agent's own.
#[must_use]
pub fn work_dir() -> PathBuf {

View file

@ -853,8 +853,8 @@
"kind": "Panel",
"spec": {
"id": 33,
"title": "CLAUDE.md size by agent",
"description": "Lines in each agent's CLAUDE.md file over time.",
"title": "AGENTS.md size by agent",
"description": "Lines in each agent's AGENTS.md file over time.",
"links": [],
"data": {
"kind": "QueryGroup",

View file

@ -10,7 +10,7 @@
# does NOT change the store path and therefore does NOT force a
# rebuild of every agent container.
#
# Dropped: scripts/, docs/, root-level *.md (README/CLAUDE/TODO/…).
# Dropped: scripts/, docs/, root-level *.md (README/AGENTS/TODO/…).
# Kept (build needs them): .nix, .rs, Cargo.*, branding/,
# frontend/, prompts/, flake.lock. docs/ is deliberately dropped:
# it is shipped to agent containers as its OWN narrow meta-flake