Back to blog
Engineering April 14, 2025 12 min read

FORG + Claude Code: Deep Integration Guide

Everything you need to know about connecting FORG to Claude Code. What data flows, how session tracking works, how to configure hooks, and how to attribute costs to individual developers and projects.


How the Integration Works

FORG integrates with Claude Code via the hooks system. Claude Code exposes 7 hook event types: PostToolUse, PreCompact,PreToolUse, SessionEnd, SessionStart,Stop, and UserPromptSubmit. FORG uses all seven.

When Claude Code fires a hook event, it invokes a shell script with the event payload as JSON on stdin. FORG's agent binary reads that payload, extracts the metadata (tokens, cost, model, latency), and emits a signal to the Rule Engine. The entire path adds <2ms to the hook execution time.

Critically: FORG reads the metadata from the event, not the payload. When a PostToolUse event fires for an LLM call, the event contains usage statistics — not the prompt or completion content. FORG never touches the conversation content.

Prerequisites

  • FORG agent installed: npm install -g forg-agent
  • Active FORG license (Solo plan or higher)
  • Claude Code installed and authenticated
  • macOS, Linux, or Windows (WSL2)

Step 1: Install and Activate

# Install the FORG agent
npm install -g forg-agent

# Verify installation
forg --version

# Activate with your license key
# (Get yours at forg.pro/dashboard/license)
forg activate lic_a1b2c3d4e5f6a7b8c9d0

# The activation process:
# 1. Verifies your license with the License Worker
# 2. Derives a session key using HKDF-SHA256
# 3. Stores the bundle in OS-native keystore
#    (macOS Keychain / Linux libsecret / Windows DPAPI)
# 4. Configures Claude Code hooks automatically

After activation, run forg status to verify:

$ forg status

FORG Agent v3.0.3
License:    lic_a1b2c3...  [active]
Plan:       Solo
Adapters:   claude-code [active]
Signals:    247 emitted, 0 failed
Last emit:  2s ago
Dashboard:  forg.pro/dashboard

Step 2: Verify Hook Installation

FORG automatically writes to your Claude Code settings file at~/.claude/settings.json. Check that the hooks are present:

$ cat ~/.claude/settings.json | jq '.hooks'
{
  "PostToolUse": [
    {
      "matcher": "Bash|Write|Edit|Read",
      "hooks": [
        {
          "type": "command",
          "command": "forg emit --event PostToolUse"
        }
      ]
    }
  ],
  "SessionStart": [
    {
      "hooks": [
        {
          "type": "command",
          "command": "forg emit --event SessionStart"
        }
      ]
    }
  ],
  "SessionEnd": [
    {
      "hooks": [
        {
          "type": "command",
          "command": "forg emit --event SessionEnd"
        }
      ]
    }
  ]
  // ... all 7 event types
}

All hooks are marked _forg_managed in the hook metadata. If you have a pre-existing custom ~/.claude/statusline.sh, FORG will detect it and warn you at activation — it won't overwrite it.

Step 3: Configure Dimensions

Dimensions are the metadata fields that let you slice your usage data by developer, project, team, and environment. Configure them in~/.forg/config.yaml:

# ~/.forg/config.yaml
dimensions:
  user: "${USER}@yourcompany.com"   # auto-detected from git config
  team: "backend"                    # your team name
  environment: "development"         # development, staging, production

# Per-project overrides in .forg/project.yaml at repo root
# project: "backend-api"
# team: "backend"
# environment: "development"

For teams, the recommended setup is:

  1. Each developer sets their user dimension to their work email
  2. Each repo has a .forg/project.yaml at the root withproject and team set
  3. FORG auto-detects the environment from git branch name (main/master → production, develop → staging, other → development)
# .forg/project.yaml (checked in at repo root)
project: "payment-service"
team: "payments"
# environment auto-detected from branch

What Data Flows: A Signal Walkthrough

Let's trace exactly what happens when you run a Claude Code session.

Session start: Claude Code fires SessionStart. FORG generates a sess_ prefixed UUID and opens a session record. No API call to Claude has been made yet.

// SessionStart signal
{
  "event": "SessionStart",
  "session_id": "sess_01hwxyzabc123",
  "ts": 1716840000000,
  "adapter": "claude-code",
  "dimensions": {
    "user": "alice@company.com",
    "project": "payment-service",
    "team": "payments",
    "environment": "development"
  }
}

After each LLM call: PostToolUse fires with usage statistics. This is where the token and cost data flows:

// PostToolUse signal (after an LLM call)
{
  "event": "PostToolUse",
  "session_id": "sess_01hwxyzabc123",
  "ts": 1716840045000,
  "adapter": "claude-code",
  "model": "claude-sonnet-4-5",
  "tokens": {
    "input": 2847,
    "output": 412,
    "cache_read": 1200,
    "cache_write": 0
  },
  "cost_usd": 0.00892,
  "latency_ms": { "ttft": 312, "total": 1847 },
  "dimensions": { ... }
}

Session end: SessionEnd fires when you close Claude Code or explicitly end the session. FORG closes the session record and computes session-level aggregates (total tokens, total cost, duration, call count).

Session Tracking and Attribution

FORG uses session IDs to group all API calls in a single Claude Code session. This gives you session-level analytics: cost per session, tokens per session, duration, and whether sessions ended cleanly or were abandoned (idle timeout).

In the FORG dashboard, the Sessions view shows:

  • All active and recent sessions across your team
  • Per-session cost, tokens, and duration
  • Sessions that hit budget rules (highlighted)
  • Abandoned sessions (terminated by idle timeout vs. explicit end)
  • Session cost by developer, project, and day

Cost Attribution

With dimensions configured correctly, you can answer:

// Example FORG Atlas queries once you have 30 days of data:

"What is our total AI spend by team this month?"
→ Backend: $340, Frontend: $180, DevOps: $95

"Which project has the highest cost per session?"
→ payment-service: $0.47/session (high context)

"Which developer has the most sessions per day?"
→ alice: 12 sessions/day (avg), bob: 8, charlie: 6

"What percentage of our spend is going to production?"
→ 3% (environment=production), 89% development, 8% CI

Troubleshooting Common Issues

Signals not appearing in dashboard

# Check agent status
forg status

# Tail signals in real-time
forg tail

# Check for errors
forg logs --last=50

# Force re-emit any pending signals
forg flush

Hooks not firing

# Verify hooks are installed
cat ~/.claude/settings.json | jq '.hooks | keys'

# Re-install hooks (won't overwrite custom hooks)
forg install-hooks --adapter=claude-code

# Test a hook manually
echo '{"event":"SessionStart"}' | forg emit --event SessionStart --stdin

Multiple machines

Your license supports up to 3 machines on the Solo plan (unlimited on Team+). Run forg activate on each machine with the same license key. Session IDs are globally unique across machines.

What's Next

Once you have a week of data flowing, explore the FORG dashboard:

  • Observe tab: Signal timeline, session view, cost breakdown by model/user/project
  • Control tab: Create your first budget rule, test it in warn-only mode
  • Optimize tab: Cost intelligence insights, FORG Atlas queries

The FORG docs have reference documentation for every config option, rule type, and API endpoint. Join our Discord if you run into anything.