Escape AI Code Assistant
AI coding assistant extension for VS Code and VS Code-compatible editors (e.g.
Cursor): a chat sidebar with four composer modes (Ask / Plan / Agent / Edit)
plus a dedicated AI Code Review flow, diff-preview-gated file edits, real
terminal command execution, streaming inline completions, and RAG-backed
workspace context.
The primary surface is the Escape AI view in the sidebar
(escapeAI.chatView), with a composer offering four modes:
- Ask — a normal streamed chat reply, with optional
@file mentions and
drag-and-drop/pasted attachments as extra context.
- Plan — generates a structured, numbered multi-step plan
(
POST /chat/plan) and shows an inline "Plan Ready" card in the chat
thread — step/file count, an "open plan file" link, and the real
Run this plan / Deny buttons. A read-only Plan File tab
auto-opens alongside it for reference (numbered steps, file paths — no
controls of its own); to revise a plan, just type a new message while
still in Plan mode.
- Agent — a real, agentic tool-calling loop (see below): the model reads
and edits files and runs commands live, deciding what it needs as it goes,
the same way Claude Code's own VS Code extension explores a workspace.
- Edit — nudges the model toward proposing concrete code edits for the
current context (currently a prompt hint, not a distinct execution path).
Auto-detected mode
By default (escapeAI.autoDetectMode, on), the mode chip is picked
automatically from each message's own text via a keyword heuristic
(src/state/detectComposerMode.ts) — no extra AI call, and no silent
behavior change: the detected mode always shows as a small badge above
the sent message, and the existing mode chips still let you override it
exactly like a manual pick. Detection is deliberately conservative about
ever landing on Agent mode — a real autonomous tool-calling loop that can
edit files and run terminal commands (permission-gated, but still real
actions) — only clear end-to-end/build-it-for-me language routes there; a
plain question always stays in Ask. Turn the setting off to always use
whichever mode chip is currently selected, with no auto-switching.
Every file edit — from Ask/Edit-mode replies, /refactor, /fix,
generateFromComment, Plan-mode step execution, or Agent's edit_file tool
— goes through the same diff-preview flow: nothing is ever written silently.
A change is proposed as a real VS Code diff view, gated behind an in-chat
"Escape AI wants to edit a file" card (Allow / Always allow (this session) /
Deny / type instructions instead), and only saved to disk once accepted.
Real terminal command execution works the same way: a command is shown in a
terminal-styled card (with a copy button, not an internal scrollbar — the
full command/output is always shown) and gated behind an
Allow / Always allow / Deny card before it runs.
Model + Effort picker
A single chip in the composer's toolbar row (e.g. ✦ gpt-5.4-mini · Medium ▾) opens one merged dropdown — a Model section (Auto / a real
OpenAI model / openai/gpt-oss-120b) and an Effort section
(Low/Medium/High), matching Claude Code's own model-picker pattern
rather than two separate chips. Rows show only the real model name
that will actually run — no provider name ("OpenAI"/"Groq") appears
anywhere in the picker, not even as a sub-line. Gemini is hidden entirely
— not currently in active use, though still fully supported server-side.
The Effort picker primarily maps to real generation knobs —
max_tokens/temperature — rather than a fabricated "reasoning effort"
parameter, since none of the wired providers expose one at the API
surface this backend calls (backend/api/app/services/ai.py). One
exception: when the provider is set to OpenAI, effort also selects
between three real OpenAI models — Low requests gpt-4o-mini
(faster/cheaper), Medium requests gpt-5.4-mini
(ai_providers.OPENAI_PAID_CHAT_MODEL), High requests gpt-4.1
(ai_providers.GPT_41_MODEL — the same stronger model Code Review
already uses at its own High tier) — since the backend already accepts a
client-supplied model override (chat.py). This choice is driven
purely by effort, not plan — picking OpenAI explicitly is not currently
capped by the user's plan the way "Auto" is (Free-plan chat on Auto is
actually routed to Groq server-side by default; see chat.py). Groq has
no client-selectable tiering today, so it keeps its plan-based default
regardless of effort. Ask/Edit mode only — Agent mode forces OpenAI
server-side already (see below), and Plan mode's per-step
execution doesn't thread a model/effort override at all.
Code Review (see below) reuses this same Effort setting as its own model
selector, rather than adding a second model picker.
Agent mode uses the backend's OpenAI-format tool-calling support
(POST /chat/send with a tools array, tool_call SSE events,
POST /chat/tool-result to continue the exchange). The model can call:
| Tool |
Gated? |
Notes |
read_file |
No (read-only) |
optional line range |
git_status |
No (read-only) |
git status --porcelain |
git_diff |
No (read-only) |
optional file path / staged flag |
edit_file |
Yes |
full-file replace through the same diff-preview flow as everything else |
run_terminal_command |
Yes |
child_process.exec in the workspace root, 60s timeout |
Real constraint, not a client limitation: using tools forces the backend
to route to OpenAI regardless of the composer's model picker — Groq's
tool-calling isn't wired up server-side (same is true of Gemini, hidden
from the picker but still supported for plain chat). Agent mode silently ignores a
non-OpenAI provider selection while active.
Code Review mode
Opened via the Review chip in the composer's toolbar row (next to
Attach) — not one of the Ask/Plan/Agent/Edit mode chips, since it opens
its own dedicated setup/progress/results UI rather than a normal chat
turn. Pick a review target (Current File / Git Changes [default, real git diff] / Selected Code / Workspace) and focus areas (Bugs/Security/
Performance/Code Quality/Best Practices), then Start Code Review.
- Reuses the exact same OpenAI provider call every other mode uses — no
second AI integration, no second model picker.
- Findings are structured (severity/category/file/line range/suggested
fix) and become real VS Code diagnostics — Problems panel entries and
editor squiggles, with native click-to-navigate.
- Explain routes through the existing chat/Ask infrastructure as a
standalone exchange (not injected into your main chat thread).
- Fix generates a proposed replacement, then goes through the exact
same diff-preview-and-approve flow every other edit-producing command
in this extension uses — nothing is ever written without you clicking
Accept on a real diff.
- Best-effort secret redaction strips likely
.env/API-key/token content
out of anything sent to the AI provider before the request is made; the
review prompt also explicitly instructs the model to treat reviewed
code as untrusted data, never as instructions to follow.
- "Workspace" never sends the whole repo — it reviews real git changes
when available, otherwise falls back to a capped (200-file) file
listing rather than file contents.
Other features
- Streaming inline ghost-text completions
- Code actions on selection: explain, refactor, fix
- Generate code from a natural-language comment
- Real-time workspace RAG indexing on file save, plus a bounded (500-file)
full-workspace index on activation so a freshly opened project has some
context immediately, not just files you've since saved
- Escape AI: Reindex Workspace command (also in the panel's "⋯" menu) —
re-runs that same 500-file startup pass on demand, for when the automatic
on-save indexing missed something or you've just pulled a large branch,
without needing to reload the whole window
- Status bar indexing status (pending/indexed/running, with a real
file-count denominator once available)
- Google OAuth sign-in (browser loopback flow) or a manual API key, via the
sign-in panel — no more plaintext
authToken setting (see Auth below)
- MCP server manager (connect/list-tools/disconnect against a real local MCP
server), usage meter, client-side action-log task history (Command
Palette), model comparison panel
- Real chat-session history via the "⋯" menu's History popover — past
conversations (real backend data, not the local action log) become the
live conversation when opened, so you can pick up right where you left
off
- Checkpoints and "undo last agent action" for accepted edits
- A native onboarding walkthrough
Auth
There is no escapeAI.authToken setting anymore. The token lives in VS
Code's SecretStorage, set via the sign-in panel (escapeAI.signIn) —
either "Sign in with browser" (Google OAuth) or "Use API key instead". A
one-time migration (auth/tokenStore.ts) moves a pre-existing plaintext
escapeAI.authToken value into SecretStorage on first activation for anyone
upgrading from before this change, then clears the old setting
(best-effort — a real config-API restriction on writing an undeclared key is
handled gracefully, never blocks the migration itself).
Settings
| Setting |
Purpose |
escapeAI.apiBaseUrl |
Backend base URL (defaults to https://api.escape-ai.org; point at http://localhost:8000 for local dev) |
escapeAI.inlineCompletionsEnabled |
Toggle inline ghost-text completions |
escapeAI.inlineMaxContextChars |
How much preceding text to send for inline completions |
escapeAI.ragAutoIndexEnabled |
Controls on-save indexing and the startup full-workspace index |
escapeAI.ragTopK |
RAG retrieval depth |
escapeAI.desktopAppPath |
Path to the Escape AI Desktop App, for escapeAI.openDesktopApp |
escapeAI.defaultProvider |
Seeds the composer's model picker on first use only — the per-workspace choice you make in the composer itself takes over after that |
escapeAI.autoApplyLowRisk |
Stored only, no functional effect yet — shown in the settings panel but not read by any apply path |
escapeAI.terminalApprovalMode |
Governs run_terminal_command: always-ask (default) reviews every command, auto-approve-safe skips the card for a narrow read-only allowlist (git status/diff/log, ls, pwd, cat, etc. — anchored to the whole command, no shell chaining/redirection), never blocks every command outright |
escapeAI.autoDetectMode |
Auto-pick the composer mode from each message's text (default: on) — see "Auto-detected mode" above |
Known limitations
- GitHub sign-in isn't implemented — Google OAuth or a manual API key
only. (Desktop's GitHub flow uses a custom URI scheme that doesn't map
cleanly onto VS Code's
vscode:// URI handler; see signInPanel.ts's
trailing comment for the specifics.)
- Agent mode's tool-calling is OpenAI-only (see above) — a real backend
constraint.
- Diff "added/removed" line counts use a real LCS (longest-common-
subsequence) line diff for reasonably sized files, falling back to a
cruder multiset comparison above ~2000×2000 lines to avoid an expensive
diff on a huge generated file.
- Startup RAG indexing caps at 500 files on a large monorepo checkout —
filled most-recently-modified-first (a real
stat() pass, not the raw
order findFiles returns), but still not a substitute for indexing the
whole workspace.
escapeAI.autoApplyLowRisk is still a UI-only placeholder (see the
settings table above) — escapeAI.terminalApprovalMode is fully wired.
Testing
npm test runs a real @vscode/test-electron suite (not mocked contexts)
against a temp workspace fixture with an initialized git repo, covering the
pure logic (diff stats, bash-command extraction, path filters), the token
migration, terminal/commandRunner.ts, and agent/tools.ts's tool
dispatcher (including the permission-gated tools, via a fake chat webview
that auto-resolves Allow/Deny the way a real click would).
chatHtmlScript.test.ts additionally runs the chat webview's real
evaluated getChatHtml() output through a headless DOM (jsdom) — not the
raw TypeScript source — since chatHtml.ts's entire inline <script> is
itself the text of one outer TS template literal, so a single backslash in a
regex (\n, \s, \d, \*) can get silently mangled before it ever reaches
a real browser. This is the only check that would have caught the session's
worst bug (a syntax error that broke every click in the sidebar); tsc and
reading the .ts source cannot see it. Validated by deliberately
reintroducing that exact bug and confirming the suite fails loudly.
Publishing
This extension is published manually via the Marketplace web UI
(marketplace.visualstudio.com/manage), not vsce publish — no Marketplace
Personal Access Token is configured yet (Azure DevOps org creation for the
escape-ai account hit a blocker; revisit vsce publish once that's
sorted, it enables one-command auto-incrementing releases).
To cut a new release:
./scripts/release.sh patch # or minor / major
This bumps the version, adds a placeholder CHANGELOG entry (fill it in
for real before publishing), and rebuilds escape-ai-code-assistant-<version>.vsix.
Upload that file via the publisher's Update button on the Marketplace.
Installed users get it automatically — VS Code auto-updates extensions by
default, no separate configuration needed.