neuron-explorer
Steering-first neuron explorer for Qwen3.5-4B: push every MLP neuron, keep every rollout, browse the results
Multi-tier AI orchestration CLI — built for developers who think in systems.
Developer toolsTypeScript · JavaScriptGitHub @Varun-SVOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Loading the full README. The saved excerpt is shown below.
One prompt → an organization of AI agents that plan, delegate, and execute in parallel.
Auto-routed to the cheapest model that's best at each step. Up to 90% cheaper than running everything on one frontier model.
Cascade is an open-source CLI that runs your prompt through a hierarchical three-tier agent system — T1 plans → T2 manages → T3 executes — auto-routing each step to the best-value model, running tools, and compiling one coherent result. Think Claude Code / Gemini CLI / Copilot CLI, but uniquely built around orchestration.Read the full README ↗One prompt → an organization of AI agents that plan, delegate, and execute in parallel. Auto-routed to the cheapest model that's best at each step. Up to 90% cheaper than running everything on one frontier model.
Cascade runs your prompt through a hierarchical three-tier agent system — T1 plans → T2 manages → T3 executes, sized to the task — auto-routing each step to the best-value model, running tools, and compiling one coherent result. Think Claude Code / Gemini CLI / Copilot CLI, but built around orchestration.
cascade "Refactor the auth module to use JWT, add tests, and open a PR"
| Surface | What it is | Get it |
|---|---|---|
| CLI | Interactive REPL and one-shot runs in your terminal | npm install -g cascade-ai — Quick Start |
| Desktop app | Chat, a live Cockpit of the agent tree, a code editor with a terminal, and a browser the agent can drive | cascadeai.in/download |
| Cascade Cloud | Hosted chat, bring your own keys — files, memory, generated documents, browser control | cascadeai.in |
| Self-host | The Cloud web app on your own machine | docker compose up — Self-host |
| OpenAI-compatible API | POST /v1/chat/completions for any OpenAI SDK | OpenAI-compatible API |
| SDK | runCascade() / createCascade() from Node | SDK |
The CLI, desktop app and Cascade Cloud share one account. Settings can follow you between them through opt-in, end-to-end-encrypted sync: you push and pull by hand, with a passphrase.
Auto and Cascade fuses live public benchmark scores with live pricing to pick the best-value model for each task, then learns from how each model actually did.e14, and acts on them by ref; a model that can see images can also get a screenshot (tools.browserVision)./auto) — hands-off runs: safe tools run silently, dangerous ones still ask, budget caps stay the hard stop./continue) — hit the token budget on a big task? Resume from the partial state instead of redoing it.saved $5.63 — 90% vs. all-T1); no flat-agent tool can show this number.Other AI CLIs run a single agent. Cascade runs a visible organization — and the terminal shows you the org at work:
$0.031 · saved $0.094 — 75% vs. all-T1), because cheap T3 workers (free, when they are local) do the heavy lifting while a premium T1 model only administrates. No flat-agent tool can show this number./comms) — live radio chatter between workers: peer messages, broadcasts, file locks, barrier syncs. No other CLI has agent-to-agent communication at all, let alone on screen./why — every run can explain itself: the complexity verdict and the classifier's reasoning, which model served each tier, failovers, and escalations.planApproval: "always") — Complex runs pause so you can approve T1's proposed org chart and budget ("3 managers · 7 workers · est. $0.40") before anything spawns. You sit above T1.Cascade has shipped roughly 70 releases since v0.13.2 and is now at v0.82.0. Grouped by theme rather than listed one-by-one; CHANGELOG.md has every change.
POST /v1/chat/completions and GET /v1/models, so any OpenAI SDK can call Cascade (v0.70) — and one-command self-hosting with docker compose up (v0.69).ANTHROPIC_AUTH_TOKEN + ANTHROPIC_BASE_URL) and the endpoint that issued it are adopted, synced and sent together, never to another host; Claude subscription tokens are refused everywhere (v0.75).\(…\), \[…\], $…$, bare \begin{align*}) while prices stay prices, and long answers stream without slowing the chat.compileTaskGraph + DependencyScheduler) instead of two separate hand-rolled implementations — pinned by a parity harness across 600 generated graphs so ordering didn't silently change.PARTIAL) result doesn't block; only a hard failure does./continue picks a run back up after a crash or Ctrl-C — finished sections are restored as fact and only the remainder gets re-planned./download/mac-arm64, /download/win-x64) mean a shared link never goes stale..docx/.pptx/.xlsx), not markdown text saved under the wrong extension.cascade login, the desktop app, and the web app all authenticate against one account with no OAuth secret shipped in a native client.gpt-5.5 vs. gpt-5.4-mini) instead of folding into one shared, less accurate score, and models a provider newly makes available compete in ranking instead of waiting on a hand-edited catalog.Auto picks the best-value model per task from live public benchmarks + live pricing), a boardroom plan-review gate (pause to approve or edit T1's plan before anything spawns), and autonomous /auto mode (safe tools run silently, dangerous ones still ask)./continue run resumability, and workers recruiting bounded sibling workers (request_workers) when a task fans out mid-run.saved $X vs. all-T1), the /comms peer-traffic feed, /why run explanations, and the boardroom approval gate.A Complex task runs through all three agent tiers:
User prompt
│
▼
┌─────────────────────────────────────────────┐
│ T1 Administrator │
│ • Analyzes complexity │
│ • Selects models for all tiers │
│ • Decomposes task into n sections │
│ • Compiles final output │
└──────────────┬──────────────────────────────┘
│ dispatches in parallel
┌──────────┼──────────┐
▼ ▼ ▼
┌───────┐ ┌───────┐ ┌───────┐
│ T2 │ │ T2 │ │ T2 │ Managers
│ Sec.1 │ │ Sec.2 │ │ Sec.3 │ • Own one section
└───┬───┘ └───┬───┘ └───┬───┘ • Spawn T3 workers
│ │ │ • Aggregate results
T3s T3s T3s Workers
execute execute execute • Run tools
subtasks subtasks subtasks • Self-test output
• Escalate if needed
Complexity decides how much of the organization a task gets. A classifier (with cheap heuristics first) grades each prompt, and only the tiers the work needs are spun up:
| Complexity | Tiers in play | Shape |
|---|---|---|
| Simple | T3 | One worker answers directly — small talk gets a direct answer with no worker at all |
| Moderate | T2 → T3 | One manager and its workers, no planner |
| Complex | T1 → T2 → T3 | T1 plans 3–5 sections, one T2 manager each |
| Highly Complex | T1 → T2 → T3 | 5+ sections |
/why shows the verdict and the reasoning for the last run.
AbortSignal to stop any run mid-flight; all tiers halt at the next safe checkpoint and emit run:cancelled with partial outputANTHROPIC_BASE_URLprivacy.paths rule forces local-onlyModels are discovered from each provider at startup, so new releases compete in routing without a Cascade update.
run_code interpreter (Python/Node)"codeIndex": { "enabled": true } and cascade index — code_search over a local code indexweb_search and SSRF-guarded web_fetchbrowser_control of a real browser, and in the desktop app read_current_page.docx / .pptx / .xlsx and PDFs, with charts and embedded imagespeer_message between workers, knowledge_graph_search over project facts once the project has learned some, and on Cascade Cloud ask_user for a structured question"enableToolCreation": false. Those always run confined: in a hard V8 isolate when the optional isolated-vm addon is installed, and otherwise in a WebAssembly sandbox that ships with Cascade. Either way the code sees no filesystem, network or processes, only callTool (which asks before anything dangerous) and an SSRF-guarded fetchCASCADE.md — project-level instructions for agents.cascadeignore — files agents' file and search tools cannot read or change#topology, #sessions, #logs, #settings)npm install -g cascade-ai
Requires Node.js ≥ 22.
# 1. Initialize a project
cd my-project
cascade init
# 2. Set API keys (or add to .env)
export ANTHROPIC_API_KEY=sk-ant-...
export OPENAI_API_KEY=sk-...
export GOOGLE_API_KEY=AIza...
# 3. Check everything is working
cascade doctor
# 4. Start the interactive REPL
cascade
# 5. Or run a one-shot prompt
cascade run "explain the auth module in this repo"
Run the Cascade Cloud web app (chat UI + API + socket) yourself, on one port, with no cloud account:
cp .env.example .env
echo "SESSION_SECRET=$(openssl rand -base64 32)" >> .env
echo "CLOUD_DEV_BYPASS=1" >> .env # local-only sign-in; see the warning below
docker compose up # → http://localhost:8787
docker compose up builds the image, serves the web UI straight from the server (no separate web container), and keeps the SQLite database + uploads in a named volume so a restart doesn't wipe them. .env.example documents every variable the server reads (from cloud/server/src/env.ts), grouped required-first, each with what it does and what breaks if it's unset.
CLOUD_DEV_BYPASSis an authentication bypass, not a convenience toggle. It adds a sign-in button that accepts any name with no credential, so anyone who can reach the port can sign in as anyone. That is why it ships commented out, why the step above is explicit rather than the default, and whydocker-compose.ymlpublishes to127.0.0.1only. Before putting this on a network anyone else can reach: setGITHUB_CLIENT_ID/GOOGLE_CLIENT_IDfor real OAuth, removeCLOUD_DEV_BYPASS, and only then change the port binding.
See the Dockerfile and docker-compose.yml for the build/runtime details.
Anything that already talks to OpenAI can talk to Cascade. Point the client's base_url at your server's /v1 and use a Cascade access token as the API key — POST /v1/chat/completions and GET /v1/models work with the official SDKs, streaming and not.
from openai import OpenAI
client = OpenAI(api_key=CASCADE_ACCESS_TOKEN, base_url="http://localhost:8787/v1")
reply = client.chat.completions.create(
model="cascade", # a routing mode, not a model
messages=[{"role": "user", "content": "Compare Postgres and SQLite for a CLI tool."}],
)
print(reply.choices[0].message.content)
print(reply.cascade) # which tier + model actually served it, and what routing saved
model names a routing mode, because Cascade picks a model per subtask — that is the product:
model | what runs |
|---|---|
cascade | full orchestration, balanced quality against cost |
cascade-fast | one mid-tier model, no orchestration |
cascade-quality | full orchestration, biased to quality |
Anything else returns 404 model_not_found rather than quietly running something you didn't ask for. Unsupported parameters (n > 1, logprobs, tools, response_format, …) are rejected, not ignored — a silently dropped parameter returns a response that looks successful and is wrong. temperature and max_tokens are honoured, applied across tiers.
Provider keys. On a single-account instance — a self-host, where the operator and the caller are the same person — the endpoint uses the provider keys in your .env (OPENAI_API_KEY, ANTHROPIC_API_KEY, …; the same names the CLI reads). The moment a second account exists this stops automatically, because the operator's key would otherwise pay for everyone else's runs. Any instance can also take keys per request via the SDK's extra_body={"providers": [...]}.
/v1 is for server-side clients: Authorization is not allowed cross-origin, so a browser-side SDK is deliberately not served. Tools/function calling and image inputs are not in v1 — Cascade's tools run server-side, and attachments go through POST /api/uploads.
Cascade keeps what it knows about a project outside the project, in a folder of its own:
~/.cascade-ai/projects/<folder name>-<hash>/ — its settings (config.json), sessions, audit trail, world state, code index and run checkpoints. Your provider keys are kept once for the machine, in ~/.cascade-ai/credentials.json, and every project uses them; no project's config holds a key. The project itself holds only what is meant to be shared: CASCADE.md and .cascadeignore. These folders are readable by you alone: one open to others that Cascade cannot tighten, such as one owned by another account, is refused. Rename or move a project on the same disk and its state follows it, found by the folder's identity on disk; a copy, or a move to another disk, starts afresh, and Cascade says where the old state is. Delete a project and make or clone another at the same path, and its settings, local-only rules and own keys carry over, while what the earlier one did and knew — sessions, world state, the code index, private outputs — is set aside beside its state folder. A project that still has a .cascade/ folder from an earlier version has it moved there the first time Cascade opens it, keys included (a .cascade that is a symlink is left alone) — a project whose key differed from the machine-wide one keeps using its own. cascade doctor prints where a project's config is.
Prefer the picker over hand-editing config. Inside the REPL, run
/modelto walk through a three-step interactive picker (provider → tier → model, with an Auto option at every step). The picker writes the project's config for you and hot-swaps the running router — no restart needed.
{
"version": "1.0",
"providers": [
{ "type": "anthropic", "apiKey": "sk-ant-..." },
{ "type": "openai", "apiKey": "sk-..." },
{ "type": "gemini", "apiKey": "AIza..." },
{ "type": "ollama" }
],
"models": {
"t3": "llama3.2:3b"
},
"autoBias": "balanced",
"tools": {
"shellAllowlist": [],
"shellBlocklist": ["sudo rm", "rm -rf", "mkfs"],
"requireApprovalFor": ["shell", "file_write", "file_delete"],
"browserEnabled": false,
"browserVision": "list",
"mcpServers": [
{ "name": "filesystem", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "."] }
],
"mcpTrusted": ["filesystem"]
},
"dashboard": {
"host": "127.0.0.1",
"port": 4891,
"auth": true,
"teamMode": "single"
},
"theme": "midnight",
"telemetry": { "enabled": false },
"plugins": ["./plugins/my-tool.js"],
"planApproval": "never",
"altScreen": false
}
The file is strict JSON — no comments.
models pins a tier to a model; a tier left out stays on Auto.tools.mcpTrusted names the MCP servers allowed to start; an untrusted one is refused."codeIndex": { "enabled": true } turns on the code_search tool; build its index with cascade index.autoBias sets Auto's trade-off: "balanced", "quality" or "cost".planApproval: "always" pauses Complex runs in the boardroom: approve T1's proposed sections, worker counts, and estimated cost before any T2 manager spawns. Headless/SDK runs auto-approve.altScreen: true (or the --alt-screen flag) renders the TUI in the terminal's alternate screen buffer — vim-style, flicker-proof, shell restored on exit. History scrolls in-app with PgUp/PgDn since the alt screen has no native scrollback.API keys are also read from environment variables:
| Provider | Environment Variable |
|---|---|
| Anthropic | ANTHROPIC_API_KEY — or a gateway's ANTHROPIC_AUTH_TOKEN with its ANTHROPIC_BASE_URL |
| OpenAI | OPENAI_API_KEY |
| Gemini | GOOGLE_API_KEY (GEMINI_API_KEY via cascade link) |
| Azure | AZURE_OPENAI_KEY, with AZURE_OPENAI_ENDPOINT and AZURE_OPENAI_DEPLOYMENT (AZURE_OPENAI_API_KEY via cascade link azure) |
If you already use Claude Code, OpenAI Codex, Gemini CLI, or GitHub Copilot CLI, Cascade can reuse the credentials they store on your machine instead of asking you to paste keys again:
cascade link # list detected credentials
cascade link anthropic # adopt an API key for a provider
cascade link groq # adopt a compatible service, with its endpoint
cascade doctor also reports what's linkable. How each credential is treated:
| Source | Stored as | Reusable? |
|---|---|---|
ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY env | API key | ✅ directly |
AZURE_OPENAI_KEY env | API key | ⚠️ needs routing — AZURE_OPENAI_ENDPOINT + AZURE_OPENAI_DEPLOYMENT, or deployments already configured |
OPENROUTER_API_KEY, GROQ_API_KEY, DEEPSEEK_API_KEY, XAI_API_KEY, MISTRAL_API_KEY, TOGETHER_API_KEY, FIREWORKS_API_KEY | API key | ✅ directly — adopted together with the service's endpoint |
ANTHROPIC_AUTH_TOKEN env | bearer token | ⚠️ needs the gateway that issued it — ANTHROPIC_BASE_URL, or baseUrl already configured |
Codex ~/.codex/auth.json (API-key mode) | API key | ✅ directly |
Claude Code ~/.claude/.credentials.json | subscription OAuth | ❌ detected only — Anthropic prohibits third-party use |
| Codex ChatGPT login · Gemini CLI · Copilot CLI | vendor OAuth | ❌ detected only — locked to that vendor's backend |
⚠️ Subscription tokens are not adoptable. Anthropic does not permit third-party developers to route requests through Claude Free, Pro or Max credentials, and refuses them server-side; the Codex, Gemini CLI and Copilot tokens each target their own vendor's backend rather than the public API. Cascade detects them so you know what is on the machine and why it cannot use them, and declines to configure a provider that would fail on its first call. It only ever reads your own local files, and never transmits a credential anywhere except to that credential's own provider.
Create a CASCADE.md in your project root to give agents project-specific instructions — just like CLAUDE.md. Run cascade init to generate a template.
List files and directories agents cannot read or modify. Syntax is identical to .gitignore. Secrets (.env, *.pem, *.key) are protected always, whatever the file says, and Cascade's own files are outside the project, where no agent reaches. See Security for what it covers.
Each tier draws from its own class of model: frontier models for T1's planning, mid-size models for T2's management, and small, fast models for T3's work. With Auto (the default), Cascade picks within that class per task, by public benchmark scores for the task type weighed against live pricing (autoBias sets the trade-off), and adjusts from how each model actually performed. cascade stats shows what it has learned, and /rate good | bad teaches it.
"models" in config, /model in the REPL, or cascade models set t1 anthropic:<model>.privacy.paths rule keeps a folder local-only.Images are only processed by vision-capable models. When you attach an image:
# Install Ollama then pull a model
ollama pull llama3.2:3b # T3 workers
ollama pull llava # T3 vision tasks
ollama pull llama3:70b # T2 managers
# Cascade auto-detects Ollama at localhost:11434
cascade doctor # confirms detection
{
"providers": [{
"type": "azure",
"apiKey": "...",
"baseUrl": "https://YOUR_RESOURCE.openai.azure.com",
"deploymentName": "gpt-4o",
"apiVersion": "2024-08-01-preview",
"region": "global"
}]
}
region selects the right price sheet — Azure charges ~10% more for us and
eu deployments than for global ones. Defaults to the global rates.
{
"providers": [{
"type": "openai-compatible",
"apiKey": "...",
"baseUrl": "https://api.groq.com/openai/v1",
"model": "llama-3.1-70b-versatile",
"local": false
}]
}
local)An OpenAI-compatible endpoint is either your own hardware — llama.cpp, LM
Studio, vLLM — where inference genuinely costs nothing, or somebody's paid API.
The same is true of Ollama, which is usually local but can be pointed at a
rented box. local says which:
local | Meaning |
|---|---|
true | Self-hosted. Calls cost $0, and Cascade reports $0. |
false | Hosted. Cascade prices calls from its pricing dataset; a model it can't price reports "cost not tracked", never $0.00. |
| (unset) | Inferred: Ollama is local; an OpenAI-compatible endpoint is local when baseUrl points at localhost or your LAN. |
Set it explicitly whenever the default guesses wrong — a hosted endpoint mistaken for a local one is how real spend gets reported as free.
T3 workers have access to the following tools. All destructive operations require explicit approval unless disabled in config.
| Tool | Description | Dangerous |
|---|---|---|
shell | Execute shell commands (allowlist / blocklist) | ✓ |
run_code | Run Python or Node code | ✓ |
file_read · file_list | Read a file (optional line range); list a directory | |
file_write · file_edit · file_delete | Write, exact-string edit, delete | ✓ |
glob · grep | Find files by pattern; search their contents | |
code_search | Search the workspace code index — needs "codeIndex": { "enabled": true } in config and cascade index | |
git | status, diff, log, add, commit, push, pull, … | ✓ |
github | Open PRs, list and comment on issues (GitHub / GitLab) | ✓ |
web_search | Search the web (SearXNG, Brave or Tavily) | |
web_fetch | Fetch a page, SSRF-guarded | |
browser | Headless Playwright automation (off unless tools.browserEnabled) | ✓ |
browser_control | Drive a real browser — desktop app and web (CDP or Steel). On the web: page views with refs, and screenshots for vision models (tools.browserVision) | ✓ |
read_current_page | Read the page you have open — desktop app | |
image_analyze | Describe an image (vision-capable models) | |
generate_image · generate_speech · generate_video | Generate media, with a provider key that supports it | |
transcribe_audio | Speech-to-text for an audio file | |
generate_document | Render a REAL .docx / .pptx / .xlsx from Markdown or CSV |
On the web (a CDP browser or Steel), browser_control describes each page as a page view: the controls on screen and further down, each under a ref.
[Page view 2]
Page: Dine — https://dine.example/search
Viewport 1280×800, scrolled 0 of 1,013
On screen:
[e5] button "Account"
[e8] combobox "Party size": "2 people" (options "1 person", "2 people", "4 people")
[e14] button "Reserve 7:30 pm"
The model acts by ref ({"action":"click","ref":"e14"}), and CSS selectors still work. On a ref, select_option chooses an option by its text as the view lists it, never by the value hidden in the page; text the view shortened still picks the option it came from. A page view never shows what is typed into a field, nor that text in the page's title or address, a search query included; the results a page lists for a search are its own text and stay visible. A ref is refused, never re-matched, once the page has loaded something else or the control it named has gone or been renamed, even past the part of its name the view shows. A ref inside an iframe is refused once a frame on the page has loaded another document.
tools.browserVision sets how much it sees. It applies to a remote browser — Cascade Cloud and self-hosted deployments set it with REMOTE_BROWSER_VISION, and an SDK host that attaches one reads it from its config. The desktop's built-in browser keeps CSS selectors. Page views need Playwright 1.60 or later, the version Cascade installs; with an older one the agent is offered the original actions only, and reads page text and uses CSS selectors.
| Setting | What the model gets |
|---|---|
off | Page text and CSS selectors only |
list (default) | Page views with refs, for every model |
image | Page views, plus a screenshot for models that can see images |
marked | Page views, plus a screenshot with each ref drawn on it (experimental) |
When screenshots are on:
Approval prompts name the element and the site. A click on something labelled pay, buy, order, delete, remove, send, transfer, publish, confirm, approve, authorize, allow, withdraw, subscribe or donate asks every time, even after "always allow" — read past accents, invisible characters and lookalike letters. So does Enter or Space where it may submit a form, alone or in a key combination, and a click, fill or key press on something the page view did not name, such as a CSS selector or an icon-only button, or named only in part because its name was too long to show or had typed text hidden in it. An approved action runs only on the page it was approved on, not after the page has moved to another, even on the same site; one by CSS selector also stops when an app changes its route. Hosted deployments set REMOTE_BROWSER_VISION. scripts/browser-vision-eval/ holds the side-by-side test that decides the default.
MCP servers' tools, plugins and dynamic tools join this list at runtime.
generate_document, notfile_write, is how a Word/PowerPoint/Excel file gets made: those formats are ZIP archives of OOXML, so text saved under the extension opens as a corrupted file. It embeds generated images (on its own line) and turns a fenced```chart:barblock (body: CSV) into a real, editable PowerPoint chart — see docs/file-generation.md.
"tools": {
"shellAllowlist": ["npm", "git", "python"], // only these prefixes allowed
"shellBlocklist": ["sudo", "curl http://"] // always blocked
}
cascade [options] Start the interactive REPL
cascade run <prompt> Run a single prompt and exit
cascade init [path] Initialize Cascade in a directory
cascade doctor Diagnose API keys, Ollama, config
cascade link [provider] Reuse credentials from Claude Code / Codex / Gemini / Copilot
cascade models [action] [tier] [v] List models per tier, or set/unset a tier's model
cascade stats Auto-routing history: which models work best per task type
cascade index [path] Build or refresh the code index (code_search also needs codeIndex.enabled)
cascade export Export a session to Markdown or JSON
cascade identity list|create|set-default Manage identities
cascade mcp connect <url>|list|remove Connect remote MCP servers over OAuth
cascade dashboard Launch the local web dashboard
cascade telemetry [on|off|status] Anonymous usage telemetry (off by default)
cascade update Update to the latest version
Cascade Cloud account — the same account the desktop and web apps use:
cascade login | logout | whoami Sign in to Cascade Cloud on this machine
cascade sync push | pull Encrypt and upload / download your settings, with a passphrase
cascade sessions List your cloud chats
cascade sessions show <id> Print a chat transcript with branch markers
cascade sessions branch <chat> <message> Switch a chat to another branch
cascade sessions rename <chat> <title> Rename a chat
cascade sessions rm <chat> <message> Delete a message and its subtree
cascade sessions delete <chat> Delete a chat
Options:
-p, --prompt <text> Single prompt (non-interactive mode)
-t, --theme <name> Color theme (see Themes)
-w, --workspace <path> Workspace path (default: cwd)
-i, --identity <name> Identity to run as
-v, --version Show version
--alt-screen Vim-style alternate screen (flicker-proof; PgUp/PgDn history)
--no-color Disable colors
Type any of these inside the REPL:
| Command | Description |
|---|---|
| Session | |
/help · /exit · /clear | Commands, exit, clear the conversation |
/sessions · /resume <id> · /search | List, resume and search past sessions |
/branch | Fork the session into parallel branches |
/compact | Summarize and compress context now |
/export [markdown|json] · /copy [n] | Export the session; copy the last (or nth-last) response |
/retry | Retry the last prompt |
/rollback | Undo all file changes made in this session |
| Running work | |
/plan <prompt> | Preview the plan without running it |
/replan [guidance] | One corrective re-plan pass on the last task |
/steer <correction> | Steer the workers of a running task |
/auto [on|off|status] | Autonomous mode: safe tools run silently, dangerous ones still ask |
/continue [tokens] | Resume the last task that hit its token budget, with a raised one (a /budget session cap must be raised or cleared first) |
/budget [set <$> | clear] | Session budget cap |
| Seeing inside | |
/status · /tree | Live agent tree; execution timeline panel |
/comms | Live agent-to-agent comms feed |
/why | How the last run was routed: complexity, models, failovers |
/cost | Session cost, tokens and delegation savings |
/logs · /diagnose | Recent runtime logs; a summary of configured providers, models and sessions (it does not test keys or connections) |
Selection & copy: mouse capture stays off, so native drag-select and right-click copy work in your terminal. When idle, the screen never repaints under you;
/copycovers the one case selection can't — grabbing text while output is still streaming (with an OSC 52 fallback that works over SSH).
Switch with /theme <name> in the REPL or set "theme" in config.
| Theme | Style | Former name |
|---|---|---|
midnight | Default — azure → sky → teal, matching T1 → T2 → T3 | cascade |
aurora | Dark | dark |
daybreak | Light | light |
bloom | Dracula-like | dracula |
tide | Nord-like | nord |
ember | Solarized-like | solarized |
The former names still work.
cascade dashboard
# → http://localhost:4891
Set CASCADE_DASHBOARD_PASSWORD (or CASCADE_DASHBOARD_PASSWORD_HASH) first: there is no default password, and with auth on and none set, sign-in is refused. The dashboard binds to 127.0.0.1 unless you change dashboard.host.
Features:
"single" (shared workspace) or "multi" (per-user isolation)Custom port:
cascade dashboard --port 8080
import { runCascade, createCascade, streamCascade } from 'cascade-ai';
// Simple run
const result = await runCascade('Write a Fibonacci function in TypeScript');
console.log(result.output);
// Streaming
await streamCascade('Explain this codebase', (token) => process.stdout.write(token));
// Full control
const cascade = createCascade({
providers: [{ type: 'anthropic', apiKey: process.env.ANTHROPIC_API_KEY }],
theme: 'dark',
});
await cascade.init();
const result = await cascade.run({
prompt: 'Refactor the auth module',
workspacePath: '/my/project',
approvalCallback: async (req) => {
console.log(`Allow ${req.toolName}?`);
return true;
},
streamCallback: (chunk) => process.stdout.write(chunk.text),
});
Pass an AbortSignal to stop a run mid-execution. All active tiers (T1 → T2 → T3) halt at the next safe checkpoint, preventing further token spend. The run() call resolves with whatever partial output has been produced so far.
import { createCascade, CascadeCancelledError } from 'cascade-ai';
const cascade = createCascade({ /* config */ });
await cascade.init();
const controller = new AbortController();
// Listen for the cancellation event
cascade.on('run:cancelled', ({ taskId, reason, partialOutput }) => {
console.log(`Task ${taskId} cancelled: ${reason}`);
console.log('Partial output so far:', partialOutput);
});
// Start the run (non-blocking)
const runPromise = cascade.run({
prompt: 'Perform a deep codebase audit',
signal: controller.signal,
});
// Cancel after 10 seconds (e.g. user pressed Ctrl-C)
setTimeout(() => controller.abort('User requested stop'), 10_000);
const result = await runPromise; // resolves gracefully, not rejected
How it propagates: The signal is threaded through T1Administrator → T2Manager → T3Worker. Each tier checks for cancellation before every LLM call so the run stops as soon as the current in-flight request completes — no mid-stream interruptions.
Cascade supports the Model Context Protocol. Connect any MCP server and its tools become available to T3 workers automatically.
cascade mcp connect https://mcp.example.com/sse # remote server, OAuth login in your browser
cascade mcp list
cascade mcp remove <name>
Local (stdio) servers go in config, under tools.mcpServers — see Configuration. List each one's name in tools.mcpTrusted too: a server that is not trusted is refused before it starts. cascade mcp connect trusts the servers it adds. Or connect one programmatically:
import { McpClient } from 'cascade-ai';
const mcp = new McpClient();
await mcp.connect({
name: 'filesystem',
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-filesystem', '/tmp'],
});
Not active yet. The
hooksconfig below is validated, and the runner is exported from the SDK asHooksRunner, but runs do not call it yet — so these scripts do not fire today. Wiring it in is on the Roadmap.
Run shell scripts before or after tool use. Defined in the project's config:
"hooks": {
"preToolUse": [
{
"command": "echo 'Tool: $CASCADE_TOOL' >> tool-calls.log",
"tools": ["shell", "file_write"]
}
],
"postToolUse": [
{
"command": "npm run lint --silent || true",
"tools": ["file_write", "file_edit"],
"timeout": 15000
}
],
"postTask": [
{ "command": "git add -A && git status" }
]
}
Once wired in, preTask will run before a task starts and postTask after it, and HooksRunner sets CASCADE_TOOL, CASCADE_INPUT, CASCADE_OUTPUT (and CASCADE_PROMPT for preTask) in the hook's environment.
Cascade stores session history, identities, and audit logs in the project's memory.db (SQLite), in its folder under ~/.cascade-ai/projects/.
Create multiple named identities with different system prompts and default models:
cascade identity create reviewer -s "You are strict about best practices."
cascade identity list
cascade identity set-default reviewer
cascade -i reviewer # run as one identity for this session
/export markdown → session-2026-04-02.md
/export json → session-2026-04-02.json
Provider keys you add — through cascade link, the /model picker, desktop Settings or cascade sync pull — are written as plain JSON to one file, ~/.cascade-ai/credentials.json, readable only by your user (mode 0600), so a key entered once works in every project. A project's own config holds no key. A project that had its own key, different from the machine-wide one, when keys moved here keeps it — in the same file, under that project — and goes on using it.
Keys in your environment (ANTHROPIC_API_KEY, …) are read at startup; cascade link is what copies one into these files. Settings you choose to sync through your Cascade account are end-to-end encrypted, so the server holds only ciphertext.
Cascade also has an encrypted keystore — the OS keychain (macOS Keychain, Windows Credential Vault, libsecret), or ~/.cascade-ai/keystore.enc under AES-256-GCM with a PBKDF2-derived key — but it is not wired in: runs neither write provider keys to it nor read them from it. Moving keys there is on the Roadmap.
web_fetch, dynamic tools and hosted search backends cannot reach private or link-local addresses, checked again at connect time.privacy.paths keeps sensitive folders on private models: ones whose endpoint is on this machine or your private network, whatever their pricing says. That is read from the address — loopback, a private range, a .local name; a provider reached by a bare name like http://ollama:11434 is declared with "privateNetwork": true. A worker whose assignment names a matching path — in its files, its description or the acceptance criteria it is graded against — runs on one from the start. One that reads a matching file on the way — with file_read, file_edit, image_analyze, or a grep of that file — moves to one at that moment, before what it read reaches any model, or is refused the read when no private model is configured; one that changes or deletes a matching file — file_write, file_delete, pdf_create, generate_document — does the same first. A grep across folders leaves local-only files out for a worker that is not local-only already, rather than let whether they matched say anything, and file_list and glob leave out their names — a name can carry what a local-only worker read. A file the assignment names is judged by what it is, so an artifact that links to a local-only file counts, and one that is protected is not read to check it. Either way its output is withheld from the tiers above, its approval requests go to you rather than to the T2 and T1 models — an "always" one of them gave earlier does not answer them — and nothing it knows leaves the machine through Cascade's tools: it cannot message its peers or ask for more workers, the tools that send their arguments elsewhere are refused to it — web and browser, GitHub, media generation and transcription, code_search, MCP, plugins, and any tool an embedder registers that does not declare localOnlySafe — and a tool the agent wrote cannot fetch once it has read such a file. Its output, tool results and streamed text stay out of the status and tool events the dashboard and audit log receive, and a tool name its model made up shows there as a placeholder. Local-only files are never put in the code index or shown to its reranker, nor copied into a document that is not itself local-only. What a local-only worker makes goes to its , outside the project ( to the file tools, to its commands), where a name it chose — which could carry what it read — shows to no one else; only a local-only worker reaches that folder. A new file in a folder a local-only pattern covers whole stays there, since that folder's names are hidden with it. A file it changes stays where it is and becomes local-only, for later runs too, even if the pattern it fell under is removed (recorded in the project's folder, shared by every run in it; a write that fails leaves no record); siblings waiting on it are told it finished, not what it said, and nothing it said goes into the knowledge graph. , and run in the process jail below, which hides local-only paths from a worker that is not local-only, and cuts the network for one that is.Agent-written tools always run confined — in the
isolated-vmisolate where the addon is installed, and otherwise in a WebAssembly sandbox (QuickJS) that every install has, the desktop app included. It runs on a thread of its own, capped in memory and terminated at its deadline, and its code reaches the machine only throughcallToolandfetch. There is no unconfined fallback: if the sandbox cannot start, the tool does not run.
Always protected, whatever .cascadeignore says — a ! line cannot undo these:
.env, .env.**.pem, *.key, id_rsa, id_ed25519codeIndex.dbPath puts it in the project.cascade/, where an earlier version kept themCascade's own files — settings, sessions, the audit trail, world state, the code index, run checkpoints — are outside the project, where no file tool reaches and no command sees them.
The file and the built-ins apply to every file, search and listing tool (file_*, grep, glob, image_analyze, …), to the code index and code_search, and to paths reached through a symlink or a hard link. The process jail hides the built-ins from shell, run_code and git too, but not .cascadeignore's own entries: that list commonly names node_modules/ and dist/, which builds and tests have to read.
Agents may read .cascadeignore but not change or remove it: the file tools refuse, and commands see it read-only — the file it links to, or another name for it, too — and it is put back as it was if one changes it anyway. Cascade reads it when a run starts, so a line taken out would unprotect a path from the next run on. Edit it yourself.
Any tool marked as dangerous requires explicit y / n before execution. Configure which tools require approval in the project's config, tools.requireApprovalFor.
"tools": {
"shellAllowlist": ["npm", "git", "python3"],
"shellBlocklist": ["sudo", "curl", "wget", "nc"]
}
Bash — add to ~/.bashrc:
source /usr/local/lib/node_modules/cascade-ai/completions/cascade.bash
Zsh — add to ~/.zshrc:
fpath=(/usr/local/lib/node_modules/cascade-ai/completions $fpath)
autoload -Uz compinit && compinit
Fish:
cp /usr/local/lib/node_modules/cascade-ai/completions/cascade.fish \
~/.config/fish/completions/
src/ The engine — published to npm as `cascade-ai`
├── core/
│ ├── tiers/ T1Administrator, T2Manager, T3Worker
│ ├── orchestration/ Typed task graph, dependency scheduler, durable resume
│ ├── router/ Auto-routing: benchmarks, pricing, learned outcomes, failover
│ ├── verification/ Acceptance checks — mechanical first, a model only when needed
│ ├── knowledge/ Project knowledge graph (world state) and session memory
│ ├── privacy/ Per-path privacy tiers
│ ├── audit/ Secret redaction and the hash-chained audit log
│ ├── permissions/ Escalation T3 → T2 → T1 → you
│ ├── steering/ peer/ Live steering; worker-to-worker messages
│ ├── documents/ Shared Office/PDF renderers (also used by the web app)
│ ├── markdown/ Shared chat Markdown steps (maths, streaming pace)
│ └── cascade.ts Main Cascade class (EventEmitter facade)
├── providers/ Anthropic, OpenAI, Gemini, Azure, Ollama, OpenAI-compatible
├── tools/ Shell, code, files, search, git, web, browser, media, documents
├── browser/ Browser leases and remote (CDP / Steel) sessions
├── retrieval/ Code index and retrieval behind code_search
├── cli/ Ink REPL, slash commands, themes, commands
├── cloud/ Cloud client and end-to-end-encrypted key sync
├── config/ Config schema, keystore, credential discovery and linking
├── memory/ SQLite store (sessions, identities, audit, scheduler)
├── dashboard/ Local dashboard server (Express, JWT, Socket.io)
├── audit/ hooks/ mcp/ scheduler/ notifications/ telemetry/
├── sdk/ runCascade(), createCascade(), streamCascade()
└── index.ts Package exports
app/ Desktop app (Electron + React): chat, Cockpit, code editor, browser
cloud/
├── server/ Cascade Cloud API, auth, billing, OpenAI-compatible /v1, docs
└── web/ Cascade Cloud chat UI (React + Vite)
web/ Local dashboard SPA (ReactFlow agent graph)
Shipped
| Status | Feature |
|---|---|
| ✓ | T1/T2/T3 hierarchical orchestration, sized to the task |
| ✓ | 6 AI providers + Ollama |
| ✓ | Provider failover with automatic recovery |
| ✓ | Streaming REPL (ink) |
| ✓ | Live agent tree visualization |
| ✓ | Web dashboard + WebSocket |
| ✓ | MCP client, with OAuth for remote servers (cascade mcp connect) |
| ✓ | Scheduled tasks (run by the dashboard server) |
| ✓ | SDK |
| ✓ | Plugin loading from config |
| ✓ | Auto model specialization discovery |
| ✓ | T3 text-tool fallback (Ollama support) |
| ✓ | Peer communication visualization in dashboard |
| ✓ | Conversational fast-path (bypass T1 for simple prompts) |
| ✓ | Redaction layer — secrets/PII stripped from T3 output before it travels upstream |
| ✓ | Per-path privacy tiers (privacy.paths — local models only, output withheld upstream — for work whose assignment names a sensitive path, and from the moment a worker reads one) |
| ✓ | Hash-chained audit log (encrypted entries; /audit, GET /api/audit/verify check the chain) |
| ✓ | Independent T2-critic reflection loop (reflection.enabled) |
| ✓ | Live steering — /steer / desktop Steer bar injects corrections into running workers |
| ✓ | Session rollback button (desktop) + /rollback (CLI) |
| ✓ | Cost-per-feature attribution (costByFeature in results, CLI cost panel, desktop chat) |
| ✓ | Project world state (encrypted local log feeding T1 planning) |
| ✓ | Project knowledge graph (world-state v2) — queryable facts T1 plans from; knowledge_graph_search (v0.14) |
| ✓ | Hard sandbox for agent-written tools — a V8 isolate via the optional isolated-vm addon (v0.14), and a WebAssembly sandbox on every install, so they never run unconfined |
Next
| Status | Feature |
|---|---|
| 🔜 | Hooks — the config and HooksRunner exist; runs do not call them yet |
| 🔜 | Provider keys in the encrypted keystore — it exists but runs do not use it; keys are written as plain JSON |
| 🔜 | A tamper-evident audit log — a keyed or externally anchored chain head, so a truncated or rewritten log fails verification |
| 🔜 | Task-completion notifications and webhooks (Slack / Discord / custom URL) — a NotificationManager exists but nothing sends through it |
| 🔜 | The process jail on Windows, and a Docker fallback where no jailer works — see docs/ROADMAP.md |
| 🔜 | Cross-session history research — a prior-work brief before T1 plans — see docs/ROADMAP.md |
| 🔜 | VSCode extension (cascade-vscode) — see docs/ROADMAP.md |
| 🔜 | JetBrains extension (cascade-jetbrains) — see docs/ROADMAP.md |
| 🔜 | Multi-plan branching (T1 proposes N plans) — see docs/ROADMAP.md |
| 🔜 | Plugin marketplace (plugins load from a config list today) |
| 🔜 | Voice input in chat (audio files can already be transcribed with transcribe_audio) |
| 🔜 | Multi-workspace support (the desktop switches its one workspace live today) |
| 🔜 | Smaller follow-ups: steering history in the transcript, custom redaction patterns, a per-run privacy report — see docs/ROADMAP.md |
| Tool | Required Version |
|---|---|
| Node.js | ≥ 22.x |
| npm | ≥ 10.x |
git clone https://github.com/Varun-SV/Cascade-AI.git
cd Cascade-AI
npm install # CLI dependencies (uses the committed package-lock.json)
npm --prefix web install # web dashboard dependencies (needed by `npm run build`)
npm run build
v0.5.7 moved from Ink 5 / React 18 to Ink 6.8 / React 19 and raised the
Node.js floor to 20. The repo now commits package-lock.json, so after a
pull a plain npm install upgrades even a stale node_modules in place —
then rebuild with npm run build so dist/ matches the source (the CLI warns
on startup when it detects a stale build).
If git pull refuses because your old untracked package-lock.json would be
overwritten, or npm install still reports ERESOLVE (this happens on
checkouts that predate the committed lockfile — npm keeps the installed
react@18 in place while ink@6 needs react>=19), do a clean install:
rm -rf node_modules web/node_modules package-lock.json web/package-lock.json
git pull
npm install
npm --prefix web install
npm run build
npm run dev # watch mode for the CLI
npm run build # build CLI + web dashboard
npm run dev:web # hot-reload dashboard at web/
npm run dev:app # desktop app (Electron) in dev mode
npm run build:app # build the desktop app
npm run dev:cloud # Cascade Cloud server
npm run dev:cloud-web # Cascade Cloud web UI
npm test # vitest (engine, desktop logic)
npm test -w cascade-cloud-web # Cloud web UI tests
npm run lint # tsc --noEmit, including the desktop app
Permission escalation. When a T3 Worker needs to execute a dangerous tool the
request travels T3 → PermissionEscalator → T2 → T1 → User. Read-only tools are
auto-approved by rule; dangerous ones use a max-10-token LLM inference at each
tier. Session-wide approvals are cached by ${t2Id}:${toolName}.
Adding a tool. Create src/tools/my-tool.ts extending BaseTool; implement
getDefinition(), execute(), and optionally isDangerous(); register in
src/tools/registry.ts → registerDefaults(); if approval is required, add the
tool name to DEFAULT_APPROVAL_REQUIRED in src/constants.ts.
Adding a plugin. Use the ToolPlugin interface from
src/tools/registry.ts to bundle one or more tools.
*.test.ts alongside the source file they test.fs, network) with vi.mock(); don't mock internal logic.async/await, not .then() chains.withRetry() from
src/utils/retry.ts.CascadeToolError so they carry a .userMessage.npm test passesnpm run build succeeds.cascadeignore patterns respected for file toolsCascade AI is released under the MIT License. Copyright © 2026 Varun SV.
| ✓ |
pdf_create | Render a PDF | ✓ |
knowledge_graph_search | Query the project's knowledge graph of facts — appears once the project has learned some |
peer_message | Message a sibling worker |
ask_user | Ask you one structured question instead of guessing — Cascade Cloud and self-hosted web |
/audit | Check the audit log's hash chain |
| Models and setup |
/model | Pick a provider and model for a tier (or Auto) |
/model-info · /models · /providers | Active models per tier; available models; configured providers |
/rate good|bad | Rate the last task, to improve Auto-routing |
/config · /mcp · /identity · /theme <name> | Configuration summary, MCP servers, identity, theme |
@private/…$CASCADE_PRIVATE_DIRshellrun_codegitshell, run_code and git run in bubblewrap on Linux wherever it works. macOS sandbox-exec is not accepted as a containment boundary. Cascade's own folder, the built-in secrets, ~/.cascade-ai, the usual credential locations in your home folder (~/.ssh, ~/.aws, ~/.config/gcloud, ~/.kube, ~/.docker/config.json, ~/.netrc, ~/.npmrc and the like — the git tool keeps what it pushes and pulls with) and — for a worker that is not local-only — local-only paths are hidden from them, and so is the repository's git store while its history holds any of those files, or while git keeps anything no branch reaches — a deleted branch, an amended commit, a file staged and then unstaged — until it prunes it (the git tool keeps working, leaves them out of its diffs and of what it stages or stashes, refuses a push that would send one — asking the destination through its own jailed git, since reaching a remote can run a program — and there runs none of your global git or ssh configuration, which a command could rewrite); a repository nested in the workspace, or a submodule, is checked and hidden the same way, and read-only to a local-only worker's commands; the git tool never runs hooks, and git's configuration files — a nested repository's, and every file one includes — are read-only to commands, so none can name a program for it to run with your credentials; tool calls wait while a command runs, and check their path again once their turn comes, so none can swap a checked path for a symlink before a tool opens it; a hard link to a hidden file is hidden too; each command gets its own process namespace, so Cascade's environment is not there to read; a symlink whose name is hidden hides what it leads to; and a local-only worker's commands have no network, cannot reach host services through Unix sockets, and write only into the workspace and its private folder — with a private /tmp, the git store and hard-linked files read-only, and every other tool call in the workspace, from any run or process, waiting until they end, when what they made is moved to the private folder, what they changed or deleted is marked local-only, and the folders they did not make get their mode and times back (they cannot set extended attributes at all) (a deletion by file_delete too, so the rest sees the path as local-only rather than missing). If that mark cannot be saved, what they changed or made is moved to the private folder rather than left where another process could read it. On macOS shell and code commands are refused: sandbox-exec cannot contain surviving children or isolate the parent process environment. Every command's environment has provider keys and credential-file hints taken out. Files named by standard credential variables, including GOOGLE_APPLICATION_CREDENTIALS, AWS_SHARED_CREDENTIALS_FILE and each KUBECONFIG entry, are hidden too, including hard-link aliases; Git retains its credential access. Without a supported jailer — Windows, macOS, or a Linux where bubblewrap is missing or cannot create user namespaces — shell and run_code are refused, since nothing would keep them from reading a protected file and handing it to a cloud model; the git tool, which checks its own operations, runs with the keys taken out and no configuration that can start a program: no global or system git configuration (the plain settings in it, such as line endings and your name, are passed on, and a filter it defines is marked required, so a file that needs one is not added unfiltered); a repository whose own configuration names a program — a diff or merge driver, a filter, a credential helper, an ssh command — is refused, with the setting named; and a commit your configuration would sign is not made. Pushing over HTTPS then has no credential helper, and ssh reads no ~/.ssh/config. Agents' file tools cannot change anything in a .git folder, under any name. Set tools.processJail to bwrap to require bubblewrap; the retained sandbox-exec setting refuses commands. Set it to off to explicitly run commands with neither jail nor scrubbing./audit checks the chain. That catches an edited or removed entry in the middle, but not a removed tail, a chain recomputed by someone with write access, or a deleted database: the chain has no key and no anchor outside the log./continue resumes it with a raised one. A session spending cap set with /budget set stops runs too; /continue does not lift it, so raise it or /budget clear first.| ✓ | .cascadeignore enforced for every file and search tool and the code index; Cascade's own files and your keys kept outside the project |
| ✓ | Process jail for shell, run_code and git — bubblewrap on Linux; arbitrary commands fail closed on macOS and Windows — on top of approvals |
| ✓ | Cascade Cloud (hosted chat — GitHub/Google login, bring-your-own-key, cascadeai.in) |
| ✓ | Cascade Cloud billing — Razorpay subscriptions, Free and Pro plans |
| ✓ | Desktop app — chat, Cockpit, code editor + terminal, browser; downloads from the site |
| ✓ | End-to-end-encrypted settings sync across CLI, desktop and web — manual push and pull, with a passphrase |
| ✓ | Typed task graph with durable resume after a crash, cancel or budget cap (v0.68) |
| ✓ | Self-host with docker compose up (v0.69) |
| ✓ | OpenAI-compatible API — /v1/chat/completions, /v1/models (v0.70) |
| ✓ | Browser control in the desktop app and on the web — live view, take over and hand back (v0.78 – v0.81) |
| ✓ | Ask-before-guessing on Cascade Cloud — one structured question instead of an invented answer (v0.81) |
| ✓ | Code index and code_search — opt-in: codeIndex.enabled, then cascade index |
| ✓ | Media generation (image, speech, video) and audio transcription |