Skip to content

config

import "github.com/linuskendall/cosmonaut/internal/config"

Package config loads the cosmonaut JSONC configuration file and defines the Target struct that describes a named codespace target (repository, branch, machine type, Zed display settings, etc.).

Index

Variables

DaemonFieldDocs is the authoritative documentation for DaemonConfig fields.

var DaemonFieldDocs = []FieldDoc{
    {"hotkey", "string", false, "Global hotkey (e.g. Cmd+Shift+S)"},
    {"terminal", "string", false, "Terminal app for picker; auto to detect"},
    {"inhibitSleep", "string", false, "Hold sleep/shutdown inhibitor while a codespace session is active: off (default), sleep, or sleep+shutdown"},
}

TargetFieldDocs is the authoritative documentation for every Target field.

var TargetFieldDocs = []FieldDoc{
    {"repository", "string", false, "GitHub repository in owner/repo form; optional for Coder targets"},
    {"branch", "string", false, "Preferred branch when creating or matching a codespace"},
    {"displayName", "string", false, "Exact display name to disambiguate codespace matches"},
    {"codespaceName", "string", false, "Exact codespace name for strict reuse"},
    {"workspacePath", "string", true, "Remote folder Zed should open (e.g. /workspaces/repo)"},
    {"machine", "string", false, "Machine type forwarded to gh codespace create"},
    {"location", "string", false, "Location forwarded to gh codespace create"},
    {"devcontainerPath", "string", false, "Dev container config path forwarded to gh codespace create"},
    {"idleTimeout", "string", false, "Idle timeout forwarded to gh codespace create (e.g. 30m)"},
    {"retentionPeriod", "string", false, "Retention period forwarded to gh codespace create (e.g. 720h)"},
    {"uploadBinaryOverSsh", "bool", false, "Set Zed's upload_binary_over_ssh for this host"},
    {"zedNickname", "string", false, "Friendly name shown in Zed's remote project list"},
    {"autoStop", "string", false, "Auto-stop codespace after idle duration (e.g. 30m)"},
    {"preWarm", "string", false, "Time-of-day to pre-warm codespace (e.g. 08:00)"},
    {"coder", "object", false, "Coder-specific target settings: template, workspaceName, parameters, stopAfter, organization, portForwards"},
}

func DaemonFieldsHelp

func DaemonFieldsHelp() string

DaemonFieldsHelp returns a formatted help string for daemon config fields.

func ParseJSONC

func ParseJSONC(source string) ([]byte, error)

ParseJSONC strips comments and trailing commas, then returns clean JSON bytes. The conversion uses a real JWCC parser (tailscale/hujson), not regexes: comment markers or ",}" sequences inside string values — shell snippets in coder.parameters, glob patterns — pass through untouched instead of silently corrupting the config, and malformed input is reported as an error instead of producing garbage.

func SaveConfig

func SaveConfig(path string, cfg *Config) error

SaveConfig writes the config to the given path as formatted JSON with 4-space indentation for easy hand-editing.

Takes the write lock for the duration of the marshal so a concurrent writer can't mutate the struct mid-serialization. A nil config is an error: marshaling nil would write the literal `null` over the user's config file.

func TargetFieldsHelp

func TargetFieldsHelp() string

TargetFieldsHelp returns a formatted help string for all target fields.

func WorkspaceSSHKey

func WorkspaceSSHKey(provider, name string) string

WorkspaceSSHKey returns the canonical map key used by Config.WorkspaceSSH for a workspace. Stable across renames since both provider and the provider-issued name are immutable.

type CoderProviderConfig

type CoderProviderConfig struct {
    Organization string `json:"organization,omitempty"`
}

type CoderTargetConfig

type CoderTargetConfig struct {
    Template      string            `json:"template,omitempty"`
    WorkspaceName string            `json:"workspaceName,omitempty"`
    Parameters    map[string]string `json:"parameters,omitempty"`
    StopAfter     string            `json:"stopAfter,omitempty"`
    Organization  string            `json:"organization,omitempty"`
    PortForwards  []PortForward     `json:"portForwards,omitempty"`
}

type Config

type Config struct {
    DefaultTarget     string            `json:"defaultTarget,omitempty"`
    WorkspaceProvider string            `json:"workspaceProvider,omitempty"` // "github" (default) or "coder"
    Editor            string            `json:"editor,omitempty"`            // any binary on PATH; "" / "zed" / "zeditor" use the built-in Zed integration
    Providers         ProviderConfigs   `json:"providers,omitempty"`
    Targets           map[string]Target `json:"targets"`
    Daemon            *DaemonConfig     `json:"daemon,omitempty"`

    // WorkspaceSSH holds per-workspace SSH options keyed by "<provider>:<name>"
    // (e.g. "github:cs-abc" or "coder:my-ws"). Unset workspaces fall back to
    // the global defaults: ControlMaster on, Tmux off.
    WorkspaceSSH map[string]WorkspaceSSHSettings `json:"workspaceSsh,omitempty"`
    // contains filtered or unexported fields
}

func LoadConfig

func LoadConfig(path string) (*Config, error)

LoadConfig reads a JSONC config file and returns the parsed Config.

LoadConfig returns a freshly-allocated *Config that no other goroutine has a reference to yet, so it doesn't need to hold the mutex while populating it.

func (*Config) CoderOrganization

func (c *Config) CoderOrganization() string

CoderOrganization returns Providers.Coder.Organization under the read lock.

func (*Config) EffectiveWorkspaceProvider

func (c *Config) EffectiveWorkspaceProvider() string

func (*Config) EnsureDaemon

func (c *Config) EnsureDaemon() DaemonConfig

EnsureDaemon initialises Config.Daemon to a zero-value DaemonConfig if it's nil, and returns a snapshot of the current daemon settings under the read lock. The returned struct is a copy: mutating it does not affect the live config — use the SetDaemon* helpers for that.

func (*Config) GetDefaultTarget

func (c *Config) GetDefaultTarget() string

GetDefaultTarget returns the DefaultTarget name under the read lock.

func (*Config) GetEditor

func (c *Config) GetEditor() string

GetEditor returns the configured editor name.

func (*Config) SetDaemonHotkey

func (c *Config) SetDaemonHotkey(hotkey string)

SetDaemonHotkey persists the daemon Hotkey field. Daemon is auto-created if nil. An empty string falls back to the platform default at register time.

func (*Config) SetDaemonInhibitSleep

func (c *Config) SetDaemonInhibitSleep(mode string)

SetDaemonInhibitSleep persists the daemon InhibitSleep field. Daemon is auto-created if nil.

func (*Config) SetEditor

func (c *Config) SetEditor(editor string)

SetEditor persists the editor name. Callers should follow up with SaveConfig to flush to disk.

func (*Config) SetTarget

func (c *Config) SetTarget(name string, t Target)

SetTarget writes a deep copy of t into the Targets map, so later caller mutations of t (or its Coder sub-struct) can't reach into the live config. The Targets map is auto-created if nil.

func (*Config) SetWorkspaceSSHControlMaster

func (c *Config) SetWorkspaceSSHControlMaster(provider, name string, val *bool)

SetWorkspaceSSHControlMaster persists an explicit ControlMaster setting for a workspace. Passing nil clears it (so the default applies).

func (*Config) SetWorkspaceSSHTmux

func (c *Config) SetWorkspaceSSHTmux(provider, name string, val *bool)

SetWorkspaceSSHTmux persists an explicit Tmux setting for a workspace. Passing nil clears it (so the default applies).

func (*Config) Target

func (c *Config) Target(name string) (Target, bool)

Target returns a deep copy of the named target, or the zero value with ok=false when no such target is configured. The copy shares no pointers with the live config, so callers may freely mutate it (e.g. to stage a launch override) without racing concurrent readers or leaking the change back into the config.

func (*Config) TargetsSnapshot

func (c *Config) TargetsSnapshot() map[string]Target

TargetsSnapshot returns a deep copy of the Targets map taken under the read lock. Safe to iterate or mutate without further locking; mutations do not affect the live config.

func (*Config) UpdateTarget

func (c *Config) UpdateTarget(name string, fn func(t *Target, exists bool))

UpdateTarget performs a read-modify-write on the named target atomically. The callback receives a deep copy of the target (so mutating nested pointers like Coder never aliases the live config) plus whether the target already existed; whatever the callback leaves in *t is written back. The Targets map is auto-created if nil.

func (*Config) WithEditor

func (c *Config) WithEditor(editor string, fn func())

WithEditor swaps in a temporary editor for the duration of fn (typically a launch flow whose editor override should not leak to the persistent config) and restores the prior value when fn returns. Holds the write lock for the whole window so no concurrent reader observes a half-swapped state.

func (*Config) WorkspaceSSHControlMaster

func (c *Config) WorkspaceSSHControlMaster(provider, name string) bool

WorkspaceSSHControlMaster returns the resolved ControlMaster setting for a workspace, with the default (true) applied when no explicit value is set.

func (*Config) WorkspaceSSHTmux

func (c *Config) WorkspaceSSHTmux(provider, name string) bool

WorkspaceSSHTmux returns the resolved Tmux setting for a workspace, with the default (false) applied when no explicit value is set.

type DaemonConfig

DaemonConfig holds settings for the background daemon (tray, hotkey, poller).

type DaemonConfig struct {
    Hotkey       string `json:"hotkey,omitempty"`       // e.g. "Cmd+Shift+S" (macOS) or "Ctrl+Shift+S" (Linux)
    Terminal     string `json:"terminal,omitempty"`     // terminal app to launch picker in; "auto" to detect
    InhibitSleep string `json:"inhibitSleep,omitempty"` // "off" (default), "sleep", or "sleep+shutdown"
}

type FieldDoc

FieldDoc describes a single config target field for generated documentation.

type FieldDoc struct {
    JSON     string // JSON key name
    Type     string // human-readable type
    Required bool
    Desc     string
}

type GitHubProviderConfig

type GitHubProviderConfig struct{}

type PortForward

type PortForward struct {
    Label      string `json:"label,omitempty"`
    LocalPort  int    `json:"localPort,omitempty"`
    RemotePort int    `json:"remotePort,omitempty"`
    Protocol   string `json:"protocol,omitempty"`
}

type ProviderConfigs

type ProviderConfigs struct {
    GitHub GitHubProviderConfig `json:"github,omitempty"`
    Coder  CoderProviderConfig  `json:"coder,omitempty"`
}

type Target

type Target struct {
    Repository          string             `json:"repository,omitempty"`
    Branch              string             `json:"branch,omitempty"`
    DisplayName         string             `json:"displayName,omitempty"`
    CodespaceName       string             `json:"codespaceName,omitempty"`
    WorkspacePath       string             `json:"workspacePath"`
    Machine             string             `json:"machine,omitempty"`
    Location            string             `json:"location,omitempty"`
    DevcontainerPath    string             `json:"devcontainerPath,omitempty"`
    IdleTimeout         string             `json:"idleTimeout,omitempty"`
    RetentionPeriod     string             `json:"retentionPeriod,omitempty"`
    UploadBinaryOverSSH *bool              `json:"uploadBinaryOverSsh,omitempty"`
    ZedNickname         string             `json:"zedNickname,omitempty"`
    AutoStop            string             `json:"autoStop,omitempty"` // auto-stop after idle duration (e.g. "30m")
    PreWarm             string             `json:"preWarm,omitempty"`  // time-of-day to pre-warm codespace (e.g. "08:00")
    Coder               *CoderTargetConfig `json:"coder,omitempty"`
}

func (Target) Clone

func (t Target) Clone() Target

Clone returns a deep copy of the target: the Coder sub-struct (with its Parameters map and PortForwards slice) and the UploadBinaryOverSSH pointer are duplicated, so mutating the copy never writes through to the original.

func (Target) ExplicitWorkspaceName

func (t Target) ExplicitWorkspaceName(provider string) string

type WorkspaceSSHSettings

WorkspaceSSHSettings stores per-workspace SSH knobs. Each field is a pointer so "unset" can be distinguished from an explicit on/off.

type WorkspaceSSHSettings struct {
    // ControlMaster enables OpenSSH connection multiplexing
    // (ControlMaster auto + ControlPersist) in the managed extras block,
    // so additional sessions to the same workspace reuse the existing TCP
    // connection. Default: true.
    ControlMaster *bool `json:"controlMaster,omitempty"`
    // Tmux wraps `cosmonaut shell` (and the GUI's SSH button) in
    // `tmux new -A -s cosmonaut` on the remote so the shell session
    // survives SSH drops. Default: false.
    Tmux *bool `json:"tmux,omitempty"`
}

Generated by gomarkdoc