Skip to content

Feature flag configuration

Configuration and persisted state for SASE feature flags.

feature_flags

feature_flags is the portable user and project override surface for code-owned SASE feature flags. Registry defaults live in src/sase/feature_flags/registry.py; the config block only overrides registered keys. It remains valid and lower-precedence than a saved machine preference. The Config Flags pane and sase flag enable / sase flag disable never edit this block, overlays, project-local sase.yml, or chezmoi source.

feature_flags:
  demo_key: true

The generated JSON Schema exposes one boolean property per registered flag with its description and default. Unknown keys are tolerated by the schema so downgraded installs can still read a config written by a newer SASE, but the resolver warns and ignores unknown keys at runtime.

beta flags default off and gate work that is still landing; sunset flags default on and keep a fallback path reachable until the flag is removed. The schema marks sunset flags deprecated. One sunset flag is currently registered: artifacts_agent_pane_retired (default on) hides the Artifacts ▸ Agent sub-tab and moves agent history to the Agents tab Archive (,a). To opt out and restore the pane, run sase flag disable artifacts_agent_pane_retired or set feature_flags: {artifacts_agent_pane_retired: false} in configuration. Apart from that flag, the typed sudo request workflow (sase sudo) and its review modal are always available, only agent_meta.autonomy carries %auto state, and a hard provider disable relaunches stranded agents through sase agent drain (see llm_provider.usage_limit and Launch Control's automatic provider drain in Launch Control).

Data decks and agent tabs are always available; configure them through the Agents tab reference, not feature flags. An unregistered key in feature_flags.json is removed the next time an installing process reconciles the file.

Use session and turn spellings in new prompts and config, and --name for proc list and run commands. See Agent launch spellings for accepted compatibility forms.

Macro name and field compatibility is described in the macro migration notes.

For owner-manifest compatibility rules, see Agent Hood Synchronization.

%if:: script-admission and %proc are always available: parser, completion, and launch-plan contract included. Static %if(should_run=true|false) segment omission works before typed launch planning. User-initiated sase's TUI and sase run submissions execute typed directives through durable typed admission without a LaunchApproval gate. The frozen plan keeps the complete %id and %clan identity binding, and keyed {@<id>} markers resolve once at batch creation. Agent-initiated launches still freeze the typed plan for LaunchApproval; after approval, the same admission coordinator resolves waits, evaluates %if:: predicates, and dispatches eligible units — agent units through the established agent launch path, and %proc units through native stand-alone named-proc dispatch; see Typed launch units.

Saved machine preferences

Persistent enable/disable choices live in a SASE-owned machine-state file $SASE_HOME/feature_flags.json (normally ~/.sase/feature_flags.json), not in configuration. The file is a bounded JSON object of exact booleans keyed by registered flag names; equal-to-default values are still stored because enable and disable are durable user choices. Inspect the path with sase flag show <key> or the Flags pane detail card (STATE).

{
  "version": 1,
  "flags": {
    "demo_key": true
  }
}

Missing state is an empty snapshot (every flag uses its registry/config default). A malformed, oversized, or unsupported whole file is not silently deleted or overwritten: reads return no preferences plus a diagnostic, mutations fail with the path and a recovery-oriented message, and registered flags still resolve from lower layers.

Valid unknown keys in the machine-state file are tolerated by registry-neutral reads and writes. Installing processes reconcile the file against the running SASE registry and remove unregistered saved entries. The TUI defers cleanup until its initial surface is ready and then shows one toast; AXE and agent runners report cleanup on stderr. If no unregistered keys are present, the file is left unchanged. If cleanup fails or the file becomes unusable, SASE preserves it, keeps the diagnostic, and retries on the next startup.

Misspelled and unregistered saved keys are removed during reconciliation. After a downgrade, registered flags resolve from registry and config defaults until a choice is saved again. Portable YAML feature_flags entries are diagnosed and ignored when unknown; they are not rewritten.

Resolution order

Effective value is resolved in this order, later sources winning:

registry default
  < user config
  < overlay config
  < saved machine preference (SAVED)
  < explicit in-process/test override
  < SASE_FEATURE_FLAGS transport / environment variable
  < root CLI -f/--enable-feature or -F/--disable-feature

Plugin config layers never flip first-party flag defaults. A local-config entry for any feature flag is ignored with a scope_violation warning: a feature flag cannot be set from the local config layer, because sase's TUI disables project-local config and flags must resolve consistently across frontends.

The Flags pane and sase flag list / show report effective state and saved state separately. Provenance SAVED means the machine-state file won. If environment or root CLI overrides still shadow the saved choice, the UI shows a “forced for this process” warning rather than pretending the toggle already controls this process. Saving still restarts sase's TUI and the service host; the saved value takes effect once that higher source is removed.

Root-level -f/--enable-feature and -F/--disable-feature force a registered flag on or off for one sase invocation. They must appear before the subcommand (sase -f demo_key run "..."). They outrank every config layer, a saved machine preference, and an inherited SASE_FEATURE_FLAGS value, and they merge into SASE_FEATURE_FLAGS so launched agents and other child processes inherit the same overrides.

SASE_FEATURE_FLAGS is a strict JSON object of booleans, for example {"demo_key":false}. Malformed JSON, a non-object payload, or a non-boolean value is a startup error for that process. SASE-launched children inherit a resolved snapshot through the same variable, so sase flag list marks env provenance prominently. CLI overrides are marked the same way (CLI:--enable-feature / CLI:--disable-feature). After a successful save, SASE merges the chosen key into SASE_FEATURE_FLAGS so an sase's TUI execv restart does not inherit the old pinned snapshot above the new saved value.

Enable, disable, and restart

sase flag enable <flag>
sase flag disable <flag>

Both commands persist the choice in the machine-state file and, on success, restart the scheduler service proc when it is already running. A stopped scheduler is left stopped. They never start a proc the user had stopped, and they never signal a sase's TUI session in another terminal — restart any separately running sase's TUI yourself. Repeating an already-saved enable or disable is idempotent for the store but still retries that scheduler restart. A restart failure does not roll back the saved preference: rich and JSON output distinguish mutation from restart so a partial success is safe to retry. Unknown flags are usage errors (exit 2); store or restart failures use exit 1. --json emits one versioned document with separate mutation and restart objects.

From Config > Flags, a confirmed toggle uses the same mutation path, then waits for TUI-local tasks and installation changes and performs one controlled sase's TUI and service host restart. Independent commands keep running.

Create temporary flags with sase flag new <key> rather than editing the registry by hand. The command creates a task bead of type flag, prints the registry entry, and gives the both-states test checklist. Kinds are beta (default off) and sunset (default on); the registry default is derived from the kind. See Beads for the removal lifecycle.

Source: src/sase/feature_flags/registry.py, src/sase/feature_flags/schema.py, src/sase/feature_flags/snapshot.py, src/sase/feature_flags/state.py

sase flag

With no subcommand, sase flag defaults to sase flag list.

Moved to sase flag.

Moved to Feature flag configuration.

Command behavior

Unknown keys on enable/disable exit 2. Store or scheduler-restart failures exit 1; JSON then has "ok": false with the preference still recorded under mutation. --json emits one versioned document with separate mutation and restart objects. Neither command edits portable config files.

A non-empty human sase flag list ends with a compact statistics footer: how many flags were rendered and which kinds they use, how many resolve on versus off, how many decisions came from a layer above the registry default, and whether any loaded removal bead is soon or due. Homogeneous kind or on/off values fold into the count head. For example:

3 flags · 2 beta  1 sunset · 2 on  1 off · 1 overridden · ⧗ 1 soon  ⧗ 1 due

--json keeps schema version 1 and does not include this footer.

new requires a SASE-managed checkout because the registry lives in this source tree. --when-enabled, --when-disabled, and --remove-when are required and each accepts @<path>. -k/--kind is beta (default; off) or sunset (on). There is no --scope.

_[project]: A sase project is a named unit of work registered with SASE. _[workspace]: A sase workspace is a numbered clone of a project's primary repo, managed by the workspace store and tracked in that project's registry.json. _[agent]: A sase agent is an agent session or a single agent that does not belong to a session. _[prompt]: A prompt is the text SASE hands to a provider to start an agent turn. _[macro]: A macro is a reusable prompt triggered with #name in agent prompts. _[Patch]: A Patch is SASE's local unit of change. _[bead]: A bead is one tracked work item in SASE's git-native issue tracker. _[plan]: A plan is a persisted, approved artifact recording the intent behind agent work. _[TUI]: The TUI is SASE's terminal interface for running agents and reviewing results. _[epic]: An epic is an executable multi-phase plan run with sase bead work. _[gate]: A sase gate is a durable, command-backed request for one user decision, created when work must pause for the user. _[monitor]: A sase monitor is a monitor turn that runs one long command under a detached supervisor, so the command outlives the agent that started it. *[stitch]: A stitch is the lightweight ordered change record inside a Patch's STITCHES: section.