Files
zzet--gortex/cmd/gortex/hook.go
T
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

68 lines
2.9 KiB
Go

package main
import (
"github.com/spf13/cobra"
"github.com/zzet/gortex/internal/hooks"
)
var (
hookPort int
hookMode string
hookAgent string
)
var hookCmd = &cobra.Command{
Use: "hook",
Short: "Agent hook handler (Claude Code by default; --agent for Gemini / Antigravity / Hermes / Kimi)",
Hidden: true, // Not for direct user invocation.
Run: func(_ *cobra.Command, _ []string) {
// --agent selects the hook wire protocol. Empty (the default) is the
// Claude Code format; protocol-specific agents branch below, and the
// remaining external agents share the hookSpecificOutput.additionalContext
// wire shape.
switch hookAgent {
case "hermes":
// Hermes (NousResearch hermes-agent) sends
// snake_case events and expects an action/message decision shape, so
// it gets its own dispatcher.
hooks.RunHermes(hookPort, hooks.ParseMode(hookMode))
return
case "pi":
// Pi (earendil-works/pi) has no MCP; its Gortex extension
// shells `gortex hook --agent=pi`, sending a normalized event
// envelope on stdin and applying the PiDecision read back.
hooks.RunPi(hookPort, hooks.ParseMode(hookMode))
return
case "codex":
// Codex support is intentionally soft-only: the adapter installs
// Bash PreToolUse/PostToolUse plus a UserPromptSubmit hook that emit
// additionalContext without ever denying the tool call.
hooks.RunCodex(hookPort)
return
case "kimi":
// Kimi Code CLI: UserPromptSubmit / PreToolUse / Stop /
// SubagentStart. Soft guidance rides Kimi's plain-stdout context
// channel; an indexed whole-file read is blocked via the documented
// hookSpecificOutput.permissionDecision shape.
hooks.RunKimi(hookPort, hooks.ParseMode(hookMode))
return
case "", "claude":
// Claude Code — handled below.
default:
hooks.RunExternalAgent()
return
}
hooks.Run(hookPort, hooks.ParseMode(hookMode))
},
}
func init() {
hookCmd.Flags().IntVar(&hookPort, "port", 8765, "Gortex web server port")
hookCmd.Flags().StringVar(&hookMode, "mode", "deny",
"hook posture: 'deny' (redirect Grep/Glob/Read of indexed source), 'enrich' (never deny; PostToolUse appends graph context), 'consult-unlock' (deny fallback reads until the graph is queried once this session), or 'nudge' (soft-deny once per burst of non-symbolic calls)")
hookCmd.Flags().StringVar(&hookAgent, "agent", "",
"hook wire protocol: empty/'claude' (Claude Code PreToolUse/UserPromptSubmit), 'codex' (Codex Bash PreToolUse/PostToolUse + UserPromptSubmit soft context), 'kimi' (Kimi Code CLI UserPromptSubmit/PreToolUse/Stop/SubagentStart; plain-stdout context, permissionDecision deny for indexed reads), 'hermes' (NousResearch hermes-agent pre_tool_call/pre_llm_call), 'pi' (earendil-works/pi extension bridge — normalized PiEvent envelope in, PiDecision out), or 'gemini'/'antigravity' (emits hookSpecificOutput.additionalContext). Default (empty) is the Claude Code format.")
rootCmd.AddCommand(hookCmd)
}