Skip to content
Giallo

SessionStart: restore context after compaction

Choose what to add with SessionStart after startup, resume, and compaction. Git, persistent instructions, and environment, with small, verifiable output.

Reading time: 11 min

Claude Code SessionStart: event, control and result in the development workflow

SessionStart is the Claude Code event useful for adding dynamic context when a session starts or resumes. It can be filtered on the startup pattern, including compact, to provide guidance after the compaction. It is suitable for small and verifiable information, such as the current branch or work checklist reference; static instructions already have their path in memory files. SessionStart in the reference.

The goal is not to reconstruct the whole conversation at every shot. A hook should retrieve what it takes from the project and indicate where it came from. Copying large logs, all environment variables or entire folders can add noise and make useless data available. The Guide to the Claude Code Hooks introduces event, matcher and handler; here the theme is the context worth reinserting.

Verified Sources on 9 October 2026. Examples are hypothetical and snippets have not been run in this guide. Hooks are not attributed a perfect memory nor a measured cost reduction.

In summary

  • SessionStart can distinguish start-up, take-up, and match-action.
  • Persistent instructions and dynamic data have different responsibilities.
  • The status of the job must live in verifiable files, in addition to the conversation.
  • The output of the hook should be limited to the data needed for recovery.
  • CLAUDE_ENV_FILE serves the session environment, not to rewrite the personal shell.

What changes when the context is compacted?

The compaction produces a synthetic representation of the work to allow the continuation of the session. It should not be confused with a complete archive or even a universal deletion of persistent instructions. Memory documentation describes file loading and post-comaction behavior; starting with the idea that everything is lost often leads to unnecessary copies. Memory of Claude Code.

The practical problem is to orient yourself correctly: which target remains active, which files contain the status, and which controls are really finished? A small reference may be more useful than a repetition of the summary. If the repository keeps a task document, the agent can read it instead of receiving a partial copy generated by a script.

Durable information needs to be updated when the facts happen. A hook performed at the shoot cannot invent a test result never recorded nor know which decision was made off the project. That is why the quality of the written state counts before the quality of the message entered by the hook.

What information belongs to CLAUDE.md?

Stable instructions such as project commands, module responsibilities, and conventions can live in a memory file. They are different from a branch that changes during work or from a suite still running. The documentation recommends the memory path for static context that does not need scripts. SessionStart and Static Context.

Don't turn the hook into a second source of contradictory truth. If the project document says to use a package manager and the script suggests another command, the recovery receives two incompatible instructions. Keep the rules in one place and have only the necessary dynamic reference or data added to the hook.

A convention in the instruction file remains context. To prevent a class of operations you need an actual check, such as a permission rule or PreToolUse for Protected Files. Rereading "do not edit this folder" after compaction is not equivalent to technically blocking a tool call.

How to distinguish status, proof and reminder?

A status data describes the situation of the project: branch, modified files, active task. One Test documents a completed audit, with relevant command and review. A reminder indicates an activity to be performed. Mixing these three elements makes it easy to interpret “execute the tests” as “the tests have been performed”.

Information Suitable source Useful Formulation Limit
Current Branch Git Branch read at startup Does not describe the full content
Active target Task Document File reference and section Depends on the file update
Verification concluded Result of the check Command, Outcome and Verified Can be overcome by new edits
Pending activity Checklist To be performed after shooting It's not a test
Stable rule Instruction file Project Convention It is not a technical gate

The message must retain the distinction. "Previous result to be reconfirmed if files have changed" is more accurate than "green tests". For feedback after edits, PostToolUse for formatting and testing explains how to collect an outcome that belongs to current work.

A little hook that only reads the branch

This shell example adds a limited dynamic data. Requires Git and CLAUDE_PROJECT_DIR, does not read customer files and does not print the full state of the environment. It is an educational example not executed. In a real project you should also try the case of detached HEAD and that of a non-Git directory.

#!/bin/sh
set -eu
project_dir=${CLAUDE_PROJECT_DIR:?Progetto non disponibile}
if branch=$(git -C "$project_dir" branch --show-current 2>/dev/null); then
  if [ -n "$branch" ]; then
    printf 'Contesto dinamico: branch corrente %s.\n' "$branch"
  else
    printf 'Contesto dinamico: nessun branch nominato attivo.\n'
  fi
else
  printf 'Contesto dinamico: branch non disponibile.\n'
fi

The script returns an orientation, not a guarantee that that branch is clean or ready for a merge. Even the branch name can contain confidential information: in the real project it uses names that do not carry personal data and evaluates whether it is necessary to enter it in the context of the model.

The following recording selects the shot after compaction. It integrates the block into the project settings and calls the script back to the declared path. Reinsertion of context.

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "compact",
        "hooks": [
          {
            "type": "command",
            "command": "sh \"$CLAUDE_PROJECT_DIR/.claude/hooks/session_context.sh\""
          }
        ]
      }
    ]
  }
}

Startup, resume and compact: when to use each filter?

A piece of information needed at each start can be associated with the appropriate pattern or a larger matcher. A required orientation only after compaction can use compact. The reference lists the supported motifs and the field on which the matcher operates; the choice must be compared with the session and the version of the player. Matcher SessionStart.

Do not duplicate the same output in multiple handlers for no reason. Configurations can be distributed between user, project, and local scopes: a personal copy of the script and a shared copy can produce two identical messages. In /hooks Check which recordings are actually present.

The useful test includes new start, recovery and relevant compaction. It is not enough to see the message once: if the requirement concerns compact, you have to observe that path. When the hook does not appear or start at the wrong time, Hooks debugging helps to check the filter before changing the script.

What are PreCompact and PostCompact?

The events directly related to the compaction have a contract distinct from SessionStart. They may be useful for reacting before or after the transition, but they are not an invitation to automatically print the entire transcript. The reference describes what data and outcomes are supported by each event. PreCompact and PostCompact.

The choice depends on the effect. If you want a dynamic data when resuming work, SessionStart may be enough. If you need to observe the compaction step for a local process, use the corresponding event and a compatible handler. Do not assume that a valid JSON response for one event has the same function in another.

A message before the compaction is not automatically persistent memory. If the fact has to survive, save it in the appropriate document with an explicit procedure. Do not perform indiscriminate saving of conversation data: they often contain information that should not be replicated in other files or services.

How to limit output without losing important information?

Start with the question that the message must solve: “Where do I read the status of the task?” or "Which branch is active?". If two lines are enough, don't add a list of all the files in the repository. A reference to an updated document allows for targeted reading; a long copy can become obsolete as soon as it resumes work.

To measure the volume, save the synthetic output in a test file and count characters or words. This measures how much text the script adds, not how many tokens will be billed or the process saved. Costs depend on overall use; documentation does not offer a universal percentage reduction through a hook. Cost management.

Those who want to observe the context can read Token Weather. The display is about context window indicators and thresholds: it should not be used to infer that the instructions are correct or that all task information has been retained.

How to use CLAUDE_ENV_FILE with a clear boundary?

CLAUDE_ENV_FILE is a path provided to make variables available to subsequent Bash operations of the session, according to the documented contract. It does not mean permanently changing the profile of the personal shell. Its use must be separated from the output that becomes context for Claude. Persistence of session variables.

Don't print out all the variables to see if the mechanism works. They may contain secrets or credentials. If the project needs a non-sensitive variable, define its name, allowed value, and where it needs to be available. Use an explicit list instead of copying the computer environment.

Writing to an environment file also requires correct quotation. A value from a project file must not be executed as an arbitrary shell. When the requirement really concerns bootstraps and prerequisites, it evaluates whether a dedicated setup command is clearer than the repeated work at each SessionStart.

Two job shoots in Italian companies

Hypothetical, untested example: a digital agency in Genoa develops a portal with more active branches. After compaction he wants Claude to read the checklist of the current request, instead of reconstructing it from the file name. The hook inserts the branch and reference to the task document. The checklist distinguishes concluded checks and pending tasks; new edits may make a previous test passed and should be noted.

Hypothetical, untested example: an SME from Vicenza works on an importer for synthetic warehouse data. Some operations require local service, others do not. The team keeps in the task which tests require the service and which environment is active. SessionStart adds a short orientation; it does not print configurations, passwords, or the dataset. Upon resuming, the agent knows where to read the prerequisites, without receiving the entire archive.

The difference between cases is the useful dynamic data: in the first branch and request, in the second environment and available evidence. There is no universal message to copy in all companies. The recovery must follow the structure of the process that the team has chosen.

What errors make the context inconsistent?

The most common is to use two sources of truth: a document and a script describing the same state with different words. Others are copying previous results such as current, printing large logs, confusing context outputs and environment variables, and ascribing a hook to a technical block it does not possess.

A test of recovery with contradictory information

In a synthetic repository, prepare a checklist indicating a pending test and an earlier test output. After resuming it checks that the hook message does not turn the pending test into a positive outcome. The document must clearly retain the provenance and status of the information.

If the stream uses agents, Hooks for subagent and team adds the liability issue: everyone needs to know which status files they can update. For conclusion, Stop hook without loop describes how to ask for a finite verification without making incomplete memory an infinite request to continue.

When does a given reinsert become obsolete?

The branch read at shooting may change later in the same session. A reference to the task may remain correct while its content is updated. The hook message describes the moment it was produced: it is not a continuous sync stream.

It therefore indicates provenance and does not attribute permanent validity to the text. When the next decision depends on that data, read it back from the source. SessionStart orients the work; Git and the task document remain the places to check the current status.

How to adopt SessionStart without weighing down the workflow?

Start with dynamic information and a recovery path. Try the positive case, the one without the data and the one where the command fails. Check that the text is small and does not replicate instructions already loaded. Add new information only if they resolve an observed uncertainty, and keep the reason for the choice in the repository.

Mods by Claude can offer interfaces to observe the state of the session, but there is no need to introduce a plugin for a few lines orientation. The simplest form remains useful when producing correct data and has an understandable limit.

For projects where agents and people share many tasks, designing AI agents may include status files, responsibilities, and resume checks. The result to be sought is a conscious continuation: stable instructions in the right place, current dynamic data and evidence that retains their meaning.

Giallo Studio guides: methodology and sources

How we apply it in the company

Related resources

AI consulting services and process automation

FAQ

Can SessionStart activate after compaction?

Yes, the compact matcher lets you select that reason for starting the session. The script can add dynamic context relevant to resuming the work.

Do you always need to reinsert all of CLAUDE.md?

No. Instruction files have their own loading and memory rules. The hook should mostly add dynamic information that is not already available.

What output is useful for context?

The branch, a brief summary of work status, or references to a checklist can help. State where the data comes from and limit the amount inserted.

Does CLAUDE_ENV_FILE change my personal shell?

It is not a permanent change in the user's shell configuration. It is used to make variables available to subsequent session operations according to the documented contract.

Does compaction guarantee perfect memory?

No. A summary is not a complete archive and a hook does not automatically reconstruct every detail. The important state must also live in verifiable files.

Can I print all the environment variables?

It is a choice to avoid: they may contain credentials or confidential data. If you need environment, use an explicit list of non-sensitive values.

Put it into practice

Let's turn this guide into your first live workflow.

Tell us what process you want to lighten: we evaluate feasibility, return and first operational step.