SAGE’s default UX when you run sage in a TTY is a persistent REPL: one process stays open and reads line-oriented input via Python Prompt Toolkit (not input()), so completion, key bindings, and the bottom status bar work reliably.
| Mechanism | Role |
|---|---|
| PromptSession | Keeps the prompt active; maintains history and layout. |
| Buffer | Holds the current line; updates on each keystroke before Enter. |
Custom completer (_SageSlashCompleter) |
Treats the last token as the prefix, including a leading /. |
Key binding on / |
Inserts / and calls start_completion so the menu opens immediately. |
| Enter | Submits the whole line to SAGE for parsing (/run …, NL, etc.). |
| Variable | Effect |
|---|---|
SAGE_SHELL_SIMPLE_INPUT=1 |
Disable prompt_toolkit; plain input() — no / menu. |
SAGE_SHELL_COLUMN_COMPLETIONS=1 |
Floating column completion menu (full terminal). |
SAGE_SHELL_READLINE_COMPLETIONS=1 |
List-style completions (Linux console / some SSH). |
SAGE_SHELL_NO_STATUSBAR=1 |
Hide the bottom status block. |
SAGE_SHELL_INTENT |
heuristic | ollama | off — NL routing before run. |
SAGE_REPO_URL |
Base URL for repo/doc links printed after /commands. |
SAGE_VERIFY_TIMEOUT_S |
Cap for planner verification subprocesses (seconds). Unset = no cap. 0 = unlimited. |
SAGE_RUN_OUTPUT |
summary (default) — end-of-run Goal / Plan / Files / Outcome panels. full — short verify labels + metrics line (.sage/last_run_metrics.json, checkpoint/intervention counts). debug — verbose [Verify] Running: … lines. |
After sage run (including /run from the shell), the CLI prints a structured Rich report.
sage run "your goal" [--research | --auto | --silent] [--no-clarify] [--plan-only] [--dry-run]
[--plan] [--resume] [--repo PATH] [--explain-routing] [--fresh]
[--include GLOB ...]
| Mode / flag | Behavior |
|---|---|
--research (default) |
Human checkpoints: post-plan approval (a approve / r reject / e edit .sage/last_plan.json then another sage run "…" without --fresh), escalation when the intel feed requires review, destructive tool apply confirmations where applicable. |
--auto |
Fewer interactive checkpoints (still logs). |
--silent |
Most autonomous; skips failed tasks per policy. |
--no-clarify |
Planner does not ask TTY clarifying questions (SAGE_NO_CLARIFY=1 same). |
--plan-only |
Prints planner DAG and writes .sage/last_plan.json; no tool execution. |
--plan |
Before the coder starts each task, the model proposes a step-by-step plan and waits for y / n (auto-proceeds when not a TTY). |
--dry-run |
Does not apply file patches (verification may still run where applicable). |
--resume |
Reload the loop checkpoint saved at .sage/loop_checkpoint.bin and continue from the last completed turn. No-ops if no checkpoint exists. |
--repo PATH |
Point at an existing repo for codebase intelligence (indexing / retrieval). |
--explain-routing |
After the run, print a routing decision summary for the session. |
--fresh |
Ignore memory/handoff.json (no resume from interrupt snapshot). |
--include GLOB |
Repeatable planner scope hints (e.g. src/**/*.py). |
Non-interactive automation: set SAGE_NON_INTERACTIVE=1 so plan checkpoints default to approve without blocking on stdin.
Interrupt resume: If memory/handoff.json exists, the next sage run "your goal" loads it unless you pass --fresh. For mid-task loop resume, use --resume which reloads .sage/loop_checkpoint.bin (written after every tool turn and on Ctrl-C).
Embed file content directly in a prompt using @path/to/file syntax:
sage run "Refactor @src/api/auth.py to use JWT — see @docs/auth_spec.md"Any token matching @<path>.<ext> is replaced with the file's content (up to 8 000 chars) before the run starts. Useful for attaching context files, specs, or examples without copy-pasting.
| Variable | Effect |
|---|---|
SAGE_SESSION_ID |
Set by the CLI per run; correlates structured logs. |
SAGE_TRACE_ID |
Optional correlation id (also in .sage/last_run_metrics.json). |
SAGE_WORKSPACE_ROOT |
Set by the CLI to the run cwd. |
SAGE_MODEL_PROFILE |
e.g. test — use the test profile in models.yaml for all roles (small local models in CI/laptop). |
SAGE_MODELS_YAML |
Override path to models.yaml (default: ~/.config/sage/models.yaml or bundled). |
SAGE_BENCH |
When set by sage bench, adjusts timeouts/profile. |
SAGE_PARALLEL_CONFLICT_UI |
Default 1 — Rich panel when parallel workers hit file-lock conflicts; set 0 to disable. |
End-of-run metrics JSON: .sage/last_run_metrics.json (task counts, models_used, prompt_quality_delta, local_vs_cloud_ratio, human_checkpoints_reached, …).
Run sage init in the project directory you want SAGE to work in (it does not install SAGE — use startup.sh from the SAGE repository clone for that).
sage init creates .sage/, ensures memory/, default .sage/rules.md, pytest.ini hints, and updates .gitignore. The CLI prints a Next panel with a sample sage run and SAGE_MODEL_PROFILE=test.
Note: startup.sh exists only in the SAGE repo root, not in each project folder.
Merged USER_RULES load in this order (later files append; models see the full stack):
~/.sage/rules.md(global).sage/rules.md(project).sage/rules.<agent>.md(per agent, e.g.rules.coder.md)- Legacy
.sage-rules.mdif present
Commands:
sage rules— print merged rules (--agent,--path,--repoas needed).sage rules validate— heuristic contradiction / safety checks (--strictexits non-zero on warnings).sage rules add "Your rule sentence"— append to.sage/rules.md(--globalfor~/.sage/rules.md).
sage memory— list files undermemory/.sage memory digest— aggregate session logs + fix patterns intomemory/weekly_digest.md(override with--out).
Session state: memory/system_state.json. Handoff: memory/handoff.json.
| Command | What it does |
|---|---|
/compact |
Compress the current conversation history in-place — keeps the last assistant message and a summary; frees context for long sessions. Prints Context compressed: N → M messages. |
/history |
Show the last 10 turns of the current session (role + first 120 chars). |
/clear |
Wipe the session history and start fresh. |
/chat |
Open a multi-turn local LLM chat thread (saved under .sage/chat_sessions/). |
/run <goal> |
Kick off sage run from inside the shell without opening a new terminal. |
/commands |
Print all available slash commands with short descriptions. |
Query the task database for past runs:
sage history [--days N] [--agent AGENT] [--status STATUS] [--limit N]
| Flag | Default | Effect |
|---|---|---|
--days N |
7 | Look back N calendar days. |
--agent AGENT |
all | Filter by agent name (coder, reviewer, …). |
--status STATUS |
all | Filter by task status (completed, failed, blocked). |
--limit N |
50 | Maximum rows to show. |
Output is a Rich table: task id, status (colour-coded), agent, description, timestamp.
Run sage commands or sage → /commands for the full catalog.
| Command | Purpose |
|---|---|
sage shell / bare sage (TTY) |
Interactive slash-command shell (default when no subcommand) |
sage tui |
Full-screen Textual UI (pip install 'sage[tui]' or textual) |
sage doctor |
Environment: Python, venv, Ollama, models.yaml, optional Textual for TUI (--json) |
sage status |
Last saved session snapshot |
sage session |
reset / refresh / status / handoff (view or --clear interrupt handoff) |
sage prep |
Hardware scan + recommended Ollama pulls (--disk-budget, --json) |
sage setup |
scan | suggest | apply | pull | init — machine-aware Ollama routing (interactive wizard on first run) |
sage index |
Build or rebuild the Qdrant semantic code index under .sage/qdrant_code_index/ |
sage config |
show | validate | migrate | paths | set — inspect/edit models.yaml |
sage bench |
Benchmark suite; --out, --run-pack-dir, --compare-policy |
sage permissions |
Tool policy; permissions set … writes .sage/policy.json |
sage rl |
export, collect-synth, analyze-rewards, eval-offline, train-bc, train-cql |
sage sim |
generate (oracle JSONL), run (parallel pytest; optional --docker) |
sage cron |
weekly-memory-optimizer — run maintenance jobs on demand |
sage eval |
golden | e2e | smoke — trust / regression checks (see tests) |
RL and simulator walkthrough → getting_started.md.
On first install — or any time you want to reassign resources — run the interactive wizard:
sage setupThis runs four stages:
- Scan — detects RAM (GiB), VRAM (via nvidia-smi / rocm-smi), CPU cores, and free disk under the Ollama model dir.
- Suggest — maps detected hardware to a model tier (minimal / light / balanced / large) and lets you choose a quality preference (speed / balanced / quality).
- Apply — writes the chosen stack into
models.yaml(planner, architect, coder, shell roles). - Pull — downloads any missing Ollama models with a Rich progress bar (skips already-present ones).
Results are saved to .sage/hardware.json for future headless re-runs (sage setup --headless).
| Tier | RAM threshold | Tiny / shell | Coder | Planner / Architect |
|---|---|---|---|---|
| minimal | < 5 GiB | 1.5b | 1.5b | 1.5b |
| light | 5–12 GiB | 1.5b | 7b | 1.5b |
| balanced | 12–24 GiB | 1.5b | 7b | 14b |
| large | ≥ 24 GiB | 1.5b | 14b | 32b |
quality_preference = "quality" bumps effective RAM +20% (moves to the next tier); "speed" drops it −20%.
SAGE maintains a local Qdrant vector index over your project's source files so that the context compressor can retrieve the most relevant code chunks before sending prompts to the LLM.
sage index # full rebuild (first run or after large refactors)The index lives at .sage/qdrant_code_index/ and is updated incrementally after every file write or edit inside an agent tool-use loop — no manual rebuild needed during normal operation.
Supported extensions: .py .ts .js .jsx .tsx .go .rs .java .cpp .c .h .md .yaml .yml .toml .json
Skipped directories: .git .venv venv __pycache__ node_modules .sage dist build
Chunk size: 40 lines with a 30-line stride.
Requires qdrant-client (pip install qdrant-client). If not installed, sage index prints an install hint and exits — SAGE still works without it (Qdrant retrieval is skipped gracefully).
SAGE tracks context usage per turn and reacts before hitting the model's context window:
| Threshold | Action |
|---|---|
| 80 % of context window | Inserts a warning message into the conversation with exact token counts; the agent can choose to summarise or wrap up. |
| 90 % | Prunes the oldest assistant turns (keeps the system prompt + last 6 messages) — or calls the LLM to auto-compact if SAGE_AUTO_COMPACT=1. |
| Variable | Effect |
|---|---|
SAGE_AUTO_COMPACT=1 |
At 90 % context usage, ask the LLM to produce a one-paragraph summary of the oldest half of the conversation before pruning. Off by default (hard prune). |
Token estimation: 1 token ≈ 4 characters (character-count heuristic, no extra API calls).
Context window sizes are read from models.yaml → routing[role].context_window first, then fall back to a built-in table for common Ollama models.
When SAGE runs a multi-task plan, it keeps a working memory of which files were written or edited by each completed task. Before the next task's coder agent starts, that history is appended to its system prompt:
CONTEXT — files modified by earlier tasks in this run:
src/auth.py: wrote by T1
src/utils.py: edited by T2, edited by T3
This lets later tasks avoid conflicting edits and understand existing context without re-reading every file. The working memory is held in the workflow state (working_memory key) and is not persisted across separate sage run invocations.
After /commands, the shell prints links from SAGE_REPO_URL (or git remote origin when unset):
export SAGE_REPO_URL=https://github.com/your-org/your-forkSee also INSTALL.md (bootstrap) and README.md (overview).