Documentation
¶
Overview ¶
Package hooks serves the Claude Code SessionStart and UserPromptSubmit hook endpoints and installs/removes their entries in a settings.json. Both handlers authenticate the same static bearer key as MCP, and both fail open: any internal error yields a 200 with empty additionalContext so a broken briefing can never block an agent. Only a bad key (401) or an unknown ?client= discriminator (400, an install bug rather than a runtime condition) returns non-2xx.
Index ¶
- Variables
- func CommandHookEndpoints() map[string]string
- func InstalledEvents(client Client) ([]string, error)
- func RecordedCommandPaths(clientName Client, settingsPath string) (seamBin, configPath string, ok bool)
- type Client
- type Config
- type Handler
- type InstallOptions
- type InstallResult
- type InstallStatus
- type UninstallOptions
- type UninstallResult
Constants ¶
This section is empty.
Variables ¶
var HookClients = []Client{ClientClaudeCode, ClientCodex}
HookClients lists every accepted hook client discriminator. It is the canonical set behind request parsing, programmatic profile selection, error text, and the seam CLI's test-pinned copy.
Functions ¶
func CommandHookEndpoints ¶
CommandHookEndpoints returns the `seam hook <arg>` events the installer wires as command hooks across every client profile, each mapped to the endpoint that hook must forward to. It is a union: the Codex profile adds user-prompt-submit (a command hook there, http for CC) and stop, so the CLI pin covers both clients. An event that both profiles wire as a command hook shares one endpoint.
It exists for the seam CLI's test. The CLI keeps its own copy of this mapping -- it cannot import this package without dragging the store, the retriever, and SQLite into a binary whose job is one HTTP POST -- and a hook fails open by contract, so drift between the two copies is a silent no-op rather than an error: install-hooks would write a command line the CLI rejects, or forward to a route that is not there, and the only symptom would be a briefing that stopped arriving.
func InstalledEvents ¶
InstalledEvents is the set of hook events Seamless installs for a client, in install order. A caller (doctor) compares InstalledStatus against len(InstalledEvents) for the same client.
func RecordedCommandPaths ¶ added in v0.3.7
func RecordedCommandPaths(clientName Client, settingsPath string) (seamBin, configPath string, ok bool)
RecordedCommandPaths returns the seam binary and config path recorded in the first seam-shaped command hook of the client's profile in settingsPath. Doctor uses it to judge an install against the paths it was installed with rather than against the running binary's siblings: `make doctor` from a repo checkout must not report a ~/.local/bin install stale. ok is false when the file cannot be read or no command hook runs a seam executable.
Types ¶
type Client ¶ added in v0.3.3
type Client string
Client identifies the agent host a hook request came from. It selects the ambient session-name prefix (cc/ vs cx/) so a Claude Code agent and a Codex agent working the same machine get distinct, self-describing session names.
const ( // ClientClaudeCode is the default: Claude Code sends no discriminator, so an // empty client resolves here and existing cc/ behavior is unchanged. ClientClaudeCode Client = "claude-code" // ClientCodex is the shared local Codex app/CLI/IDE host, whose ambient // sessions are named cx/. ClientCodex Client = "codex" )
type Config ¶
type Config struct {
DB *sql.DB
Retrieve *retrieve.Service
Events *events.Recorder
Files *files.Manager
APIKey string
MaxEventChars int
PlanCapture config.PlanCapture
PlansDir string
Logger *slog.Logger
}
Config carries the Handler's dependencies. DB backs ambient sessions and the session-end harvest; Events may be nil (injection telemetry is then skipped); Files may be nil (plan/subagent capture is then skipped). MaxEventChars caps captured prompt/findings text (0 = unlimited); injected content is always stored in full (it is bounded by the client-aware context policy upstream). PlansDir is where Claude Code writes plan-mode files; empty defaults to ~/.claude/plans (tests override it).
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler serves the hook endpoints.
type InstallOptions ¶
type InstallOptions struct {
Client Client // agent client profile; "" (zero value) => Claude Code
SettingsPath string // target file: CC settings.json or Codex hooks.json (created if absent)
BaseURL string // e.g. http://127.0.0.1:8081
APIKey string // static bearer key (written into the CC http hook header; Codex command hooks carry none)
SeamBin string // path to the seam CLI for command hooks; "" => "seam" (PATH)
ConfigPath string // abs seamless.yaml passed to command hooks as `--config` so they resolve config from any cwd; "" omits it
}
InstallOptions configures an install.
type InstallResult ¶
type InstallResult struct {
Changed bool
BackupPath string // "" when no backup was written
Actions []string // per-hook: "SessionStart: added|updated|unchanged"
}
InstallResult reports what an install did.
func Install ¶
func Install(opts InstallOptions) (InstallResult, error)
Install merges the client's Seamless hook entries into the settings/hooks file at opts.SettingsPath, preserving unknown keys, replacing any existing Seamless-managed entries in place, and backing the file up once before the first change. It is idempotent: an already-current file is left untouched.
type InstallStatus ¶ added in v0.3.7
InstallStatus separates exact current definitions from stale definitions that Seamless owns or can confidently adopt. Owned is their union in profile order and is the set uninstall may remove; foreign definitions are omitted.
func InstalledStatus ¶
func InstalledStatus(opts InstallOptions) (InstallStatus, error)
InstalledStatus classifies every event in a client's profile against the exact desired definition described by opts. An event is Current only when it has exactly one current definition and no stale owned duplicate. A missing or empty file yields an empty status and no error.
type UninstallOptions ¶ added in v0.3.5
type UninstallOptions struct {
Client Client // agent client profile; "" (zero value) => Claude Code
SettingsPath string // target file: CC settings.json or Codex hooks.json
BaseURL string // e.g. http://127.0.0.1:8081 -- the http-url ownership arm needs it
}
UninstallOptions configures an uninstall.
type UninstallResult ¶ added in v0.3.5
type UninstallResult struct {
Changed bool
BackupPath string // "" when no backup was written
Actions []string // per-hook: "SessionStart: removed|absent"
}
UninstallResult reports what an uninstall did.
func Uninstall ¶ added in v0.3.5
func Uninstall(opts UninstallOptions) (UninstallResult, error)
Uninstall removes the client's Seamless hook entries from the settings/hooks file at opts.SettingsPath, the exact inverse of Install. It uses the shared definition classifier and removes current, marked-stale, or confidently legacy Seamless entries. It preserves every unknown key and every foreign entry -- including a v1 "seam_managed" hook at a different URL. An event array that empties is dropped, and the top-level "hooks" key is dropped if it empties (the file itself is never deleted, even if it becomes "{}"). It backs the file up once before the first change (reusing backupOnce, which is once-ever, so it never clobbers Install's original backup). It is idempotent: a file with nothing of ours -- or a missing file -- is left untouched with no error.