Documentation
¶
Overview ¶
Package flags provides a layered feature flag resolver for the ox CLI.
Flags are resolved from multiple sources in ascending priority order:
defaults → daemon (remote settings) → env vars
Each source returns a Patch — only the fields it has an explicit opinion on. Nil fields in a Patch mean "no opinion" and won't override prior values. This lets sources be added or removed without changing merge semantics.
Usage:
// At CLI startup (zero network calls):
flags.Init(ctx, flags.DaemonProvider{CachedSettings: s}, flags.EnvProvider{})
// Anywhere in the process:
if flags.Get().DistillEnabled { ... }
Index ¶
Constants ¶
const CLISettingsFetchTimeout = 3 * time.Second
CLISettingsFetchTimeout is the maximum time to wait for /api/v1/cli/settings. Fail fast: if the server is slow, use cached/default values immediately.
const CLISettingsMaxAge = time.Hour
CLISettingsMaxAge is the maximum age of a cached CLISettingsResponse before it is considered stale. Stale cache is still used — the daemon refreshes in the background. This matches the 1-hour polling interval.
Variables ¶
This section is empty.
Functions ¶
func Init ¶
Init resolves flags from the given providers and stores the result globally. Providers are applied in the order given; later providers have higher priority. Safe to call multiple times (e.g., after daemon contact). Cost: no network calls — providers must not perform I/O during Patch().
func SaveCachedSettings ¶
func SaveCachedSettings(endpointURL string, r *CLISettingsResponse) error
SaveCachedSettings atomically writes r into a per-endpoint cache file. Creates the cache directory if needed. Each endpoint writes its own file, so concurrent writes for different endpoints cannot race or lose each other's data.
Types ¶
type CLIFeatures ¶
type CLIFeatures struct {
CodeDB *bool `json:"codedb,omitempty"`
Whisper *bool `json:"whisper,omitempty"`
Distill *bool `json:"distill,omitempty"`
AutoDistill *bool `json:"auto_distill,omitempty"`
TUI *bool `json:"tui,omitempty"`
}
CLIFeatures contains server-evaluated feature gate values. Fields are *bool so omitted JSON fields remain nil ("no opinion") rather than being zero-valued to false, which would incorrectly override default-on flags during rolling upgrades when the server hasn't added a new flag yet.
type CLIKillswitches ¶
type CLIKillswitches struct {
DisableFileDeleteTools bool `json:"disable_file_delete_tools"`
DisableShellExecTools bool `json:"disable_shell_exec_tools"`
}
CLIKillswitches contains server-evaluated kill switch values. All fields default to false (kill switches off) when the endpoint is unavailable.
type CLISettingsResponse ¶
type CLISettingsResponse struct {
Features CLIFeatures `json:"features"`
Killswitches CLIKillswitches `json:"killswitches"`
// PrimeAppend is appended to ox agent prime output after team context.
// Allows the cloud to push org-wide prime additions without a CLI release.
PrimeAppend string `json:"prime_append,omitempty"`
FetchedAt time.Time `json:"fetched_at"`
}
CLISettingsResponse is the wire type for GET /api/v1/cli/settings.
sage-mono evaluates PostHog feature flags server-side (using device_id + user_id as distinct IDs) and returns pre-evaluated booleans. The ox CLI receives evaluated values — no PostHog SDK is needed in the CLI binary.
If the endpoint is unreachable, Defaults are used. The daemon polls this endpoint on a background interval (see ox-ha7r) and caches the result to disk so CLI startup never blocks on a network call.
func LoadCachedSettings ¶
func LoadCachedSettings(endpointURL string) (*CLISettingsResponse, error)
LoadCachedSettings reads the cached CLISettingsResponse for the given endpoint. Returns nil with no error if the file doesn't exist or is corrupt — callers treat nil as "no cached settings, use defaults".
type DaemonProvider ¶
type DaemonProvider struct {
// CachedSettings is populated by the daemon IPC settings_get handler.
// Nil means the daemon has not yet fetched remote settings.
CachedSettings *CLISettingsResponse
}
DaemonProvider reads a pre-fetched CLISettingsResponse from the daemon IPC cache. At CLI startup, initFeatureFlags() queries the daemon via IPC (settings_get) and falls back to disk cache. The daemon polls GET /api/v1/cli/settings on a background interval (CLISettingsMaxAge).
type EnvProvider ¶
type EnvProvider struct{}
EnvProvider reads FEATURE_* environment variables and maps them onto flag fields. Only variables that are explicitly set (non-empty) contribute a patch — unset variables leave the corresponding field nil (no opinion).
This preserves backward compatibility with the existing FEATURE_* conventions in internal/auth/feature.go without requiring changes to those call sites.
type Flags ¶
type Flags struct {
// Feature gates — default true for authenticated users.
// A server-side kill switch or env override can set these false.
CodeDBEnabled bool
WhisperEnabled bool
DistillEnabled bool
AutoDistill bool
TUIEnabled bool
// Kill switches — default false (not activated).
// Any source setting these true disables the capability.
DisableFileDeleteTools bool
DisableShellExecTools bool
// PrimeAppend is injected after team context in ox agent prime output.
// Set by the remote settings endpoint to push org-wide prime additions
// without requiring a CLI release or changes to CLAUDE.md.
PrimeAppend string
}
Flags is the fully resolved set of feature flags for the current process. All fields have safe defaults via Defaults.
func Defaults ¶
func Defaults() Flags
Defaults returns the baseline Flags used when no provider has an opinion. Feature gates are on; kill switches are off; string fields are empty.
type Patch ¶
type Patch struct {
CodeDBEnabled *bool
WhisperEnabled *bool
DistillEnabled *bool
AutoDistill *bool
TUIEnabled *bool
DisableFileDeleteTools *bool
DisableShellExecTools *bool
PrimeAppend *string
}
Patch is a partial flag override from a single source. Nil fields mean "no opinion" — they are skipped during merge. NOTE: When adding fields, also update allNil() in env.go and applyPatch() in resolve.go.
func RemoteSettingsToPatch ¶
func RemoteSettingsToPatch(r *CLISettingsResponse) *Patch
RemoteSettingsToPatch converts a CLISettingsResponse into a Patch. Called by the daemon after a successful fetch before caching.
type Provider ¶
Provider supplies a partial set of flag overrides from one source. Returning (nil, source, nil) means this provider has no opinion right now.