Documentation
¶
Overview ¶
Package config provides layered configuration loading.
Index ¶
- func ApplyOverrides(cfg *Config, o FlagOverrides)
- func GlobalConfigDir() string
- func IsHTTPURL(rawURL string) bool
- func LoadFromEnv(cfg *Config) error
- func NonInteractiveEnv() bool
- func NormalizeBaseURL(url string) string
- func RepoConfigPath() string
- type Config
- type FlagOverrides
- type ProfileConfig
- type ProfileLayer
- type ProfileOrigin
- type ReplacedProfileLayer
- type Source
- type TrustEntry
- type TrustStore
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ApplyOverrides ¶
func ApplyOverrides(cfg *Config, o FlagOverrides)
ApplyOverrides applies non-empty flag overrides to cfg. Exported so root.go can re-apply after profile overlay.
func GlobalConfigDir ¶
func GlobalConfigDir() string
GlobalConfigDir returns the global config directory path.
func IsHTTPURL ¶ added in v0.8.0
IsHTTPURL reports whether rawURL is an absolute http(s) URL with a host. Used to reject non-web schemes (file://, etc.) and hostless forms (e.g. "https:example.com", which url.Parse accepts with an empty Host) for llm_endpoint, since those would later be concatenated into a request URL and produce confusing/invalid requests.
func LoadFromEnv ¶
LoadFromEnv loads configuration from environment variables. Exported so root.go can re-apply after profile overlay.
Values are stored as-is, malformed or not — mirroring the trusted-file path in loadFromFile. Validation happens at use-time in summarize.ValidateEndpoint (the TUI's LLM path, the only consumer of llm_endpoint), which fails closed for providers that send llm_api_key to the endpoint. Other commands never consume the value, so `basecamp config unset llm_endpoint` (or unsetting the env var) can always repair a bad value. Erroring here would block every command — including the repair path — for all providers, even ones that never consume the endpoint.
Always returns nil today; the error return is kept so validation can be reintroduced for a specific variable without churning every caller.
func NonInteractiveEnv ¶ added in v0.8.0
func NonInteractiveEnv() bool
NonInteractiveEnv reports whether BASECAMP_NONINTERACTIVE is set to a truthy value. When true, the CLI must not show interactive prompts regardless of TTY detection. This is an escape hatch for agents and harnesses that run the CLI under an allocated PTY (where stdout looks like a terminal) and want to avoid a selection prompt wedging the session — without forcing a machine output format the way --agent does.
func NormalizeBaseURL ¶
NormalizeBaseURL ensures consistent URL format (no trailing slash).
func RepoConfigPath ¶ added in v0.2.2
func RepoConfigPath() string
RepoConfigPath walks up from CWD to find .basecamp/config.json at the git repo root. Returns empty string if not found or outside $HOME.
Types ¶
type Config ¶
type Config struct {
// API settings
BaseURL string `json:"base_url"`
AccountID string `json:"account_id"`
ProjectID string `json:"project_id"`
TodolistID string `json:"todolist_id"`
// Profile settings (named identity+environment bundles)
Profiles map[string]*ProfileConfig `json:"profiles,omitempty"`
DefaultProfile string `json:"default_profile,omitempty"`
ActiveProfile string `json:"-"` // Set at runtime, not persisted
// Auth settings
Scope string `json:"scope"`
// Cache settings
CacheDir string `json:"cache_dir"`
CacheEnabled bool `json:"cache_enabled"`
// Output settings
Format string `json:"format"`
// Behavior preferences (persisted via config set, overridable by flags)
Hints *bool `json:"hints,omitempty"`
Stats *bool `json:"stats,omitempty"`
Verbose *int `json:"verbose,omitempty"`
Onboarded *bool `json:"onboarded,omitempty"`
// LLM settings (for TUI smart zoom summarization)
LLMProvider string `json:"llm_provider,omitempty"`
LLMModel string `json:"llm_model,omitempty"`
LLMAPIKey string `json:"llm_api_key,omitempty"`
LLMEndpoint string `json:"llm_endpoint,omitempty"`
LLMMaxConcurrent int `json:"llm_max_concurrent,omitempty"`
LLMTokenBudget int `json:"llm_token_budget,omitempty"`
// Experimental feature flags (opt-in via "config set experimental.X true --global").
Experimental map[string]bool `json:"experimental,omitempty"`
// Sources tracks where each value came from (for debugging).
Sources map[string]string `json:"-"`
// ProfileOrigins records, per profile name, the config files its entry
// in Profiles was made from. Set by the file layers only: a profile an
// invocation adds to Profiles in memory has none.
ProfileOrigins map[string]*ProfileOrigin `json:"-"`
}
Config holds the resolved configuration.
func Load ¶
func Load(overrides FlagOverrides) (*Config, error)
Load loads configuration from all sources with proper precedence. Precedence: flags > env > local > repo > global > system > defaults
func (*Config) ApplyProfile ¶
ApplyProfile overlays profile values onto the config.
This is the first pass of a two-pass precedence system:
Pass 1 (this method): Profile values unconditionally overwrite config fields.
Pass 2 (caller): LoadFromEnv + ApplyOverrides re-apply env vars and CLI
flags, which take final precedence over profile values.
The caller in root.go MUST call LoadFromEnv and ApplyOverrides after this method to maintain the precedence chain: flags > env > profile > file > defaults.
func (*Config) IsExperimental ¶ added in v0.3.0
IsExperimental returns true if the named experimental feature is enabled.
type FlagOverrides ¶
type FlagOverrides struct {
Account string
Project string
Todolist string
Profile string
CacheDir string
Format string
}
FlagOverrides holds command-line flag values.
type ProfileConfig ¶
type ProfileConfig struct {
BaseURL string `json:"base_url"`
AccountID string `json:"account_id,omitempty"`
ProjectID string `json:"project_id,omitempty"`
TodolistID string `json:"todolist_id,omitempty"`
Scope string `json:"scope,omitempty"`
ClientID string `json:"client_id,omitempty"`
}
ProfileConfig holds configuration for a named profile.
type ProfileLayer ¶ added in v0.12.0
ProfileLayer is one config file's entry for a profile.
type ProfileOrigin ¶ added in v0.12.0
type ProfileOrigin struct {
// Layers are the files whose entries make up the profile, farthest
// first: the first defines it, and each later one refines it.
Layers []ProfileLayer
// Fields maps each field set on the profile, by its JSON key, to the
// path of the file that set it.
Fields map[string]string
// Replaced are the entries a closer one replaced whole, farthest
// first, each with the entry that replaced it. Nothing of them
// applies.
Replaced []ReplacedProfileLayer
}
ProfileOrigin is where a profile's effective entry came from. See mergeProfile for how entries from different files combine.
func (*ProfileOrigin) Closest ¶ added in v0.12.0
func (o *ProfileOrigin) Closest() ProfileLayer
Closest is the closest file contributing to the profile: the one whose fields win.
func (*ProfileOrigin) Includes ¶ added in v0.12.0
func (o *ProfileOrigin) Includes(source Source) bool
Includes reports whether a file of the given source contributes to the profile.
func (*ProfileOrigin) ReplacedLayer ¶ added in v0.12.0
func (o *ProfileOrigin) ReplacedLayer(source Source) *ReplacedProfileLayer
ReplacedLayer returns the replaced entry from a file of the given source, nil when no such entry was replaced.
type ReplacedProfileLayer ¶ added in v0.12.0
type ReplacedProfileLayer struct {
ProfileLayer
// By is the entry that replaced it: for another Basecamp, or for
// another account on the same one.
By ProfileLayer
}
ReplacedProfileLayer is a file's entry for a profile that a closer entry replaced whole, and the entry that replaced it.
type TrustEntry ¶ added in v0.2.2
TrustEntry records a single trusted config path and when it was trusted.
type TrustStore ¶ added in v0.2.2
type TrustStore struct {
// contains filtered or unexported fields
}
TrustStore manages the set of trusted local/repo config file paths. Trusted configs are allowed to set authority keys (base_url, profiles, default_profile) that are normally rejected from local/repo sources.
func LoadTrustStore ¶ added in v0.2.2
func LoadTrustStore(configDir string) *TrustStore
LoadTrustStore is a convenience that creates a TrustStore and verifies the backing directory exists. A missing file is fine (empty store); a missing directory is a no-op (returns nil store, no error).
func NewTrustStore ¶ added in v0.2.2
func NewTrustStore(configDir string) *TrustStore
NewTrustStore returns a TrustStore backed by trusted-configs.json in configDir.
func (*TrustStore) IsTrusted ¶ added in v0.2.2
func (ts *TrustStore) IsTrusted(path string) bool
IsTrusted reports whether path (after canonicalization) is in the trust store.
func (*TrustStore) List ¶ added in v0.2.2
func (ts *TrustStore) List() []TrustEntry
List returns all trusted entries.
func (*TrustStore) Trust ¶ added in v0.2.2
func (ts *TrustStore) Trust(path string) error
Trust adds path to the trust store (idempotent — re-trusting updates the timestamp).