Documentation
¶
Index ¶
- Constants
- func CreateStderrLog() (string, error)
- func DefaultLauncher() terminal.Launcher
- func LaunchCommand(args []string, stderrLog string) string
- func MustJSON(v any) json.RawMessage
- func ShellQuote(s string) string
- func StripANSI(s string) string
- func TranscriptPath(home, dir, sessionID string) string
- func ValidTmuxKey(key string) bool
- func WaitForPaneReady(ctx context.Context, term terminal.Session) bool
- type AgentNotFound
- type PaneState
- type PermissionOption
- type Session
- func (s *Session) Emit(ev events.Event)
- func (s *Session) EmitTerminalGone(ctx context.Context)
- func (s *Session) MarkActive()
- func (s *Session) MarkFinished() bool
- func (s *Session) RemoveStderrLog()
- func (s *Session) ScanTerminalTick()
- func (s *Session) ScanTranscriptTick()
- func (s *Session) SendCancelKeys(ctx context.Context) error
- type SessionOptions
- type TerminalPermission
- type TranscriptReader
- type TranscriptRecord
Constants ¶
const ( PromptInjectCheckInterval = 500 * time.Millisecond PromptInjectTimeout = 30 * time.Second )
const ( // StopReasonAgentNotFound means Claude Code rejected the --agent name. StopReasonAgentNotFound = "agent_not_found" // StopReasonLaunchFailed means claude exited before avenor submitted a // prompt, for a reason avenor could not name. StopReasonLaunchFailed = "launch_failed" )
Stop reasons for a Claude process that exited without ever running a turn. Both report status=failed: the old behaviour reported status=done with an empty output, which is byte-for-byte what a real end_turn that said nothing looks like, so callers could not tell a typo from a completed run.
Variables ¶
This section is empty.
Functions ¶
func CreateStderrLog ¶ added in v0.26.0
CreateStderrLog creates the file LaunchCommand redirects claude's stderr into. The caller owns it and should remove it on teardown via Session.
func DefaultLauncher ¶
func LaunchCommand ¶ added in v0.26.0
LaunchCommand renders the shell command that starts claude inside a terminal.
`exec` replaces the shell with claude so that tmux's #{pane_pid} reports claude's own PID and the terminal exits when claude does.
stderr goes to stderrLog because a fatal launch banner is otherwise unreachable. Claude Code writes it to stderr and exits within ~300ms; tmux then destroys the session together with its pane, and `capture-pane` shows a blank grid for the whole life of that pane anyway (confirmed at 25ms sampling, and with remain-on-exit holding the dead pane open). A file survives both. The redirect costs nothing on a healthy run: Claude Code draws its TUI on stdout and leaves stderr empty.
func MustJSON ¶
func MustJSON(v any) json.RawMessage
func ShellQuote ¶
ShellQuote single-quotes a string for safe interpolation into a shell command.
func TranscriptPath ¶
func ValidTmuxKey ¶
ValidTmuxKey returns true if key is a safe single-character string for tmux send-keys.
func WaitForPaneReady ¶
WaitForPaneReady blocks until Claude's input box is taking input. It auto-dismisses the trust-safety dialog if present. Returns false on context cancel, capture error, send error, or the PromptInjectTimeout deadline — callers must treat any false return as "do not paste, the pane is not in a known-ready state".
Types ¶
type AgentNotFound ¶ added in v0.26.0
type AgentNotFound struct {
// Agent is the rejected --agent value. Empty when the banner did not parse.
Agent string
// Available is the roster Claude Code listed, whitespace-collapsed. Empty
// when the capture did not include it.
Available string
}
AgentNotFound is the diagnosis for a launch Claude Code refused because it did not recognise the requested agent.
func DetectAgentNotFound ¶ added in v0.26.0
func DetectAgentNotFound(text string) (AgentNotFound, bool)
DetectAgentNotFound reports whether text holds the unrecognised-agent banner, along with whatever diagnostics it could recover from it.
func (AgentNotFound) Message ¶ added in v0.26.0
func (a AgentNotFound) Message() string
Message renders the diagnosis for the event stream. The roster is the single most useful thing for whoever typo'd the agent name, so it goes in the message and not only in a structured field.
type PaneState ¶
type PaneState string
func ClassifyPane ¶
ClassifyPane returns the most-specific pane state. After a turn is submitted the pane shows both an echo line that starts with `❯` (the prior user prompt) AND a spinner line below it; the input box `❯` reappears at the bottom. An activity line therefore must beat any `❯` line, otherwise we'd report idle while a turn is still running.
type PermissionOption ¶
type Session ¶
type Session struct {
SessionID string
RunID string
Dir string
TmuxName string
Term terminal.Session
Transcript *TranscriptReader
// StderrLog is the file claude's stderr is redirected into by LaunchCommand.
// It outlives the terminal, which is the only way to read a fatal launch
// banner — see LaunchCommand for why the pane cannot be used.
StderrLog string
Events chan events.Event
Done chan struct{}
Ctx context.Context
CancelFn context.CancelFunc
StartedAt time.Time
Mu sync.Mutex
Prompted bool
Active bool
Finished bool
PendingTerminalPerm *TerminalPermission
}
func NewSession ¶
func NewSession(ctx context.Context, opts SessionOptions) *Session
func (*Session) EmitTerminalGone ¶ added in v0.26.0
EmitTerminalGone emits the terminal session.end for a Claude process that exited on its own. Both providers call it from their sessionGone branch, which cannot tell a finished turn from a refused launch by itself — the alive poll sees the same dead terminal either way — so classify the exit first.
MarkFinished is the existing guard against double-emitting: a run that already reported avenor_finish, a cancel, or a transcript end_turn keeps that verdict.
func (*Session) MarkActive ¶
func (s *Session) MarkActive()
func (*Session) MarkFinished ¶
func (*Session) RemoveStderrLog ¶ added in v0.26.0
func (s *Session) RemoveStderrLog()
RemoveStderrLog deletes the stderr log. Safe to call on a session that has none.
func (*Session) ScanTerminalTick ¶
func (s *Session) ScanTerminalTick()
func (*Session) ScanTranscriptTick ¶
func (s *Session) ScanTranscriptTick()
type SessionOptions ¶
type TerminalPermission ¶
type TerminalPermission struct {
RequestID string
Prompt string
Options []PermissionOption
CreatedAt time.Time
}
func ParseTerminalPermission ¶
func ParseTerminalPermission(text string) *TerminalPermission
ParseTerminalPermission extracts a TerminalPermission from pane text, or nil if the text doesn't represent a Claude permission dialog.
type TranscriptReader ¶
type TranscriptReader struct {
// contains filtered or unexported fields
}
TranscriptReader incrementally reads new records from a JSONL transcript. Successive Tick calls return only records appended since the last call.
func NewTranscriptReader ¶
func NewTranscriptReader(path string) *TranscriptReader
func (*TranscriptReader) Tick ¶
func (r *TranscriptReader) Tick() ([]TranscriptRecord, time.Time, error)
Tick reads records appended since the previous call. It returns the records, the file's mtime (zero if missing), and any read error. A missing file is not an error — callers tick early and often, and the transcript only appears once Claude writes its first record.
Offset only advances past newline-terminated lines so a half-written final record is left for the next tick to consume in full.
type TranscriptRecord ¶
type TranscriptRecord struct {
Type string `json:"type"`
AITitle string `json:"aiTitle,omitempty"`
Timestamp string `json:"timestamp,omitempty"`
StopReason string `json:"stop_reason,omitempty"`
Text string `json:"text,omitempty"`
ContentEvents []events.Event `json:"-"`
}
TranscriptRecord is the minimal subset of JSONL fields used for status and best-effort content extraction.