Documentation
¶
Overview ¶
Package hook brokers backend interactions through usher's web UI. Claude's stdio permission callback, Codex app-server approvals, and the command hook used for AskUserQuestion all submit here and wait for a UI response.
Index ¶
- type Event
- type Manager
- func (m *Manager) IsAutoApprove(sessionID string) bool
- func (m *Manager) List() []Pending
- func (m *Manager) QuickDecide(ev Event) (Response, bool)
- func (m *Manager) Respond(id string, r Response) error
- func (m *Manager) SetAutoApprove(sessionID string, enabled bool)
- func (m *Manager) Submit(ctx context.Context, ev Event) (Response, error)
- func (m *Manager) SubscribePending() (<-chan Pending, func())
- type Pending
- type Response
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Event ¶
type Event struct {
SessionID string
ToolUseID string
Event string
ToolName string
ToolInput json.RawMessage
Cwd string
AllowAlways bool
}
Event is the input usher receives from `usher hook` and forwards to Submit.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager owns pending interactions and the per-session blanket auto-approve flag. Auto-approve is persisted to disk so the trust boundary survives restarts.
func New ¶
New constructs a Manager. autoPath is the file backing the auto-approve flag map; pass "" to disable persistence (e.g. in tests). If the file exists at construction time, its state is loaded; subsequent calls to SetAutoApprove rewrite it atomically.
func (*Manager) IsAutoApprove ¶
IsAutoApprove reports whether sessionID is currently in blanket-allow mode.
func (*Manager) QuickDecide ¶
QuickDecide settles ev from blanket auto-approve without UI; returns (zero, false) when input is needed.
func (*Manager) Respond ¶
Respond delivers the user's decision to the matching pending interaction. Returns an error if the ID is unknown or the entry has already been resolved.
func (*Manager) SetAutoApprove ¶
SetAutoApprove flips the blanket "allow every tool call" flag for a session and persists the change to disk so it survives restarts.
func (*Manager) Submit ¶
Submit blocks until the user responds via Respond or ctx is cancelled. Short-circuits via QuickDecide first.
func (*Manager) SubscribePending ¶ added in v0.4.0
SubscribePending returns a buffered channel that receives each new pending interaction as it is submitted, plus a cancel function. The web UI polls List() instead; this push path lets the web-push dispatcher surface permission prompts as notifications without polling. Drop-on-full, so a slow consumer never blocks Submit.
type Pending ¶
type Pending struct {
ID string `json:"id"`
SessionID string `json:"session_id"`
Event string `json:"event"`
ToolName string `json:"tool_name,omitempty"`
ToolInput json.RawMessage `json:"tool_input,omitempty"`
Cwd string `json:"cwd,omitempty"`
// AllowAlways is true only when the originating backend advertised a
// native rule or repeated-approval decision for this request.
AllowAlways bool `json:"allow_always"`
CreatedAt time.Time `json:"created_at"`
}
Pending describes a permission request waiting for a user decision.
type Response ¶
type Response struct {
Behavior string `json:"behavior"` // allow | deny
Reason string `json:"reason,omitempty"`
// Scope is "once" (default) or "session". "session" is the historical API
// spelling for the UI's "always" choice; the backend owns its exact scope.
Scope string `json:"scope,omitempty"`
// Answers resolves an AskUserQuestion tool call: each entry maps a
// question (verbatim from the tool input) to the option label the user
// chose in the web UI. When set, the server merges it into the tool's
// updatedInput so claude proceeds with the answer instead of blocking on
// the pane TUI selector. Behavior is "allow" in this case.
Answers map[string]string `json:"answers,omitempty"`
}
Response is the user's decision on a pending interaction.