There are many agentic coding agents, but this one is mine. Built as a Pi extension, this one focuses on simple workflows and often the only things I care about when working are:
- A list of Git changes and the diff
- Running a local development server
- Running tests
That is why I created SAGE — as a Pi extension the goal is simple: get the agent to do your work, see the changes, and verify the tests are passing.
- 3-Panel Dashboard — A real-time TUI dashboard rendered above the status line with three columns:
- Git Status — Polls
git statusat a configurable interval and displays modified, added, deleted, renamed, and untracked files in a color-coded tree view - Dev Task Runner — Runs a long-lived development command (e.g.
deno task dev) and streams its output - Test Runner — Runs a test command in watch mode, parses pass/fail counts from Deno and Jest output
- Git Status — Polls
- Interactive Diff Viewer — Full-screen modal showing a file list alongside color-coded diffs for staged, unstaged, and untracked changes. Vim-style navigation (
j/k,g/G,Page Up/Down) - Keyboard Shortcuts
Ctrl+Shift+Up/Down— Adjust dashboard heightCtrl+Shift+G— Open diff viewer
- Graceful Process Management — SIGTERM with SIGKILL fallback, circular output buffer, live status indicators
- Configuration Wizard —
/sage initwalks you through creating asage.yamlinteractively
Install SAGE as a Pi extension:
npm install sageMake sure git is available on your system — SAGE shells out to it for status and diff information.
- Install the extension
- Run
/sage initto generate asage.yamlin your project root - The dashboard appears automatically on session start
| Command | Description |
|---|---|
/sage init |
Interactive setup wizard — creates sage.yaml |
/sage toggle |
Show or hide the dashboard |
/sage start [task|test] |
Start one or both runners |
/sage stop [task|test] |
Stop one or both runners |
/sage restart [task|test] |
Restart one or both runners |
/sage refresh |
Force a git status refresh |
/sage config |
Print the current configuration as JSON |
/sage diff |
Open the diff viewer |
Create a sage.yaml in your project root (or run /sage init):
# Command to run your local dev server
task:
command: "deno task dev"
cwd: "." # Working directory (optional, relative to project root)
env: # Environment variables (optional)
NODE_ENV: development
# Command to run your tests
test:
command: "deno test --watch"
cwd: "."
env: {}
# Git watcher settings
git:
poll_interval: 3000 # Polling interval in milliseconds (default: 3000)
show_untracked: true # Include untracked files in the status panel (default: true)
# Dashboard layout
layout:
height: 0 # Row height — 0 means auto/half terminal (default: 0)
columns: [25, 37, 38] # Column width percentages for [git, task, test] (default: [25, 37, 38])| Field | Type | Default | Description |
|---|---|---|---|
task.command |
string |
— | Shell command for the dev task runner |
task.cwd |
string |
. |
Working directory for the task command |
task.env |
object |
{} |
Environment variables passed to the task process |
test.command |
string |
— | Shell command for the test runner |
test.cwd |
string |
. |
Working directory for the test command |
test.env |
object |
{} |
Environment variables passed to the test process |
git.poll_interval |
number |
3000 |
How often to poll git status (ms) |
git.show_untracked |
boolean |
true |
Show untracked files in the git panel |
layout.height |
number |
0 |
Dashboard height in rows (0 = half terminal) |
layout.columns |
[n, n, n] |
[25, 37, 38] |
Column width percentages |
Both task and test are optional — if omitted, the corresponding panel shows "no command configured."
extension.ts → Main entry point, event handlers, command registration
src/
├── config.ts → sage.yaml loader and defaults
├── git-watcher.ts → Polls git status, parses porcelain output
├── process-runner.ts → Spawns and manages child processes
├── layout.ts → 3-column bordered dashboard renderer
└── panels/
├── git-panel.ts → Git file tree with status colors
├── task-panel.ts → Dev task output display
├── test-panel.ts → Test output with pass/fail parsing
└── diff-viewer.ts → Full-screen interactive diff modal
MIT