Creating and developing startup hooks for Claude Code on the web. Use when the user wants to set up a repository for Claude Code on the web, create a SessionStart hook to ensure their project can run tests and linters during web sessions.
Create SessionStart hooks that install dependencies so tests and linters work in Claude Code on the web sessions.
{
"session_id": "abc123",
"source": "startup|resume|clear|compact",
"transcript_path": "/path/to/transcript.jsonl",
"permission_mode": "default",
"hook_event_name": "SessionStart",
"cwd": "/workspace/repo"
}
#!/bin/bash
set -euo pipefail
echo '{"async": true, "asyncTimeout": 300000}'
npm install
The hook runs in background while the session starts. Using async mode reduces latency, but introduces a race condition where the agent loop might depend on something that is being done in the startup hook before it completed.
Available environment variables:
$CLAUDE_PROJECT_DIR - Repository root path$CLAUDE_ENV_FILE - Path to write environment variables$CLAUDE_CODE_REMOTE - If running in a remote environment (i.e. Claude code on the web)Use $CLAUDE_ENV_FILE to persist variables for the session:
echo 'export PYTHONPATH="."' >> "$CLAUDE_ENV_FILE"
Use $CLAUDE_CODE_REMOTE to only run a script in a remote env:
if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then
exit 0
fi
Make a todo list for all the tasks in this workflow and work on them one after another
Find dependency manifests and analyze them. Examples:
package.json / package-lock.json → npmpyproject.toml / requirements.txt → pip/PoetryCargo.toml → cargogo.mod → goGemfile → bundlerAdditionally, read though any documentation (i.e. README.md or similar) to see if you can get additional context on how the environment setup works
Create a script that installs dependencies.
Key principles:
mkdir -p .claude/hooks
cat > .claude/hooks/session-start.sh << 'EOF'
#!/bin/bash
set -euo pipefail
echo '{"async": true, "asyncTimeout": 300000}'
# Install dependencies here
EOF
chmod +x .claude/hooks/session-start.sh
Add to .claude/settings.json (create if doesn't exist):
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.sh"
}
]
}
]
}
}
If .claude/settings.json exists, merge the hooks configuration.
Run the hook script directly:
CLAUDE_CODE_REMOTE=true ./.claude/hooks/session-start.sh
IMPORTANT: Verify dependencies are installed and script completes successfully.
IMPORTANT: Figure out what the right command is to run the linters and run it for an example file. No need to lint the whole project. If there are any issues, update the startup script accordingly and re-test.
IMPORTANT: Figure out what the right command is to run the tests and run it for one test. No need to run the whole test suite. If there are any issues, update the startup script accordingly and re-test.
Make a commit and push it to the remote branch
We're all done. In your last message to the user, Provide a detailed summary to the user with the format below: