spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

agents-md: send the AGENTS.md loaded line to the debug logBrowse files
poteat authored 23 days ago parent 684800b · commit 07df966e931d
5 changed files+23 -13compared with 684800b
Mmods/agents-md/README.md
Mmods/agents-md/hooks/register.ts
Mmods/agents-md/tests/fixtures/started-of.ts
Mmods/agents-md/tests/fixtures/types/started/started.ts
Mmods/agents-md/tests/register.test.ts
@@ -91,7 +91,7 @@
9191 | event | what the hook does |
9292 | --- | --- |
9393 | `session.start` | in every mode: passes the start straight through and floats the usage row for the configured mode, never awaited; the first start of a load logs how a stored `projectInstructions` value is read. The session's start never waits on this plugin |
94-| `prompt.context` | under `claude-md-or-agents-md` and `claude-md-and-agents-md`: walks `$.fs.ancestors` for the `AGENTS.md` files above the working directory and answers them as `project` instruction files, each `@` import its own entry after its file, each placed where a project file of its directory stands (root first, before the first deeper project file, else after the last project file, before memory); files the engine already holds by path or by content are left out; under `claude-md-or-agents-md` it answers nothing when the project has a `CLAUDE.md` of its own (among the handed files, else found by a `$.fs.ancestors` walk, so a `CLAUDE.md` the engine loaded and then withheld still counts), and logs which files it loaded once, and again after a move to another project root; handed unknown files (a hook above rewrote the `claudeMd` text) it adds nothing; the first context of a load sends the load row (counts) and the feature mark; under `managed-only` (matcher: a `project`, `local` or `user` file present): answers the list without those kinds |
94+| `prompt.context` | under `claude-md-or-agents-md` and `claude-md-and-agents-md`: walks `$.fs.ancestors` for the `AGENTS.md` files above the working directory and answers them as `project` instruction files, each `@` import its own entry after its file, each placed where a project file of its directory stands (root first, before the first deeper project file, else after the last project file, before memory); files the engine already holds by path or by content are left out; under `claude-md-or-agents-md` it answers nothing when the project has a `CLAUDE.md` of its own (among the handed files, else found by a `$.fs.ancestors` walk, so a `CLAUDE.md` the engine loaded and then withheld still counts), and names the files it loaded in the debug log (`$.ui.log` with `to: "debug"`: `no CLAUDE.md found; AGENTS.md loaded: <paths>`, nothing in the transcript) once, and again after a move to another project root; handed unknown files (a hook above rewrote the `claudeMd` text) it adds nothing; the first context of a load sends the load row (counts) and the feature mark; under `managed-only` (matcher: a `project`, `local` or `user` file present): answers the list without those kinds |
9595 | `agent.spawn` on `fork: true` | under `claude-md-or-agents-md` and `claude-md-and-agents-md`: a fork the Agent tool starts shares its parent's prompt prefix, so the parent loop's delivered nested files are copied to the fork's loop and not attached to it again (a `/fork` or `/subtask` fork does not raise `agent.spawn` yet and starts from an empty set, as every fork did before; a fork started in the same tool batch as a `Read` inherits that Read's file although its prefix holds a placeholder for it) |
9696 | `tool.call` on `Read` | under `claude-md-or-agents-md` and `claude-md-and-agents-md`, for a file under the session's project root (`$.session.root()`, read live, so `/cd`, a host's directory change and worktree moves are followed and a moved root starts the delivered sets and the fallback decision over; a file elsewhere gets nothing, as the engine attaches no nested `CLAUDE.md` there; and nothing anywhere in a run where the engine attaches nothing to a turn, `--bare` with its `CLAUDE_CODE_SIMPLE` or `CLAUDE_CODE_DISABLE_ATTACHMENTS`, read on every Read through `$.env.get` as the engine reads them on every turn): walks only the directories strictly between the root and the read file (`$.fs.ancestors` with `below: root`, as the engine walks only those for a nested `CLAUDE.md`, never up to the filesystem root again) and attaches their `AGENTS.md` files not yet given to that agent loop, not already among the context's instruction files (by path or, for a project file, by text) and not claimed by a `CLAUDE.md` of the same directory (or imported by one), as `context` after the tool result, framed `Contents of <path>:` byte for byte as the engine frames a nested `CLAUDE.md`, whatever its size; each file once per loop and conversation (the context's recomputation after a compaction or `/clear` starts the count over), the context's files never; a Read that attached files sends the nested row. A `~` or `~/` path is read under the home directory as the Read tool reads it |
9797
@@ -162,8 +162,8 @@
162162 claude plugin test mods/agents-md
163163
164164 `tests/register.test.ts` covers the default mode: a project with `AGENTS.md`
165-alone gets it as a project instruction file and one transcript line naming
166-it, a project with a `CLAUDE.md` of its own is left to the engine without a
167-walk, a failed walk leaves the context as handed, and the start hands
168-`$.telemetry` the mode row alone where a test seats a provider for that
169-noun, and goes on untouched where none is seated.
165+alone gets it as a project instruction file and one debug-log line naming
166+it, with nothing in the transcript, a project with a `CLAUDE.md` of its own is
167+left to the engine without a walk, a failed walk leaves the context as handed,
168+and the start hands `$.telemetry` the mode row alone where a test seats a
169+provider for that noun, and goes on untouched where none is seated.
@@ -154,6 +154,7 @@
154154 .filter(file => file.parent === undefined)
155155 .map(file => file.path)
156156 .join(', '),
157+ { to: 'debug' },
157158 )
158159 }
159160
@@ -6,15 +6,20 @@
66
77 /**
88 * A session that starts untouched beneath the plugins, rooted at SESSION's
9- * working directory, every toast and transcript line they raise kept for the
10- * test to read, on a mock clock the test settles before it reads them.
9+ * working directory, every toast, transcript line and debug-log line they
10+ * raise kept for the test to read, on a mock clock the test settles before it
11+ * reads them.
1112 *
13+ * A `$.ui.log` line lands in `lines` when it is bound for the transcript and
14+ * in `debugLines` when its `to` is `debug`, so a test tells the two apart.
15+ *
1216 * @param on the test's `on`
1317 * @returns the toasts, lines and walks raised, in order, and the clock
1418 */
1519 export function startedOf(on: On): Started {
1620 const toasts: ToastAsked[] = []
1721 const lines: string[] = []
22+ const debugLines: string[] = []
1823
1924 on('session.start', ($, e) => ({ cwd: e.cwd }))
2025
@@ -27,10 +32,11 @@
2732 })
2833
2934 on('ui.log', ($, e) => {
30- lines.push(e.text)
35+ const sink = e.to === 'debug' ? debugLines : lines
36+ sink.push(e.text)
3137
3238 return { value: undefined }
3339 })
3440
35- return { toasts, lines, walks: [], clock: mock.clock(on) }
41+ return { toasts, lines, debugLines, walks: [], clock: mock.clock(on) }
3642 }
@@ -4,12 +4,13 @@
44
55 /**
66 * What the plugins raised while a session ran: each toast as asked for, each
7- * transcript line, the first name of each walk they asked for; `clock`
8- * settles what they floated.
7+ * transcript line, each line sent to the debug log alone, the first name of
8+ * each walk they asked for; `clock` settles what they floated.
99 */
1010 export type Started = {
1111 toasts: ToastAsked[]
1212 lines: string[]
13+ debugLines: string[]
1314 walks: string[]
1415 clock: MockClock
1516 }
@@ -41,7 +41,8 @@
4141
4242 await started.clock.settle()
4343
44- expect(started.lines).toEqual([
44+ expect(started.lines, 'nothing new in the transcript').toEqual([])
45+ expect(started.debugLines).toEqual([
4546 'no CLAUDE.md found; AGENTS.md loaded: /repo/AGENTS.md',
4647 ])
4748 })
@@ -69,6 +70,7 @@
6970
7071 expect(started.walks).toEqual([])
7172 expect(started.lines).toEqual([])
73+ expect(started.debugLines).toEqual([])
7274 })
7375
7476 test('a failed walk leaves the context as handed', async ($, on) => {