Documentation
¶
Overview ¶
Package hook installs and manages integration hooks for Envault: the Git pre-commit hook (git.go), the Claude Code PreToolUse hook (claude.go), and the PreToolUse request handler that blocks sensitive commands (preuse.go). Secret detection rules live in the sibling package internal/scan.
Index ¶
- Variables
- func InstallGitHook(repoRoot string) error
- func IsEnvaultDir(root string) bool
- func IsGitHookInstalled(repoRoot string) bool
- func IsSensitiveEnvaultCmd(cmd string) bool
- func IsSensitiveEnvaultWriteCmd(cmd string) bool
- func RunHookPostuse(r io.Reader, w io.Writer) error
- func RunHookPreuse(r io.Reader, w io.Writer) error
- func UninstallGitHook(repoRoot string) error
- type PostuseInput
- type PreuseInput
Constants ¶
This section is empty.
Variables ¶
var ErrBlockToolCall = fmt.Errorf("tool call blocked by envault hook")
ErrBlockToolCall is returned by RunHookPreuse when the tool call must be blocked. The caller must exit non-zero so Claude Code denies the tool call — any text already written to the output writer is shown to Claude as the reason.
Functions ¶
func InstallGitHook ¶
InstallGitHook installs the Envault pre-commit hook in the Git repo at repoRoot.
- If no pre-commit hook exists, a new one is created with a #!/bin/sh shebang.
- If one exists, the Envault block is appended after the existing content.
- If the Envault block is already present, the call is a no-op.
The resulting file is always made executable (0755).
func IsEnvaultDir ¶
IsEnvaultDir returns true when .envault/ exists under root.
func IsGitHookInstalled ¶
IsGitHookInstalled reports whether the Envault block is present in the pre-commit hook for the Git repo at repoRoot.
func IsSensitiveEnvaultCmd ¶
IsSensitiveEnvaultCmd reports whether cmd invokes `envault cat` or `envault export` as the primary command (not as an argument to another tool) without the --force override flag.
func IsSensitiveEnvaultWriteCmd ¶ added in v0.9.4
IsSensitiveEnvaultWriteCmd reports whether cmd invokes `envault add` or `envault set` as the primary command without the --force override flag. Unlike a plain read, sealing a value this way requires the plaintext to already be embedded in the command text (no interactive stdin over a tool call), so it is blocked the same way as a direct plaintext read.
func RunHookPostuse ¶
RunHookPostuse reads Claude Code's PostToolUse JSON from r.
If the current user's private key is available — via the key-unlock agent (internal/agent; no passphrase needed, see envault agent unlock) or, failing that, ENVAULT_PASSPHRASE — decrypts all KindEnv vault secrets and scans the tool response for their plaintext values (and base64-encoded variants), replacing each match with a structured placeholder `<ENVAULT:NAME>` (or `<ENVAULT:NAME|base64>`) before writing to w and exiting with code 2 so Claude Code uses the masked output instead of the original.
When neither key source is available, or the vault is absent, the function returns nil (pass-through), logging the skip to the audit log.
func RunHookPreuse ¶
RunHookPreuse reads Claude Code's PreToolUse JSON from r.
Blocking rules (in priority order):
- Read/Write/Edit/NotebookEdit tools whose file_path matches a protected pattern.
- Bash commands that reference a protected path (best-effort heuristic; full adversarial coverage is in v0.8.4).
- Bash commands that invoke `envault cat` or `envault export` without --force.
Each blocked call is appended to the audit log (.envault/ai-secure.log). Returns ErrBlockToolCall when a call is denied; nil otherwise.
func UninstallGitHook ¶
UninstallGitHook removes the Envault block from the pre-commit hook at repoRoot. If the file would be empty (or contain only a shebang) after removal, it is deleted to fully restore the prior state. Returns nil if the hook was not installed.
Types ¶
type PostuseInput ¶
type PostuseInput struct {
ToolName string `json:"tool_name"`
ToolInput json.RawMessage `json:"tool_input"`
ToolResponse json.RawMessage `json:"tool_response"`
}
PostuseInput is the Claude Code PostToolUse hook JSON.
type PreuseInput ¶
type PreuseInput struct {
ToolName string `json:"tool_name"`
ToolInput map[string]interface{} `json:"tool_input"`
}
PreuseInput is the subset of the Claude Code PreToolUse hook JSON we care about.