The context system assembles the environment information that gets injected into the system prompt at the start of each conversation. It is defined in src/context.ts and provides two memoized functions: getSystemContext() for repository/environment state and getUserContext() for user-specific configuration like CLAUDE.md files.
System Context
getSystemContext() gathers environment information that gives the model awareness of the current project state.
export const getSystemContext = memoize(
async (): Promise<{ [k: string]: string }> => {
const gitStatus = // ...fetch git info
const injection = // ...cache breaker (ant-only)
return {
...(gitStatus && { gitStatus }),
...(injection && { cacheBreaker: `[CACHE_BREAKER: ${injection}]` }),
}
},
)Git Status
When the project is a git repository and git instructions are not disabled, getSystemContext calls getGitStatus() which runs several git commands in parallel:
git status output, truncated to 2000 characters.git config user.name.The git status is prefixed with a note that it is a snapshot from conversation start and will not update during the conversation. If the status exceeds 2000 characters, it is truncated with a message suggesting the model use BashTool for the full output.
const [branch, mainBranch, status, log, userName] = await Promise.all([
getBranch(),
getDefaultBranch(),
execFileNoThrow(gitExe(), ['status', '--short'], ...),
execFileNoThrow(gitExe(), ['log', '--oneline', '-n', '5'], ...),
execFileNoThrow(gitExe(), ['config', 'user.name'], ...),
])Cache Breaker
Behind the BREAK_CACHE_COMMAND feature flag, an internal-only system prompt injection can be set via setSystemPromptInjection(). This is used for ephemeral debugging and forces cache invalidation on the API side.
Skipped Scenarios
Git status is skipped in two cases:
- CCR (Claude Code Remote): the
CLAUDE_CODE_REMOTEenv var is set, avoiding unnecessary overhead on session resume - Git instructions disabled: the user has opted out via
shouldIncludeGitInstructions()settings
User Context
getUserContext() loads user-facing configuration, primarily CLAUDE.md files and the current date.
export const getUserContext = memoize(
async (): Promise<{ [k: string]: string }> => {
const claudeMd = shouldDisableClaudeMd
? null
: getClaudeMds(filterInjectedMemoryFiles(await getMemoryFiles()))
setCachedClaudeMdContent(claudeMd || null)
return {
...(claudeMd && { claudeMd }),
currentDate: `Today's date is ${getLocalISODate()}.`,
}
},
)CLAUDE.md Loading
The CLAUDE.md loading pipeline:
getMemoryFiles(): discovers CLAUDE.md files from the directory hierarchy (home directory, project root, current directory)filterInjectedMemoryFiles(): removes files that were injected by other mechanismsgetClaudeMds(): reads and concatenates the file contents
CLAUDE.md files are the primary mechanism for users to provide project-specific instructions, coding conventions, and context to the model. They are loaded from multiple locations and merged in order of specificity.
Disable Conditions
CLAUDE.md loading is disabled when:
CLAUDE_CODE_DISABLE_CLAUDE_MDSenv var is truthy: hard off, always--baremode is active AND no--add-dirdirectories are specified. Bare mode means "skip what I didn't ask for," but honors explicit--add-dirflags
Caching for Classifier
The loaded CLAUDE.md content is cached via setCachedClaudeMdContent() for use by the auto-mode classifier (yoloClassifier.ts). This breaks a circular dependency: the classifier needs CLAUDE.md content, but importing the claudemd module directly would create a cycle through permissions/filesystem -> permissions -> yoloClassifier.
Memoization Strategy
Both context functions use lodash memoize() with no arguments, meaning they compute once per process lifetime and cache the result. This is appropriate because:
- Git status and CLAUDE.md content represent the state at conversation start
- The model is told explicitly that git status is a snapshot and will not update
- For long-running sessions, the cache can be cleared via
getUserContext.cache.clear()andgetSystemContext.cache.clear()
The setSystemPromptInjection() function clears both caches immediately when the injection value changes, ensuring the cache breaker takes effect on the next query.
Context Injection Flow
The context values flow into the system prompt through the query pipeline:
getSystemContext() ---> appendSystemContext() ---> System Prompt
getUserContext() ---> prependUserContext() ---> (sent to API)System context (git status) is appended to the system prompt. This places it after the base instructions, giving the model awareness of the repository state without interfering with the core prompt structure.
Diagnostic Logging
Both context functions emit structured diagnostic logs via logForDiagnosticsNoPII:
system_context_started/system_context_completedwith duration and content flagsuser_context_started/user_context_completedwith duration and content lengthgit_status_started/git_status_completedwith truncation infogit_commands_completedwith individual command timings
These logs contain no PII (personally identifiable information) and are used for performance monitoring and debugging context assembly latency.