Documentation
¶
Overview ¶
ABOUTME: terminal-bell delivery on Unix-likes — write BEL to /dev/tty, with a ABOUTME: tmux pane-tty fallback for hook subprocesses that lack a controlling tty.
ABOUTME: Linux-specific notification handling with click-to-focus support. ABOUTME: Uses background daemon for persistent D-Bus connection when click-to-focus is enabled.
ABOUTME: Fills the zellij half of the focus hints the Linux daemon acts on. ABOUTME: Linux-only because FocusHints is the daemon's IPC payload, and the daemon is Linux-only.
Index ¶
- func EnsureClaudeNotificationsApp() error
- func FocusAppWindow(bundleID, cwd string) error
- func FocusAppWindowWithOptions(bundleID, cwd string, opts FocusWindowOptions) error
- func GetKittyWindowTarget() (windowID, listenOn string, err error)
- func GetTerminalBundleID(configOverride string) string
- func GetTerminalNotifierPath() (string, error)
- func GetTmuxPaneTarget() (string, error)
- func GetWezTermPaneTarget() (paneID, socketPath string, err error)
- func GetZellijTabTarget() (tabName, sessionName string, err error)
- func IsDaemonAvailable() bool
- func IsKitty() bool
- func IsTerminalFocused(sessionID, cwd string) bool
- func IsTerminalNotifierAvailable() bool
- func IsTmux() bool
- func IsTmuxControlMode() bool
- func IsWezTerm() bool
- func IsZellij() bool
- func MaybeCaptureGhosttyTerminalID(configOverride, sessionID, cwd string)
- func SendQuickNotification(title, message, executeCmd string) error
- func SetupPermission(ctx context.Context, root string, expected installruntime.InstalledSnapshot, ...) (string, error)
- func StartDaemon() bool
- func StopDaemon() error
- func ZellijSupportsPaneFocus() bool
- type BootClock
- type FocusWindowOptions
- type FreedesktopDelivery
- type ManagedInstallation
- type ManagedNativeProcess
- func (ManagedNativeProcess) Launch(ctx context.Context, bundle, request, receipt string) (bool, error)
- func (ManagedNativeProcess) Probe(ctx context.Context, executable string) ([]byte, error)
- func (ManagedNativeProcess) ProbePermission(ctx context.Context, executable, correlation, nonce string) ([]byte, error)
- func (ManagedNativeProcess) ProbeSetup(ctx context.Context, executable string) ([]byte, error)
- func (ManagedNativeProcess) RequestPermission(ctx context.Context, executable, correlation, nonce string) ([]byte, error)
- type NativeAttempt
- type NativeInstallation
- type NativeLease
- type NativeProcess
- type NativeSpool
- type NotificationPermissionDeniedError
- type Notifier
- type PermissionProcess
- type PrivateNativeSpool
- func (s *PrivateNativeSpool) Cleanup(ctx context.Context) error
- func (s *PrivateNativeSpool) Expire(a NativeAttempt) error
- func (s *PrivateNativeSpool) Prepare(ctx context.Context, r notification.Request, ...) (NativeAttempt, error)
- func (s *PrivateNativeSpool) Receipt(a NativeAttempt) ([]byte, error)
- type StructuredDelivery
- type SystemBootClock
- type WindowsToastDelivery
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EnsureClaudeNotificationsApp ¶
func EnsureClaudeNotificationsApp() error
EnsureClaudeNotificationsApp is a no-op on Linux.
func FocusAppWindow ¶
FocusAppWindow is not supported on non-darwin platforms.
func FocusAppWindowWithOptions ¶
func FocusAppWindowWithOptions(bundleID, cwd string, opts FocusWindowOptions) error
FocusAppWindowWithOptions is not supported on non-darwin platforms.
func GetKittyWindowTarget ¶
GetKittyWindowTarget returns the window ID and listen socket path from environment variables.
func GetTerminalBundleID ¶
GetTerminalBundleID returns empty string on Linux as terminal bundle IDs are a macOS-specific concept.
func GetTerminalNotifierPath ¶
GetTerminalNotifierPath returns an error on Linux as terminal-notifier is macOS-only.
func GetTmuxPaneTarget ¶
GetTmuxPaneTarget returns the tmux pane ID (e.g. "%42") of the pane where Claude Code is running, for use with tmux select-pane / select-window commands.
Prefers $TMUX_PANE (set by tmux per-pane at creation, always points to the process's own pane) over "tmux display-message" (which returns the currently active pane and may be wrong if the user switched tabs).
func GetWezTermPaneTarget ¶
GetWezTermPaneTarget returns the pane ID and unix socket path from environment variables. No external commands needed — the pane ID is already available in $WEZTERM_PANE.
func GetZellijTabTarget ¶
GetZellijTabTarget returns the active tab name and session name for the current zellij session.
dump-layout is answered by the running zellij server, so it can hang in a way that argument parsing cannot. It runs in the hook process, ahead of the notification the user is waiting for, so it is bounded: a session that stops answering costs the deadline and then reports a failed target, which every caller already treats as "no zellij focus" rather than "no notification".
func IsDaemonAvailable ¶
func IsDaemonAvailable() bool
IsDaemonAvailable checks if the notification daemon is available and running. Exported for testing and status checks.
func IsKitty ¶
func IsKitty() bool
IsKitty returns true if the current process is running inside Kitty with remote control enabled. Checks both $KITTY_WINDOW_ID (always set in Kitty) and $KITTY_LISTEN_ON (only set when remote control is configured).
func IsTerminalFocused ¶
IsTerminalFocused reports whether the terminal window running Claude Code currently has operating-system focus.
It is deliberately conservative: it returns true ONLY when it can positively confirm that the focused terminal belongs to this session. sessionID and cwd let platform implementations match exact tabs/windows when available. On any uncertainty - an OS API error, an unsupported platform or session (e.g. a Wayland compositor with no generic active-window query), or a terminal it cannot identify - it returns false so the caller still delivers the notification.
This bias matters: a wrong "focused" result silently swallows a notification the user is waiting for, whereas a wrong "unfocused" result merely shows one extra banner. The failure mode is therefore always an extra notification, never a missing one.
func IsTerminalNotifierAvailable ¶
func IsTerminalNotifierAvailable() bool
IsTerminalNotifierAvailable returns false on Linux.
func IsTmux ¶
func IsTmux() bool
IsTmux returns true if the current process is running inside a tmux session.
func IsTmuxControlMode ¶
func IsTmuxControlMode() bool
IsTmuxControlMode returns true if any tmux client attached to the current server is running in control mode (-CC), typically used by iTerm2. In control mode, standard tmux select-window doesn't cause iTerm2 to switch tabs; the iTerm2 Python API must be used instead.
Uses list-clients (not display-message) because display-message evaluates #{client_control_mode} for the temporary command-line client we spawn, which is never in control mode. list-clients enumerates all persistent (attached) clients, so we can check if ANY is in control mode.
func IsWezTerm ¶
func IsWezTerm() bool
IsWezTerm returns true if the current process is running inside WezTerm.
func IsZellij ¶
func IsZellij() bool
IsZellij returns true if the current process is running inside a zellij session.
func MaybeCaptureGhosttyTerminalID ¶
func MaybeCaptureGhosttyTerminalID(configOverride, sessionID, cwd string)
func SendQuickNotification ¶
SendQuickNotification sends a one-off notification without requiring a Notifier instance. executeCmd is the shell command run when the user clicks the notification (may be empty).
func SetupPermission ¶ added in v1.44.0
func SetupPermission(ctx context.Context, root string, expected installruntime.InstalledSnapshot, request bool) (string, error)
SetupPermission is an explicit installer action. It never changes enablement, sends a notification, repairs an installation, or retries authorization.
func StartDaemon ¶
func StartDaemon() bool
StartDaemon starts the notification daemon on-demand. Returns true if daemon started successfully or was already running.
func ZellijSupportsPaneFocus ¶ added in v1.43.1
func ZellijSupportsPaneFocus() bool
ZellijSupportsPaneFocus reports whether the installed zellij accepts focus-pane-id, which arrived in 0.44.1.
It asks zellij rather than comparing version numbers: `action <name> --help` exits zero for a subcommand that exists and non-zero for one that does not, needs no running session, and leaves the running one alone. Any non-zero status counts as unsupported, which is what carries this across zellij's clap upgrade — the exit code for an unknown subcommand changed from 1 to 2 — and what makes an absent zellij degrade to the target that has always existed rather than to no focus at all.
The probe is bounded: it runs in the hook process, ahead of the notification the user is waiting for, so a zellij that never answers must not hold that up. A timeout reads as unsupported, which lands on the tab path.
Types ¶
type BootClock ¶ added in v1.44.0
BootClock uses the same boot epoch and continuous seconds as native. Callers use Now at transport admission; Deliver never starts a new request budget.
type FocusWindowOptions ¶
type FocusWindowOptions struct {
GhosttyTerminalID string
}
type FreedesktopDelivery ¶ added in v1.44.0
type FreedesktopDelivery struct {
Clock BootClock
Open func(context.Context) (sessionNotifications, error)
}
FreedesktopDelivery is the Linux explicit-notify adapter. It makes one session-bus Notify call and never falls back after a possible D-Bus effect.
func NewFreedesktopDelivery ¶ added in v1.44.0
func NewFreedesktopDelivery(clock BootClock) *FreedesktopDelivery
func (*FreedesktopDelivery) CheckReadiness ¶ added in v1.44.0
func (d *FreedesktopDelivery) CheckReadiness(ctx context.Context, r notification.Request) notification.Readiness
func (*FreedesktopDelivery) Deliver ¶ added in v1.44.0
func (d *FreedesktopDelivery) Deliver(ctx context.Context, r notification.Request) notification.Receipt
type ManagedInstallation ¶ added in v1.44.0
type ManagedInstallation struct {
ControlRoot string
Expected installruntime.InstalledSnapshot
}
ManagedInstallation belongs to one request. Expected is the unchanged, immutable Installation from that request's ReadPolicySnapshot. Use the same adapter for readiness and delivery, never a startup-global snapshot. Acquire must run without a journal lock and never refreshes a stale snapshot. The kernel owns root, permanent lock, generation, owner and artifact checks.
func (ManagedInstallation) Acquire ¶ added in v1.44.0
func (m ManagedInstallation) Acquire(ctx context.Context) (NativeLease, error)
type ManagedNativeProcess ¶ added in v1.44.0
type ManagedNativeProcess struct{}
ManagedNativeProcess executes only the paths returned by a verified lease. It never uses PATH lookup, bundle-ID lookup, or the legacy notifier finder.
func (ManagedNativeProcess) ProbePermission ¶ added in v1.44.0
func (ManagedNativeProcess) ProbeSetup ¶ added in v1.44.0
ProbeSetup is used only after the installer has verified the managed artifact and its base capabilities. It never requests OS authorization.
func (ManagedNativeProcess) RequestPermission ¶ added in v1.44.0
func (ManagedNativeProcess) RequestPermission(ctx context.Context, executable, correlation, nonce string) ([]byte, error)
RequestPermission is an explicit installer action, never a notify fallback. The caller must hold a setup lease and first validate setup capabilities. A timeout cannot retract an OS prompt already dispatched; never auto-retry.
type NativeAttempt ¶ added in v1.44.0
type NativeAttempt struct{ Directory, RequestPath, ReceiptPath, Nonce string }
type NativeInstallation ¶ added in v1.44.0
type NativeInstallation interface {
Acquire(context.Context) (NativeLease, error)
}
NativeInstallation is a lease from the managed component owner. Verify must check its trusted offline manifest/fingerprint before returning a path; unknown helpers must never be executed to discover support. The lease pins the stable bundle against update through handoff. PR2 composition owns that lock/ledger.
type NativeLease ¶ added in v1.44.0
type NativeProcess ¶ added in v1.44.0
type NativeProcess interface {
Probe(context.Context, string) ([]byte, error)
// Launch returns whether a process might have handed work to LaunchServices.
// A started launcher is an unknown outcome until a correlated native receipt.
Launch(context.Context, string, string, string) (mayHaveHandedOff bool, err error)
}
type NativeSpool ¶ added in v1.44.0
type NativeSpool interface {
Prepare(context.Context, notification.Request, func(string) ([]byte, error)) (NativeAttempt, error)
Receipt(NativeAttempt) ([]byte, error)
// Expire removes only this owned attempt after the original boot deadline.
// It must not be called merely because the open launcher exited.
Expire(NativeAttempt) error
}
type NotificationPermissionDeniedError ¶
type NotificationPermissionDeniedError struct {
Details string
}
NotificationPermissionDeniedError indicates macOS rejected the native ClaudeNotifier path because notification permission is denied for the app.
func (*NotificationPermissionDeniedError) Error ¶
func (e *NotificationPermissionDeniedError) Error() string
type Notifier ¶
type Notifier struct {
// contains filtered or unexported fields
}
Notifier sends desktop notifications
func (*Notifier) SendDesktop ¶
SendDesktop sends a desktop notification. On macOS, it always prefers ClaudeNotifier/terminal-notifier to avoid Script Editor attribution and optionally enables click-to-focus. On Linux with clickToFocus enabled, it uses the background daemon. cwd is the working directory of the project; used for window-specific focus. May be empty.
type PermissionProcess ¶ added in v1.44.0
type PermissionProcess interface {
ProbePermission(context.Context, string, string, string) ([]byte, error)
}
PermissionProcess extends only the known capability mode; unsupported implementations fail closed. Acquire must verify offline before any execution.
type PrivateNativeSpool ¶ added in v1.44.0
PrivateNativeSpool is used only by notify/setup, never read-only status. Root must already be a setup-owned private directory on a local filesystem. All physical paths are derived from EvalSymlinks before creating files.
func (*PrivateNativeSpool) Cleanup ¶ added in v1.44.0
func (s *PrivateNativeSpool) Cleanup(ctx context.Context) error
Cleanup is an explicit bounded notify/setup operation. It is not a status API.
func (*PrivateNativeSpool) Expire ¶ added in v1.44.0
func (s *PrivateNativeSpool) Expire(a NativeAttempt) error
func (*PrivateNativeSpool) Prepare ¶ added in v1.44.0
func (s *PrivateNativeSpool) Prepare(ctx context.Context, r notification.Request, encode func(string) ([]byte, error)) (NativeAttempt, error)
func (*PrivateNativeSpool) Receipt ¶ added in v1.44.0
func (s *PrivateNativeSpool) Receipt(a NativeAttempt) ([]byte, error)
type StructuredDelivery ¶ added in v1.44.0
type StructuredDelivery struct {
Installation NativeInstallation
Clock BootClock
Process NativeProcess
Spool NativeSpool
}
StructuredDelivery is independent of Notifier's legacy best-effort policy. Dependencies are immutable and safe for concurrent requests. No globals, hook state, analyzer, bell, webhook or fallback are consulted by Deliver.
func NewStructuredDelivery ¶ added in v1.44.0
func NewStructuredDelivery(installation NativeInstallation, spoolRoot string) *StructuredDelivery
NewStructuredDelivery wires the real managed launcher, private spool and boot-continuous clock. Construction is read-only: setup must already have prepared spoolRoot and the trusted installation. PR4 owns policy/origin and durable admission before calling this port.
func (*StructuredDelivery) CheckReadiness ¶ added in v1.44.0
func (d *StructuredDelivery) CheckReadiness(ctx context.Context, r notification.Request) notification.Readiness
CheckReadiness releases its lease before returning; callers may then enter their journal transaction. Ready is a snapshot, never a delivery guarantee.
func (*StructuredDelivery) Deliver ¶ added in v1.44.0
func (d *StructuredDelivery) Deliver(ctx context.Context, r notification.Request) notification.Receipt
type SystemBootClock ¶ added in v1.44.0
type SystemBootClock struct{}
SystemBootClock uses the same trusted procfs boot identity and CLOCK_BOOTTIME epoch as the production journal clock, with nanosecond precision for deadlines.
type WindowsToastDelivery ¶ added in v1.44.0
type WindowsToastDelivery struct {
Clock BootClock
Open func(context.Context) (windowsToastSession, error)
}
WindowsToastDelivery is the Windows explicit-notify adapter. It shows one informational toast and never starts the click-to-focus handler or falls back to beeep after a possible toast effect.
func NewWindowsToastDelivery ¶ added in v1.44.0
func NewWindowsToastDelivery(clock BootClock) *WindowsToastDelivery
func (*WindowsToastDelivery) CheckReadiness ¶ added in v1.44.0
func (d *WindowsToastDelivery) CheckReadiness(ctx context.Context, r notification.Request) notification.Readiness
func (*WindowsToastDelivery) Deliver ¶ added in v1.44.0
func (d *WindowsToastDelivery) Deliver(ctx context.Context, r notification.Request) notification.Receipt
Source Files
¶
- ax_focus_stub.go
- bell_other.go
- delivery.go
- delivery_clock_linux.go
- delivery_files_unix.go
- delivery_installation.go
- delivery_linux.go
- delivery_process.go
- delivery_spool.go
- delivery_toast.go
- delivery_toast_other.go
- focus.go
- focus_linux.go
- ghostty_session_stub.go
- iterm2_focus.go
- kitty.go
- multiplexer.go
- notifier.go
- presentation.go
- readiness.go
- setup_permission.go
- setup_process.go
- terminal_linux.go
- tmux.go
- tmux_iterm2.go
- warp_focus.go
- wezterm.go
- windows_toast_xml.go
- zellij.go
- zellij_linux.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package nativeprotocol validates the versioned native helper replies.
|
Package nativeprotocol validates the versioned native helper replies. |