Skip to content

Commit 5248c1a

Browse files
jancurnclaude
andauthored
Improve grep instructions snippet context and formatting (#143)
* Increase grep instructions snippet context to 40 chars and wrap in backtick guards - Changed context size from 35 to 40 characters before/after match - Wrapped instruction snippets in backtick guards in human output for clarity - Normalized fallback snippet length to 90 chars to match increased context - Updated test bounds accordingly https://claude.ai/code/session_01D93T3gBkbFFoeiSaK2MG89 * Add changelog entry for grep snippet improvements https://claude.ai/code/session_01D93T3gBkbFFoeiSaK2MG89 * Use quadruple backtick guards for instructions snippets Single backticks would break when instructions contain markdown with backticks. Quadruple backticks are safe even against triple-backtick code fences commonly found in MCP server instructions. https://claude.ai/code/session_01D93T3gBkbFFoeiSaK2MG89 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 324793a commit 5248c1a

3 files changed

Lines changed: 9 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1616
### Changed
1717

1818
- Reordered `mcpc --help` to show Commands before Options for better discoverability
19+
- Increased `grep` instructions snippet context from 35 to 40 characters and wrapped snippets in backtick guards for clearer AI agent consumption
1920

2021
### Security
2122

src/cli/commands/grep.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ function buildInstructionsSearchText(instructions: string, sessionName: string):
128128

129129
/**
130130
* Extract a short snippet from instructions text around the first match.
131-
* The snippet is at most ~70 chars longer than the matched text, with ellipsis
131+
* The snippet is at most ~80 chars longer than the matched text, with ellipsis
132132
* added when the snippet doesn't reach the start/end of the instructions.
133133
* Whitespace (including newlines) is normalized to single spaces.
134134
*/
@@ -162,7 +162,7 @@ export function extractInstructionsSnippet(
162162
matchEnd = matchStart + needle.length;
163163
}
164164

165-
const contextSize = 35;
165+
const contextSize = 40;
166166
let snippetStart = Math.max(0, matchStart - contextSize);
167167
let snippetEnd = Math.min(normalized.length, matchEnd + contextSize);
168168

@@ -268,7 +268,7 @@ async function searchClient(
268268
const snippet = extractInstructionsSnippet(instructionsText, pattern, options);
269269
// Fallback: if snippet extraction fails (e.g. match was on session name prefix), show truncated text
270270
matchedInstructions =
271-
snippet || instructionsText.replace(/\s+/g, ' ').trim().slice(0, 80) + '…';
271+
snippet || instructionsText.replace(/\s+/g, ' ').trim().slice(0, 90) + '…';
272272
}
273273

274274
return {
@@ -421,7 +421,7 @@ function formatGrepResultHuman(
421421
pattern && options
422422
? highlightMatch(result.instructions, pattern, options)
423423
: result.instructions;
424-
lines.push(`${indent}${chalk.bold('Instructions:')} ${chalk.dim(snippet)}`);
424+
lines.push(`${indent}${chalk.bold('Instructions:')} ${chalk.dim('````' + snippet + '````')}`);
425425
}
426426
lines.push(
427427
...formatResultSection('Tools', result.tools, formatToolLine as (item: never) => string, indent)

test/unit/cli/grep.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ describe('extractInstructionsSnippet', () => {
8282
expect(result).toContain('mmm');
8383
expect(result!.startsWith('\u2026')).toBe(true);
8484
// total length should be roughly pattern.length + 50
85-
expect(result!.length).toBeLessThanOrEqual('mmm'.length + 80);
85+
expect(result!.length).toBeLessThanOrEqual('mmm'.length + 90);
8686
});
8787

8888
it('adds trailing ellipsis when match is far from the end', () => {
@@ -101,7 +101,7 @@ describe('extractInstructionsSnippet', () => {
101101
expect(result).toContain('lazy');
102102
expect(result!.startsWith('\u2026')).toBe(true);
103103
expect(result!.endsWith('\u2026')).toBe(true);
104-
expect(result!.length).toBeLessThanOrEqual('lazy'.length + 80);
104+
expect(result!.length).toBeLessThanOrEqual('lazy'.length + 90);
105105
});
106106

107107
it('normalizes whitespace including newlines', () => {
@@ -164,8 +164,8 @@ describe('extractInstructionsSnippet', () => {
164164
const result = extractInstructionsSnippet(text, pattern, {});
165165
expect(result).toBeTruthy();
166166
expect(result).toContain(pattern);
167-
// Snippet should be at most about pattern.length + 50 + 2 (for ellipsis chars)
168-
expect(result!.length).toBeLessThanOrEqual(pattern.length + 80);
167+
// Snippet should be at most about pattern.length + 80 + 2 (for ellipsis chars)
168+
expect(result!.length).toBeLessThanOrEqual(pattern.length + 90);
169169
});
170170

171171
it('handles case-insensitive regex', () => {

0 commit comments

Comments
 (0)