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

fix(agents-md): retain instructions after truncated readsBrowse files
7487 authored on Sep 21, 2026 · Alice T'Poteat committed 29 days ago parent ddcb43a · commit 653d32fb7326
2 changed files+73 -2compared with ddcb43a
Mmods/agents-md/hooks/register.ts
Mmods/agents-md/tests/register.test.ts
@@ -223,7 +223,14 @@
223223 ...Files.filesOf(claude),
224224 ]).filter(file => !sent.has(file.path))
225225 const attached = fresh.filter(file => !Frames.isFileAt(file, read))
226- const isWholeRead = e.offset === undefined && e.limit === undefined
226+ const output = result.result
227+ const isPartialText =
228+ output?.type === 'text' &&
229+ (output.file.truncatedByTokenCap ||
230+ output.file.startLine !== 1 ||
231+ output.file.numLines < output.file.totalLines)
232+ const isWholeRead =
233+ e.offset === undefined && e.limit === undefined && !isPartialText
227234
228235 for (const file of fresh) {
229236 const isSent =
@@ -1,4 +1,4 @@
1-import { describe, expect, test, tier } from 'claude-code/testing'
1+import { describe, expect, mock, test, tier } from 'claude-code/testing'
22
33 import Hooks from '../hooks'
44 import Fixtures from './fixtures'
@@ -84,6 +84,70 @@
8484 ).toEqual({ blocks: BLOCKS, instructionFiles: [] })
8585 })
8686
87+ for (const [name, args, file, attaches] of [
88+ [
89+ 'an auto-paginated read',
90+ {},
91+ { content: '# head\nfollow', truncatedByTokenCap: true },
92+ true,
93+ ],
94+ ['an incomplete line range', {}, { content: '# head', numLines: 1 }, true],
95+ ['a complete read', {}, {}, false],
96+ ['an explicit limit', { limit: 1 }, { content: '# head', numLines: 1 }, true],
97+ [
98+ 'an explicit offset',
99+ { offset: 2 },
100+ { content: 'follow the tail rule', numLines: 1, startLine: 2 },
101+ true,
102+ ],
103+ ['an unstructured result', {}, undefined, false],
104+ ] as const) {
105+ test(`a nested AGENTS.md after ${name}`, async ($, on) => {
106+ const dir = `${Fixtures.SESSION.cwd}/nested`
107+ const path = `${dir}/AGENTS.md`
108+ const content = '# head\nfollow the tail rule'
109+ const started = Fixtures.projectOf(
110+ on,
111+ [Fixtures.ancestorOf(dir, 'AGENTS.md', content)],
112+ [],
113+ )
114+
115+ mock.env(on, {})
116+ on('session.cwd', () => ({ value: Fixtures.SESSION.cwd }))
117+ on('tool.call', ($, e) => ({
118+ result:
119+ e.tool === 'Read' && file !== undefined
120+ ? {
121+ type: 'text',
122+ file: Object.assign(
123+ {
124+ filePath: e.file_path,
125+ content,
126+ numLines: 2,
127+ startLine: 1,
128+ totalLines: 2,
129+ },
130+ file,
131+ ),
132+ }
133+ : 'read',
134+ }))
135+
136+ const direct = await $.tool.call({ tool: 'Read', file_path: path, ...args })
137+ const source = { tool: 'Read', file_path: `${dir}/source.ts` } as const
138+ const after = await $.tool.call(source)
139+ const repeated = await $.tool.call(source)
140+
141+ expect(direct.context).toBeUndefined()
142+ expect(after.context).toEqual(
143+ attaches ? [`Contents of ${path}:\n\n${content}`] : undefined,
144+ )
145+ expect(repeated.context).toBeUndefined()
146+
147+ await started.clock.settle()
148+ })
149+ }
150+
87151 test(
88152 'the start sends the mode row alone: no walk, no toast',
89153 { plugins: [Fixtures.RECORDING] },