Documentation
¶
Index ¶
- func BuildHandshake(paths config.Paths, cols, rows uint16, cwd string) protocol.HandshakeMsg
- func EnsureDaemon(sockPath, configFile string) (net.Conn, error)
- func FetchConversation(cfg *config.Config, paths config.Paths, configFile string, sessionID string) ([]protocol.ConversationMessage, error)
- func FetchScreenSnapshot(cfg *config.Config, paths config.Paths, configFile string, sessionID string) *protocol.ScreenSnapshotResponseMsg
- func FetchScrollbackPreview(cfg *config.Config, paths config.Paths, configFile string, sessionID string) string
- func RemoteHostsPath(dataDir string) string
- func RunCreateInput(defaultRepo string, repos []RepoSuggestion, agents []string, ...) (string, string, string)
- func RunMessageOverlay(sessionID string, fetch func() ([]protocol.ConversationMessage, bool), ...)
- func RunNameInput(title string) string
- func RunShellInWorktree(worktreePath string) error
- func ShortDuration(d time.Duration) string
- func SortSessions(sessions []protocol.SessionInfo)
- func WriteScreenRestore(snap *protocol.ScreenSnapshotResponseMsg)
- type ApprovalResult
- type Client
- func Connect(cfg *config.Config, paths config.Paths, configFile string) (*Client, error)
- func ConnectFast(paths config.Paths) (*Client, error)
- func ConnectForApproval(paths config.Paths, approvalTimeout time.Duration) (*Client, error)
- func ConnectPassive(cfg *config.Config, paths config.Paths, configFile string) (*Client, error)
- func ConnectRemote(paths config.Paths, rh *RemoteHost, signer ed25519.PrivateKey, ...) (*Client, error)
- func New(cfg *config.Config, paths config.Paths, configFile string) (*Client, error)
- func (c *Client) Close()
- func (c *Client) Handshake() error
- func (c *Client) ReadControlResponse() (protocol.Envelope, error)
- func (c *Client) ReadFrame() (protocol.Frame, error)
- func (c *Client) RunPassthrough(ctx context.Context, opts PassthroughOpts) PassthroughResult
- func (c *Client) SendControl(msgType string, payload any) error
- func (c *Client) SendData(data []byte) error
- func (c *Client) SendFrame(channel byte, data []byte) error
- type DashboardModel
- type DashboardResult
- type OverlayResult
- type PassthroughKeys
- type PassthroughOpts
- type PassthroughResult
- type RemoteHost
- type RemoteHostStore
- func (s *RemoteHostStore) EnsureDeviceKey() (ed25519.PrivateKey, string, error)
- func (s *RemoteHostStore) Get(host string) (*RemoteHost, bool)
- func (s *RemoteHostStore) Names() []string
- func (s *RemoteHostStore) Put(h *RemoteHost)
- func (s *RemoteHostStore) Resolve(host string) (*RemoteHost, []string)
- func (s *RemoteHostStore) Save() error
- type RepoSuggestion
- type StatusBarCfg
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BuildHandshake ¶ added in v0.18.0
BuildHandshake constructs a HandshakeMsg with the given paths and terminal dimensions. All code that needs to send a handshake should use this so the Profile field is always populated.
func EnsureDaemon ¶
EnsureDaemon returns a connection to a live graith daemon, starting one if necessary.
A successful Unix socket dial proves *something* is listening, but not that it's a live graith daemon: the socket may be stale (left behind by a stuck or crashed process) or owned by an unrelated server. Rather than trust the dial and then block forever on a handshake that never comes, EnsureDaemon probes the socket with a handshake under a deadline. If the probe fails, a fresh daemon is started — its startup removes any stale/foreign socket before binding (daemon.Listen), while its PID-file guard (daemon.AcquirePIDFile) refuses to start if a live graith daemon already owns the path. EnsureDaemon deliberately does not unlink the socket itself: doing so could orphan a live-but-slow daemon that merely lost the probe race — its socket would be gone but the PID guard would then block the replacement from rebinding.
func FetchConversation ¶ added in v0.59.0
func FetchConversation(cfg *config.Config, paths config.Paths, configFile string, sessionID string) ([]protocol.ConversationMessage, error)
FetchConversation retrieves the full direct-message conversation (both directions) for sessionID via a one-shot passive connection. It is safe for the human CLI: msg_conversation authorises with the self-or-descendant rule, which permits unauthenticated callers.
func FetchScreenSnapshot ¶ added in v0.2.0
func FetchScrollbackPreview ¶
func RemoteHostsPath ¶ added in v0.66.3
RemoteHostsPath returns the store path within a data dir.
func RunCreateInput ¶ added in v0.52.0
func RunCreateInput(defaultRepo string, repos []RepoSuggestion, agents []string, defaultAgent string) (string, string, string)
RunCreateInput launches a bubbletea prompt for creating a session. Returns (name, repoPath, agent) or ("", "", "") on cancel.
func RunMessageOverlay ¶ added in v0.59.0
func RunMessageOverlay(sessionID string, fetch func() ([]protocol.ConversationMessage, bool), names map[string]string)
RunMessageOverlay displays the chatroom-style message viewer for sessionID, showing direct messages to and from that session grouped by peer. It is read-only in v1 and refreshes every 2 seconds. fetch returns the conversation and ok=false on a transient error (so the last good snapshot is kept). Returns when the user closes the overlay; the caller then reattaches.
func RunNameInput ¶ added in v0.9.0
RunNameInput launches a bubbletea prompt asking for a session name. Returns the entered name, or "" if the user cancelled.
func RunShellInWorktree ¶
RunShellInWorktree spawns an interactive shell with its working directory set to the given worktree path, and GRAITH_WORKTREE exported in the env. A non-zero exit status from the shell is not treated as an error since interactive shells commonly inherit the status of their last command.
func ShortDuration ¶ added in v0.3.0
func SortSessions ¶ added in v0.5.1
func SortSessions(sessions []protocol.SessionInfo)
func WriteScreenRestore ¶ added in v0.2.0
func WriteScreenRestore(snap *protocol.ScreenSnapshotResponseMsg)
Types ¶
type ApprovalResult ¶ added in v0.13.0
func RunApprovalOverlay ¶ added in v0.13.0
func RunApprovalOverlay(approvals []protocol.ApprovalInfo) []ApprovalResult
RunApprovalOverlay launches the bubbletea approval overlay listing pending approvals. Returns the list of decisions made by the user. After each approve/deny the overlay stays open; it auto-closes when empty.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
func Connect ¶
Connect creates a new client, performs the handshake, and reads the handshake response. If the daemon is running a different version, it automatically triggers a restart and reconnects. On failure the connection is closed automatically.
func ConnectFast ¶ added in v0.11.0
ConnectFast is a fast-path connect for hooks. It dials the daemon socket directly with a short timeout and does NOT auto-start the daemon.
func ConnectForApproval ¶ added in v0.13.0
ConnectForApproval is like ConnectFast but with a long deadline suitable for blocking on approval responses. The socket deadline is set to approvalTimeout plus a one-minute grace period (minimum one minute total) so the connection outlives the daemon's approval timer.
func ConnectPassive ¶ added in v0.40.0
ConnectPassive creates a new client and performs the handshake, but never triggers daemon auto-upgrade on version mismatch. Use this for long-lived helper processes (e.g. MCP proxies) that may outlive a binary upgrade and should not race with the user's explicit daemon restart.
func ConnectRemote ¶ added in v0.66.3
func ConnectRemote(paths config.Paths, rh *RemoteHost, signer ed25519.PrivateKey, cols, rows uint16) (*Client, error)
ConnectRemote dials a paired remote daemon over TLS (SPKI-pinned), performs the handshake, completes proof-of-possession (signing the daemon's challenge with the device key), and returns a ready Client authenticated as this device. Unlike New/Connect it never touches the local daemon (no EnsureDaemon, no auto-upgrade).
func (*Client) ReadControlResponse ¶
func (*Client) RunPassthrough ¶
func (c *Client) RunPassthrough(ctx context.Context, opts PassthroughOpts) PassthroughResult
type DashboardModel ¶ added in v0.3.0
type DashboardModel struct {
// contains filtered or unexported fields
}
func NewDashboardModel ¶ added in v0.3.0
func NewDashboardModel(sessions []protocol.SessionInfo, refresh func() []protocol.SessionInfo) DashboardModel
func (DashboardModel) Init ¶ added in v0.3.0
func (m DashboardModel) Init() tea.Cmd
func (DashboardModel) View ¶ added in v0.3.0
func (m DashboardModel) View() tea.View
type DashboardResult ¶ added in v0.3.0
func RunDashboard ¶ added in v0.3.0
func RunDashboard(sessions []protocol.SessionInfo, refresh func() []protocol.SessionInfo) *DashboardResult
type OverlayResult ¶
type OverlayResult struct {
Action string
SessionID string
CreateName string
CreateRepoPath string
CreateAgent string
Collapsed map[string]bool
}
OverlayResult holds the outcome of the overlay interaction.
func RunOverlay ¶
func RunOverlay(sessions []protocol.SessionInfo, currentSessionID string, fetchPreview func(sessionID string) string, refreshSessions func() []protocol.SessionInfo, deleteSession func(sessionID string) error, restartSession func(sessionID string) error, stopSession func(sessionID string) error, toggleStar func(sessionID string, star bool) error, profile string, collapsed map[string]bool, repoSuggestions []RepoSuggestion, shortcutKeys string, agents []string, defaultAgent string) *OverlayResult
RunOverlay launches the bubbletea overlay listing sessions grouped by repo. currentSessionID highlights the session the user was just attached to. fetchPreview is called asynchronously to load scrollback for the selected session.
type PassthroughKeys ¶
type PassthroughOpts ¶ added in v0.3.0
type PassthroughOpts struct {
Keys PassthroughKeys
SessionID string
Info *protocol.SessionInfo
StatusBar *StatusBarCfg
AutoPopApproval bool
}
type PassthroughResult ¶
type PassthroughResult int
const ( ResultDetached PassthroughResult = iota ResultOverlay ResultShell ResultQuit ResultDisconnected ResultRestart ResultNextSession ResultPrevSession ResultNewSession ResultForkSession ResultLastSession ResultApprovalOverlay ResultOrchestratorSession ResultMessageOverlay )
type RemoteHost ¶ added in v0.66.3
type RemoteHost struct {
Host string `json:"host"` // MagicDNS name / tailnet address
Port int `json:"port"` // remote listener port
Token string `json:"client_token"` // bearer token (this device's)
TLSPin string `json:"tls_pin_spki"` // pinned SPKI (TOFU)
Profile string `json:"daemon_profile"` // remote daemon profile (handshake must match)
}
RemoteHost is a paired remote graith daemon reachable over the tailnet (design §A/§B, #615). Credentials are minted by the remote daemon's `gr pair approve` and delivered in pair_response.
func PairRemote ¶ added in v0.66.3
func PairRemote(paths config.Paths, host string, port int, profile, deviceLabel, devicePubKey string) (*RemoteHost, error)
PairRemote performs the CLI side of device pairing with a remote daemon: it dials (capturing the server's SPKI pin via TOFU), handshakes, sends pair_request with the device public key, and blocks until the remote human runs `gr pair approve`, then returns the minted RemoteHost credentials. No token or proof-of-possession is used — this is the roleNone pairing lane.
type RemoteHostStore ¶ added in v0.66.3
type RemoteHostStore struct {
// DeviceKey is this device's ed25519 private key (base64), used for
// proof-of-possession against every paired remote daemon.
DeviceKey string `json:"device_key"`
Hosts map[string]*RemoteHost `json:"hosts"`
// contains filtered or unexported fields
}
RemoteHostStore persists this CLI's device identity and its paired remote hosts. It lives in the data dir (0600) — the local filesystem is the trust boundary, mirroring the daemon's 0700 socket.
func LoadRemoteHostStore ¶ added in v0.66.3
func LoadRemoteHostStore(path string) (*RemoteHostStore, error)
LoadRemoteHostStore loads the store, returning an empty one if the file does not exist.
func (*RemoteHostStore) EnsureDeviceKey ¶ added in v0.66.3
func (s *RemoteHostStore) EnsureDeviceKey() (ed25519.PrivateKey, string, error)
EnsureDeviceKey returns this device's ed25519 private key and base64 public key, generating and storing the key on first use. The caller should Save after a fresh key is generated.
func (*RemoteHostStore) Get ¶ added in v0.66.3
func (s *RemoteHostStore) Get(host string) (*RemoteHost, bool)
Get returns a paired host by name.
func (*RemoteHostStore) Names ¶ added in v0.66.4
func (s *RemoteHostStore) Names() []string
Names returns the paired host keys, sorted — for stable listings and error messages.
func (*RemoteHostStore) Put ¶ added in v0.66.3
func (s *RemoteHostStore) Put(h *RemoteHost)
Put stores/updates a paired host (keyed by Host).
func (*RemoteHostStore) Resolve ¶ added in v0.66.4
func (s *RemoteHostStore) Resolve(host string) (*RemoteHost, []string)
Resolve finds a paired host by exact key or by short-name/prefix match, so a user can type "myhost" for a host stored as "myhost.tailnet.ts.net". On a unique match it returns the host; otherwise it returns nil plus the sorted list of paired names (empty, or the candidates) for a helpful error.
func (*RemoteHostStore) Save ¶ added in v0.66.3
func (s *RemoteHostStore) Save() error
Save writes the store atomically (temp file + rename) with 0600 perms, so a crash mid-write can't corrupt the credential store or lose the device key, and an existing file with looser perms is replaced by a 0600 one.
type RepoSuggestion ¶ added in v0.52.0
func DiscoverRepos ¶ added in v0.52.0
func DiscoverRepos(allowedPaths []string, sessions []protocol.SessionInfo) []RepoSuggestion
type StatusBarCfg ¶ added in v0.3.0
type StatusBarCfg struct {
Position string
}