Claude
Skills
Sign in
Back

hooks-session-start-hook

Included with Lifetime
$97 forever

Create a SessionStart hook for Claude Code on the web. Use when setting up a repo so dependencies install and tests/linters run automatically on remote session start.

AI Agents

What this skill does


# /hooks:session-start-hook

Generate a `SessionStart` hook that prepares your repository for Claude Code on the web — installing dependencies, configuring environment variables, and verifying that tests and linters work.

## When to Use This Skill

| Use this skill when... | Use `/hooks:hooks-configuration` instead when... |
|---|---|
| Setting up a repo for Claude Code on the web | Configuring other hook types (PreToolUse, Stop, etc.) |
| Need automatic dependency install in web sessions | Need general hooks knowledge or debugging |
| Want tests/linters verified on session start | Writing custom hook logic from scratch |
| Onboarding a project to remote Claude Code | Understanding hook lifecycle events |

## Context

Detect project stack:

- Lockfiles: !`find . -maxdepth 1 \( -name 'package-lock.json' -o -name 'yarn.lock' -o -name 'pnpm-lock.yaml' -o -name 'bun.lockb' -o -name 'poetry.lock' -o -name 'uv.lock' -o -name 'Cargo.lock' -o -name 'go.sum' -o -name 'Gemfile.lock' \)`
- Project files: !`find . -maxdepth 1 \( -name 'package.json' -o -name 'pyproject.toml' -o -name 'requirements.txt' -o -name 'Cargo.toml' -o -name 'go.mod' -o -name 'Gemfile' -o -name 'pom.xml' \) -o -maxdepth 1 -name 'build.gradle*'`
- Linter configs: !`find . -maxdepth 1 \( -name 'biome.json' -o -name 'biome.jsonc' -o -name '.eslintrc*' -o -name 'eslint.config.*' \)`
- Existing settings: !`find .claude -maxdepth 1 -name 'settings.json' -type f`
- Existing hooks dir: !`find . -maxdepth 2 -type d -name 'scripts'`

## Parameters

| Flag | Default | Description |
|---|---|---|
| `--remote-only` | off | Wrap script in `CLAUDE_CODE_REMOTE` guard — hook exits immediately in local sessions |
| `--no-verify` | off | Skip test/linter verification step in the generated script |

## Execution

### Step 1: Detect project stack

Identify all languages and tooling from the context above.

**Language detection:**

| File Present | Language | Package Manager (from lockfile) |
|---|---|---|
| `package.json` | Node.js | npm (`package-lock.json`), yarn (`yarn.lock`), pnpm (`pnpm-lock.yaml`), bun (`bun.lockb`) |
| `pyproject.toml` | Python | poetry (`poetry.lock`), uv (`uv.lock`), pip (fallback) |
| `requirements.txt` | Python | pip |
| `Cargo.toml` | Rust | cargo |
| `go.mod` | Go | go modules |
| `Gemfile` | Ruby | bundler |
| `pom.xml` | Java | maven |
| `build.gradle*` | Java/Kotlin | gradle |

**Test runner detection:**

| Language | How to Detect | Test Command |
|---|---|---|
| Node.js | `scripts.test` in package.json | `npm test` / `bun test` / etc. |
| Python | `[tool.pytest]` in pyproject.toml, or `pytest` in deps | `pytest` |
| Rust | always available | `cargo test` |
| Go | always available | `go test ./...` |
| Ruby | Gemfile contains `rspec` or `minitest` | `bundle exec rspec` / `bundle exec rake test` |
| Java | pom.xml / build.gradle | `mvn test` / `gradle test` |

**Linter detection:**

| Config File | Linter | Command |
|---|---|---|
| `biome.json` / `biome.jsonc` | Biome | `npx biome check .` |
| `.eslintrc*` / `eslint.config.*` | ESLint | `npx eslint .` |
| `[tool.ruff]` in pyproject.toml | Ruff | `ruff check .` |
| `Cargo.toml` | Clippy | `cargo clippy` |

Report detected stack to user before generating.

### Step 2: Generate hook script

Create the script at `scripts/claude-session-start.sh` (or `.claude/hooks/session-start.sh` if no `scripts/` directory exists).

Use the **Script Template** from [REFERENCE.md](REFERENCE.md). Adapt it by:
1. Including only sections for detected languages
2. Using the correct package manager commands with frozen lockfile flags
3. Using the correct test runner and linter commands
4. Setting appropriate environment variables per language

### Step 3: Configure `.claude/settings.json`

Read existing `.claude/settings.json` if it exists. **Merge** the SessionStart hook — preserve all existing configuration.

If a `SessionStart` hook already exists, ask the user whether to:
- **Replace** the existing SessionStart hook
- **Add alongside** the existing hook (both will run)
- **Abort** and keep existing configuration

Configuration to merge:

```json
{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup",
        "hooks": [
          {
            "type": "command",
            "command": "bash \"$CLAUDE_PROJECT_DIR/scripts/claude-session-start.sh\"",
            "timeout": 120
          }
        ]
      }
    ]
  }
}
```

Use `timeout: 120` (2 minutes) for dependency installation. Adjust path if script is in `.claude/hooks/` instead of `scripts/`.

### Step 4: Finalize

1. Make the script executable: `chmod +x <script-path>`
2. Create `.claude/` directory if needed for settings.json
3. Report summary of what was created

### Step 5: Verify (unless --no-verify)

Run the generated script locally to confirm it executes without errors. Report results.

## Post-Actions

After generating the hook:

1. Suggest committing the new files:
   ```
   scripts/claude-session-start.sh
   .claude/settings.json
   ```
2. If `--remote-only` was NOT used, mention the flag for web-only behavior
3. If the project needs network access beyond defaults, remind about Claude Code web network settings
4. Mention `matcher` options: `"startup"` (new sessions), `"resume"` (resumed), `""` (all events)

## SessionStart Matcher Reference

| Matcher | Fires When |
|---|---|
| `"startup"` | New session starts |
| `"resume"` | Session is resumed |
| `"clear"` | After `/clear` command |
| `"compact"` | After context compaction |
| `""` (empty) | All SessionStart events |

## Agentic Optimizations

| Context | Approach |
|---|---|
| Quick setup, skip verification | `/hooks:session-start-hook --remote-only --no-verify` |
| Full setup with verification | `/hooks:session-start-hook` |
| Web-only with tests | `/hooks:session-start-hook --remote-only` |
| Dependency install commands | Use `--frozen-lockfile` / `ci` variants for reproducibility |
| Test verification | Use `--bail=1` / `-x` for fast failure |
| Linter verification | Use `--max-diagnostics=0` / `--quiet` for pass/fail only |

## Quick Reference

| Item | Value |
|---|---|
| Script location | `scripts/claude-session-start.sh` or `.claude/hooks/session-start.sh` |
| Settings location | `.claude/settings.json` |
| Timeout | 120 seconds (adjustable) |
| Output format | JSON with `hookSpecificOutput.additionalContext` |
| Environment persistence | Via `CLAUDE_ENV_FILE` |
| Remote detection | `CLAUDE_CODE_REMOTE=true` |

Related in AI Agents