AI Agent Code
  • Go 99.6%
  • Makefile 0.4%
Find a file
Justin Hammond 0ce6f8b0a7
All checks were successful
Build & Release / build (push) Successful in 1m4s
Build & Release / test (push) Successful in 1m33s
Extract shared protocol constants into pkg/siemserver/constants.go
Record types, event names, sources, violation types, HTTP headers,
and compliance actions are now exported constants consumable by both
the agent and applications importing the server package.
2026-03-22 23:50:26 +08:00
.forgejo/workflows Remove auto-update infrastructure in favor of MDM-managed deployments 2026-03-22 17:59:29 +08:00
cmd Extract shared protocol constants into pkg/siemserver/constants.go 2026-03-22 23:50:26 +08:00
docs Remove auto-update infrastructure in favor of MDM-managed deployments 2026-03-22 17:59:29 +08:00
internal Extract shared protocol constants into pkg/siemserver/constants.go 2026-03-22 23:50:26 +08:00
pkg/siemserver Extract shared protocol constants into pkg/siemserver/constants.go 2026-03-22 23:50:26 +08:00
.gitignore Add organization compliance scanner, managed config, hooks, and demo server 2026-03-21 19:30:56 +08:00
.goreleaser.yaml Remove auto-update infrastructure in favor of MDM-managed deployments 2026-03-22 17:59:29 +08:00
CLAUDE.md Remove auto-update infrastructure in favor of MDM-managed deployments 2026-03-22 17:59:29 +08:00
doc.go Add module doc.go for pkg.go.dev and MIT license 2026-03-22 20:07:58 +08:00
go.mod Remove auto-update infrastructure in favor of MDM-managed deployments 2026-03-22 17:59:29 +08:00
go.sum Refactor server into importable Huma library with compliance and reliability fixes 2026-03-22 02:32:09 +08:00
LICENSE Add module doc.go for pkg.go.dev and MIT license 2026-03-22 20:07:58 +08:00
Makefile Remove auto-update infrastructure in favor of MDM-managed deployments 2026-03-22 17:59:29 +08:00
managed-settings.json Add organization compliance scanner, managed config, hooks, and demo server 2026-03-21 19:30:56 +08:00
README.md Add module doc.go for pkg.go.dev and MIT license 2026-03-22 20:07:58 +08:00
renovate.json Add renovate.json 2026-03-21 19:28:26 +00:00

ai-agent

A Go daemon that watches Claude Code JSONL session files and ships raw records to a SIEM endpoint over HTTP. Designed for enterprise-wide deployment via MDM with at-least-once delivery and zero transformation of records.

Features

  • Session log collection — watches ~/.claude/projects/ for JSONL session files via fsnotify + polling backstop
  • Durable delivery — outbox pattern with bbolt ensures zero data loss on crash
  • Organization compliance — scans Claude Code and Claude Desktop configs, checks email domains and org IDs against server-managed policy, ships violations as SIEM events
  • Claude Code hooks — integrates with SessionStart and UserPromptSubmit hooks to display compliance banners and block/warn on policy violations
  • Cross-platform — single static binary for macOS (amd64/arm64), Linux (amd64), and Windows (amd64)
  • Unprivileged — runs without root/admin privileges

Quick Start

# Build all platform binaries
make build

# Set required environment variables
export CLAUDE_SIEM_ENDPOINT=http://your-siem-server:8080
export CLAUDE_SIEM_TOKEN=your-bearer-token
export CLAUDE_SIEM_HMAC_SECRET=your-hmac-secret

# Run in foreground
./dist/ai-agent-darwin-arm64 run

# Or install as a system service
./dist/ai-agent-darwin-arm64 install

CLI Commands

Command Description
run Run daemon in foreground (used by service managers)
run --test Dry-run: discover and display events that would be shipped
check Exit 0 if daemon is running, exit 1 if not
check --hook <event> Compliance check for Claude Code hooks (SessionStart or UserPromptSubmit)
install Copy binary to stable path and register as system service
uninstall Stop and remove service
start Start installed service
stop Stop installed service
status Print service status and PID

Use --debug on any command for debug-level logging.

Configuration

Environment Variables

Variable Required Default Description
CLAUDE_SIEM_ENDPOINT Yes SIEM base URL; agent derives /ingest, /config, and /update paths
CLAUDE_SIEM_TOKEN Yes Bearer token for SIEM authentication
CLAUDE_SIEM_HMAC_SECRET Yes HMAC-SHA256 shared secret for request signing
CLAUDE_SIEM_POLL_INTERVAL No 300s Polling backstop interval (minimum 60s)

Managed Config

The agent fetches server-managed configuration from GET {endpoint}/config on startup and at each poll interval. The config controls filtering, shipping, and compliance policy:

{
  "version": 1,
  "filters": {
    "ignore_types": ["file-history-snapshot", "progress"],
    "drop_sidechain": false,
    "drop_meta": false,
    "drop_tool_calls": false
  },
  "shipping": {
    "batch_size": 100,
    "flush_interval_seconds": 300
  },
  "compliance": {
    "permitted_email_domains": ["company.com"],
    "permitted_org_ids": ["org-uuid"],
    "banner": "This session is logged for compliance.",
    "action": "block",
    "violation_message": "Personal accounts are not permitted on company devices."
  }
}

Compliance Actions

  • block — violations prevent Claude Code sessions from starting and block every prompt (exit 2)
  • warn — violations are injected into Claude's prompt context as a reminder; usage is allowed but logged

Claude Code Hooks

Deploy via managed settings or user settings (~/.claude/settings.json):

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "startup|resume",
        "hooks": [
          { "type": "command", "command": "ai-agent check --hook SessionStart" }
        ]
      }
    ],
    "UserPromptSubmit": [
      {
        "hooks": [
          { "type": "command", "command": "ai-agent check --hook UserPromptSubmit" }
        ]
      }
    ]
  }
}

Architecture

~/.claude/projects/**/*.jsonl
         |
         v
   +-----------+    fsnotify / poll    +----------+
   |  Watcher  |---------------------->|  Reader  |
   +-----------+                       +----+-----+
                                            | atomic tx:
                                            | events + offset
                                            v
                                       +----------+
                                       |  Store   |  bbolt (siem.db)
                                       |  outbox  |  <- events waiting to ship
                                       |  state   |  <- file byte offsets
                                       |  deadltr |  <- failed batches
                                       +----+-----+
                                            |
                                            v
                                       +----------+     HTTP POST      +------+
                                       | Shipper  |------------------->| SIEM |
                                       |          |   Bearer + HMAC    |      |
                                       +----------+                    +------+

Package Map

cmd/collector/          Main binary — Cobra CLI (install/uninstall/start/stop/status/run/check)
cmd/server/             Demo SIEM receiver — file-based storage, serves config + updates
pkg/siemserver/         Importable server library — Huma handlers for ingest, config, stats
internal/compliance/    Org compliance scanner — reads Claude Code/Desktop configs, checks policy
internal/config/        Managed config fetch (with client identity), bbolt cache, hot-reload
internal/logging/       Custom slog.Handler + RotatingWriter (10MB, 3 files)
internal/reader/        JSONL reading, offset tracking, filtering rules
internal/shipper/       Batching, HTTP POST, HMAC signing, outbox drain
internal/store/         bbolt wrapper — state + outbox + deadletter + config buckets
internal/platform/      Machine ID, paths, PID file, OS service install

Filtering Rules

  1. Skip compact summaries — records with isCompactSummary: true (synthetic context, no audit value)
  2. Deduplicate by UUID — in-memory seen set per file, reset on restart
  3. Skip ignored types — server-managed filters.ignore_types list
  4. Drop sidechain — optionally skip agent/subagent conversations
  5. Drop meta — optionally skip system-injected meta messages
  6. Drop tool calls — optionally strip tool_use content blocks

Rules 1-2 are hardcoded. Rules 3-6 are server-managed. Everything else ships as-is.

Development

make build            # Cross-compile all 4 platform binaries to dist/
make darwin-arm64     # Build single target
make test             # go test -race -cover ./internal/... ./pkg/...
make clean            # rm -rf dist/
make snapshot         # GoReleaser snapshot build
make release          # GoReleaser release build

Demo Server

A standalone SIEM receiver for local testing:

make build
./dist/demo-server --token mytoken --hmac-secret mysecret

# In another terminal
export CLAUDE_SIEM_ENDPOINT=http://localhost:8080
export CLAUDE_SIEM_TOKEN=mytoken
export CLAUDE_SIEM_HMAC_SECRET=mysecret
./dist/ai-agent-darwin-arm64 run --debug

The demo server auto-detects dist/ for serving update artifacts and config.json for managed config.

Testing

go test ./...               # Run all tests
go test -race ./...         # With race detector
go test -cover ./internal/... ./pkg/...  # With coverage

All tests use t.TempDir() for I/O and httptest.Server for HTTP. Table-driven tests throughout.

Security

Mechanism Purpose
HMAC-SHA256 Sign batch payloads to SIEM (X-Siem-Signature header)
TLS Authenticate HTTPS servers (system trust store)
PID file locking Prevent concurrent daemon instances

Platform Notes

  • macOS: IOPlatformUUID for machine ID, ~/Library/Application Support/Claude/config.json for Desktop config
  • Linux: /etc/machine-id, requires kernel >= 5.10.94 (ext4 fast commit fix for bbolt)
  • Windows: Registry MachineGuid

License

MIT License. See LICENSE for details.