iTranslated by AI
Claude Code and Context Engineering: Automating Context Provision with Custom Commands
This is @dyoshikawa.
I added a custom slash command to Claude Code, and it worked out quite well, so I'd like to introduce it.
The Importance of Context Engineering
When working on AI coding, I feel it's a game of how accurately you can provide context to the AI and how well you can automate that process. Recently, the term "Context Engineering" seems to have emerged.
In 2025, models in the world have extremely high intelligence. However, even the smartest humans cannot work effectively without the context of what is being asked of them. "Prompt Engineering" emerged as a term describing efforts to describe tasks in an ideal format for LLM chatbots. "Context Engineering" is the next level of this; it's about doing this automatically in dynamic systems. It requires more subtlety and has become virtually the most important job for engineers building AI agents.
I want to provide good context about the work done so far after using /clear
As you interact with Claude Code, context naturally accumulates, but when the context exceeds a certain length, the LLM's performance degrades. The "context window on the spec sheet" and the "practical context window" are completely different.
This phenomenon is sometimes referred to as the "pit of death." I introduce this in the following article:
Once the pit of death starts to occur, you reset the context. In Claude Code's case, you use the /clear slash command. However, to make subsequent prompts effective, you want to provide an overview of "what has been done so far."
Solve with Custom Slash Commands
Explaining the "story so far" and giving instructions like "I've done this much, please do XX next" every time is troublesome, so I automated it by creating custom commands.
You can create commands simply by creating a .claude/commands/*.md file in your user space or project space.
Is /compact not good enough?
Claude Code has a built-in /compact command that can compress the conversation history up to that point.
While this is a viable option, I had some concerns.
Firstly, I want to avoid including trial-and-error conversations that should be discarded (or rather, that I want to discard) from the context. /compact might include these. If a history of back-and-forth conversations, such as "Let's go with approach A" and then "Oh, that didn't work, so let's go with the opposite approach B," is compressed, it might leave a contradictory narrative that could confuse the LLM. From this perspective, I believe that changes confirmed by git commit are tentatively fixed and serve as the essence of the context that should be provided.
Also, though this is not the main reason, the /compact command feels unstable and seems to bug out in places. On several occasions, when I gave additional instructions while waiting for /compact to finish, the terminal flickered uncontrollably, making it impossible to operate.
Procedure
Creating the /analyze-diff command
I created a custom slash command as shown below. This is an example of creating it in the user space. If your team members approve, you could also put it under your project and manage it with Git.
## 0. Variable Definition
Define the $TARGET_BRANCH variable according to the pseudo-code below.
```
if ($ARGUMENTS == null) {
// If no arguments, store the default branch
TARGET_BRANCH=$(git remote show origin | grep "HEAD branch" | cut -d' ' -f5)
} else {
TARGET_BRANCH=$ARGUMENTS
}
```
## 1. Update Code
Merge the latest code from the $TARGET_BRANCH remote branch into the current branch.
```bash
git fetch
git merge origin/$TARGET_BRANCH
```
## 2. Analyze Branch Differences
Analyze the differences between the origin/$TARGET_BRANCH branch and the current branch using `git diff`, and output:
- Overall summary of specification changes
- Changes in each file
This pseudo-code, which is a mix of JS and Bash, instructs to define the $TARGET_BRANCH variable. Arguments passed to a slash command like /my-command arg can be accessed as $ARGUMENTS within the command file (or rather, the system prompt instructs it to interpret it this way).
If an argument is provided, that branch is used; otherwise, the default branch is stored. Additionally, it updates the current branch with the latest from the target branch. Some people might not like this, but I prefer to update frequently, so I included it.
Then comes the main process: comparing the differences between the target branch and the current branch. It analyzes the differences and outputs an overall summary of specification changes and changes in each file. By explicitly outputting this, it remains as useful context for subsequent interactions.
I've been using it, and so far, it seems to be working quite well.
Setting Permissions
If necessary, add the following permissions.allow to your user or project's settings.json or settings.local.json to streamline automation.
{
"permissions": {
"allow": [
// ...
"Bash(git diff:*)",
"Bash(git fetch)",
"Bash(git merge origin/:*)",
// ...
]
}
}
I hope this was helpful.
Discussion