What is Onyx Code
Onyx Code is a privacy-first AI coding editor built on the VS Code foundation. It bundles a local inference engine (llama-server) plus a curated catalog of GGUF models, so chat and autocomplete work fully offline by default.
External servers (Ollama, LM Studio, OpenAI-compatible) are supported as an opt-in backend swap. Everything you would expect from VS Code is present (extensions, themes, keybindings, settings sync via import). The AI-specific surfaces sit alongside, scoped under the onyxcode.*settings namespace and an “Onyx” activity-bar item on the left rail with a chat sidebar on the right.
Pricing and licensing
Onyx Code is a one-time purchase. The Free tier covers local chat, inline autocomplete, local models, and the codebase index. Onyx Code Pro unlocks Plan and Auto agent modes, additional MCP servers, project memory, whole-codebase mode, and other Pro surfaces. The in-app activation flow uses a 16-character code emailed at purchase plus an emailed 6-digit verification code, runs on up to 3 devices per license, verifies offline against an embedded Ed25519 public key, and supports an offline-activation file for air-gapped machines. For the full activation, recovery, and device-management reference, see Licensing and activation.
Sibling product: Onyx Chat
onyxchat.appis a standalone Claude-Desktop-shaped local-AI chat app that reuses ~75-80% of Onyx Code's substrate. It is not part of Onyx Code; mentions of “Onyx Chat Pro” in the activation docs refer to that sibling product.
Quick start
Five minutes from download to your first AI reply. The onboarding wizard runs automatically on first launch.
- Install - download the signed installer from
onyxcode.app. Open the app; the onboarding wizard runs automatically the first time. - Pick a model - the wizard recommends models that fit your hardware. Confirm a download (or skip and add a
.gguffrom disk later). - Open the chat - press
Cmd+L(macOS) /Ctrl+L(Windows / Linux), or click the speech-bubble icon in the right sidebar. - Ask a question - type in the chat input and press Enter. Reference files in your workspace with
@mentions. - Apply changes - when the AI proposes code, the diff opens for review. Click Keep or Discard per file.
# Reference a file in chat
@src/components/Header.tsx
"Refactor this to extract the search bar into its own component"
# Multiple file mentions per turn
@src/index.ts @src/utils/auth.ts
"Make these match the pattern in auth.ts"Onboarding wizard
Auto-launched on first run; re-runnable any time via Command Palette → Onyx Code: Show Onboarding Wizard.
Steps
- Welcome - short intro and a hardware-detection summary (e.g. Apple Silicon, 36 GB unified memory).
- Download a Model - recommended-for-your-hardware picks plus an Add from File...path for offline imports. Includes the “How AI quality works” callout, per-card “Light model” badge on 3B-or-smaller picks, and the Codestral starter+background flow when a 5 GB+ model is picked.
- Import from VS Code - detects an existing VS Code install and offers to copy five categories with checkboxes: Settings, Keybindings, Snippets, Themes, and Extensions.
- Privacy summary - explains Air-Gap, Activity Log, Prompt Sanitizer, and
.onyxnoai. Skipping is allowed; Air-Gap can be toggled later. - You're All Set - the wizard closes; the chat sidebar opens.
Completion is tracked under onyxcode.onboarding.completed; clearing it triggers the wizard on next launch.
Licensing and activation
Onyx Code Pro is a one-time purchase. Activation runs locally: the desktop verifies a signed JWT against an embedded Ed25519 public key, then caches the license under your OS secret store. No background subscription, no recurring charges, no telemetry tied to the license.
Free vs Pro
The Free tier covers local chat, inline autocomplete, local GGUF models, and the codebase index for as long as you use the editor. Onyx Code Pro unlocks Plan and Auto agent modes, additional MCP servers beyond the bundled pack, project memory across sessions, whole-codebase (long-context) mode, and other Pro-only surfaces. A status-bar pill on the left shows the current tier (Onyx Free or PRO); click it to open the License Panel.
Activating Pro (online, code + email verification)
After purchase, you receive a 16-character activation code by email (Crockford alphabet, no ambiguous characters). Online activation also confirms you control the purchase inbox via a one-time email code, so a code shared without inbox access cannot unlock Pro online. To activate:
- Open the Command Palette (
Cmd+Shift+P/Ctrl+Shift+P) and runOnyx: Activate Pro, or type/activatein chat, click Activate Pro in the License Panel, or use the Already Have Pro? step in the Welcome wizard on first run. - Enter your 16-character code and the email you bought with, then click Send Verification Code. If they match your license, a 6-digit code is emailed to that address.
- Enter the 6-digit verification code and click Activate.
- The desktop POSTs the code, email, verification code, your hashed Machine ID, and the app version to the licensing server. On success, the server returns a signed JWT that this device caches in secret storage. The status bar flips to
PRO.
Activation requires an internet connection. If you are permanently air-gapped, use Activate from Offline File instead (see below).
Activating offline (license file)
For machines that cannot reach the internet, mint a .onyxlicense file from any internet-connected device at onyxcode.app (direct buyers) or at codesnatch.io/onyx/offline-activation (codesnatch members), copy it to the air-gapped machine, then run Onyx: Activate from Offline File (also reachable as /activate-file in chat, or from the License Panel). The file is verified against the embedded public key with no network call. Offline files are valid for 365 days; mint a new one before expiry to renew.
Already activated on this device
Running Onyx: Activate Pro (or /activate) on a device that already holds an active Pro license does not present the input form. The desktop short-circuits to an Onyx Code Pro is already active on this device dialog showing your purchase email and three buttons:
- View License opens the License Panel with full license details.
- Manage Devices jumps to the device list for the current license.
- Close dismisses the dialog.
The licensing service refuses to send a fresh activation request in this state as a second-layer guard, so a DevTools bypass of the dialog still cannot burn a duplicate activation or knock the device off its current binding. To activate with a different code, run Onyx: Deactivate This Device first.
Lost your activation code (recovery)
Run Onyx: Resend Activation Code by Email (or click Lost your code? in the License Panel). Enter the email address you used at purchase. The server checks for an active license under that email and, if one exists, re-mails the 16-character code.
The recovery endpoint is designed not to leak which addresses have purchased Onyx Code Pro. Several defenses run in layers:
- Identical response shape. Whether or not the email matches, the server returns the same status code, body, and headers. The desktop toast is the same in both cases (Request received. If this email has an active Onyx Code Pro license, the activation code will arrive in your inbox shortly.).
- Constant-time floor. Every response is padded to at least 350 ms so a missing license cannot complete faster than a successful send and reveal itself by timing.
- Three rate-limit keys. 3 requests per 24 hours per email address, 10 per hour per IP, and 5 per 24 hours per machine. The tightest one binds; the 429 response never says which key tripped.
- Origin check. The endpoint requires an
X-Onyx-Client: desktop/<version>header that every production build sends. Casual scrapers without this header fail closed with the same generic response. - Client-side cooldown. The desktop adds a 60-second cooldown after each request, persisted across app restarts. Accidental double-clicks (or a slow-network retry) cannot fire repeat requests within that window.
Managing devices
One Onyx Code Pro license runs on up to 3 devices at a time. Run Onyx: Manage Devices (or /manage-devices in chat) to see the devices bound to your license. Each row shows the device label (OS hostname when available), platform, app version, and last-seen date.
To free a slot on a device other than the one you are currently using, click the Remove button next to it. The server sends a confirmation link to your purchase email; opening that link on the current device within 15 minutes removes the target device. The link is single-use and bound to the requesting machine, so it cannot be replayed from somewhere else.
To remove the device you are currently on, run Onyx: Deactivate This Device instead. The server rejects requests to remove the calling device via Manage Devices with a dedicated error, so the local-deactivate path is the only way to free your own slot.
Refreshing the license
Online licenses are cached as 30-day JWTs. A background scheduler ticks every 6 hours and refreshes the token once it enters its last week of validity, so the cache renews on its own as long as you are online. To force a refresh (after a network switch, after toggling Air-Gap off, or just to verify your license is still good), run Onyx: Refresh License Now or click Refresh Now in the License Panel.
Offline-file licenses (365 days) are self-contained and do not refresh. The Refresh Now button is hidden when the current license is an offline file. When the 365-day window is within 30 days of expiry the desktop shows a soft notification with a one-click link to onyxcode.app/offline-activation where you can mint a fresh file; if the window closes before you renew, the desktop drops to Free and shows a recovery notification with the same link.
Deactivating this device
Run Onyx: Deactivate This Device (or /deactivate) to clear the cached license locally and release the device slot on the server. The license itself is preserved; you can re-activate on this machine any time, or use the slot on a different machine. Deactivation requires an internet connection so the server-side release succeeds. If Air-Gap Mode is on, the command refuses and points you at Manage Devices from another machine.
The License Panel
Run Onyx: Open License Panel (or /license in chat, or click the status-bar tier badge) to open a unified license overview. Pro users see their purchase email, license source, and cache-expiry date plus buttons for Refresh Now, Manage Devices, Show Machine ID, and Deactivate. Free users see a short tier explainer plus Activate Pro, Activate from File, Lost your code?, and Show Machine ID.
Machine ID
The Machine ID is a SHA-256 one-way hash of a stable per-install identifier. The server sees only this hash, never the underlying identifier or any device-fingerprinting data. Run Onyx: Show This Device's ID to display it; you only need it for offline activation (paste it into the offline-activation form to mint a file bound to this machine) or for support tickets.
Chat
The chat panel is Onyx's main AI surface. It lives in the right auxiliary bar and supports streaming markdown rendering, file mentions, attachments, sessions, slash commands, smart apply, and per-message quick actions.
Chat panel
- Where:right auxiliary bar, “Chat” view in the “Onyx Code” container.
- Open / close:
Cmd+L(primary) orCmd+I(secondary). - Setting:
onyxcode.chat.enabled- hide the panel without uninstalling.
Chat-input toolbar
A single row of square icon buttons sits below the textarea:
| Button | What it does |
|---|---|
| Air-Gap shield | Brand-green when on; click opens Privacy settings. |
.onyxrules | Brand-green when a rules file is loaded; click opens it, or scaffolds .onyxrules from a template if none exists. |
.onyxnoai | Brand-green when .onyxnoai is loaded or the workspace AI kill switch is on. |
| Agent-mode pill | Plan / Ask / Edit-auto / Auto. Opens upward-anchored picker. |
| Apply-mode wand | Auto / Manual apply. |
| Worktree | Run-in-worktree toggle (see Agent mode). |
| Model selector | Active chat-model picker. |
| Token counter | Pill showing used tokens vs the active model's context window. |
| Send / Stop | Claude-style dimmed-primary at rest; swaps to Stop while streaming. |
File mentions (@path)
Type @in the chat input to start an autocomplete dropdown that lists files in the workspace. Picking one attaches that file's content to the next message. Multiple mentions allowed per turn.
Explain @src/components/Header.tsx and propose a refactor
Refactor @src/index.ts to match the patterns in @src/utils/auth.tsSessions and history
Every chat is auto-saved on each turn. The last active session is automatically reopened on app launch, so resuming work after a quit lands you exactly where you left off. Older sessions are pruned past a hard cap. Use /new to start a fresh session and save the current to history.
Auto-summarize on context fill
When the assembled prompt crosses ~70% of the active model's context window, the oldest half of the conversation is replaced with a short model-generated summary. Toggle with onyxcode.chat.autoSummarize (default on). Use /summarize to compress earlier turns immediately.
Whole-codebase mode (long-context)
For workspaces small enough to fit your model's context window, Onyx can send the entire repo to the AI as ambient context, bypassing semantic search. Toggle onyxcode.chat.wholeCodebaseMode (default off, per-workspace). Honors .gitignore plus a workspace-local .onyxignore.
Ambient git-diff context
When the workspace is a git repository, Onyx auto-injects a compact summary of your uncommitted changes into the system prompt. Use /diff to inspect. Settings: onyxcode.chat.gitDiffMode (default auto) and onyxcode.chat.gitDiffMaxBytes (default 4 KB).
Chat export
Use /export to save the current conversation to a .md (Markdown, human-readable) or .json (full session, round-trip safe) file via a save dialog.
Inline autocomplete
As-you-type FIM (fill-in-the-middle) suggestions in the editor, rendered as ghost text. Tab accepts; Esc dismisses.
Capabilities
- Multi-line completions (default on).
- Cross-file context - function signatures and imports from open tabs feed the prompt.
- Smart trigger - suppresses suggestions while you are deleting, inside strings/comments, or just after dismissing one.
- Predictive edits - heuristic, no AI call. After you change a value-like token, Onyx scans the same file for structurally similar lines and suggests the same change as ghost text.
Speculative decoding
A small “draft” model speculates several tokens ahead, which the main model verifies in a single batched step. Cuts FIM latency by 30-50% on Apple Silicon and CUDA when the draft architecture matches.
Settings
{
"onyxcode.autocomplete.enabled": true,
"onyxcode.autocomplete.multiLine": true,
"onyxcode.autocomplete.crossFileContext": true,
"onyxcode.autocomplete.smartTrigger": true,
"onyxcode.autocomplete.predictiveEdits": true,
"onyxcode.autocomplete.debounceMs": 400,
"onyxcode.autocomplete.maxTokens": 128,
"onyxcode.autocomplete.temperature": 0.1,
"onyxcode.ai.fimTemplate": "auto",
"onyxcode.ai.speculativeDecoding.enabled": true,
"onyxcode.ai.draftMax": 8
}Onyx Tab - next-edit prediction (Zeta)
A third autocomplete provider, branded Onyx Tab. Powered by Zed Industries' open-source Zeta-2 model (Apache 2.0, GGUF, runs on the bundled llama-server unchanged). Free tier. After a substantive edit, Onyx reads the last 20 edits in a ring buffer and fires a local inference request to a dedicated llama-server process on port 12347. If the model returns a meaningfully different rewrite of your cursor's line, it appears as inline ghost text.
Cursor-jump: when you rename an identifier and Tab-accept the Zeta prediction, the cursor automatically jumps to the next occurrence of the old identifier in the file. A subtle → Tab hint appears at each pending site. Tab again accepts and jumps to the next.
| Provider | When it fires | What it predicts |
|---|---|---|
| FIM | As you type | Code that fills the gap at the cursor. |
| Predictive Edits | After you change a value-like token | Same change on structurally similar lines. No model call. |
| Next-edit prediction | After any substantive edit | Rewrite of the cursor's line based on recent edit history. ML-trained, local Zeta-2. |
Right-click “Generate Tests for Selection”
Editor context menu, or Command Palette → Onyx: Generate Tests for Selection. Sends the selected code to chat with a pre-filled prompt asking for tests. The test file is pre-declared as the response target so Smart Apply lands the proposed test file in the right path automatically.
Models
Onyx ships a bundled llama-server and supports any GGUF model on disk plus external OpenAI-compatible servers.
AI Settings panel
Open from the left activity bar (Onyx icon → Models view) or via Command Palette → Onyx: Browse Models / Onyx: Open Embeddings. Three tabs: Models, Browse Models, Embeddings.
Models tab
Downloaded models from ~/.onyxcode/models/. Each card shows file size, parameter count, and download date. The list is split into Chat models and the Onyx Tab (Inline Edit Prediction) section. Activating a card switches the chat backend; the active model gets a brand-green Active badge.
Browse Models tab
A curated featured catalog plus HuggingFace search. Models are tagged Recommended for your hardware based on detected RAM and GPU. Search results can be sorted by Popular, Name, VRAM (largest model first), or Context(largest context window first). The expandable “Which model version should I pick?” callout explains Q4 / Q5 / Q8. Models with 3B parameters or fewer get a yellow Light model badge.
Model A/B comparison (Pro)
Run one prompt against several models side by side to see which one is best for your work, before committing to it. In chat, type /compare followed by your prompt, then pick 2 to 5 installed models (the picker remembers your last set). Running /compare with no prompt shows a Choose Models button to pick the set ahead of time. Onyx assembles the context once and feeds every model the same prompt, so the only variable is the model.
Locally, models run one at a time (only one model is resident in memory at once), so a comparison loads each model in turn. Each model is confirmed fully loaded before it answers, so swapping between local models is reliable. This means it works on any machine that can run a single model, with no extra setup; the trade-off is that each added model adds a load, so a run takes longer than a normal chat. Your currently active model runs first to save a reload, and your active chat model is restored when the comparison finishes.
While a model works, its panel shows a live status (loading, generating) instead of the raw answer. When it finishes it shows Completed with a metrics line (approximate tokens, wall-clock seconds, and tokens per second), labelled Model A, Model B, and so on with the real model name beside it. Each result is collapsed by default; expand the ones you want to read and compare. Per result you can Keep This Answer (drops it into the chat so you can apply its code) or Make Active Model (switches your normal chat backend to it). A Change Models button below the comparison re-opens the picker and re-runs the same prompt with a different set.
/compare write a debounce hook in TypeScriptEmbeddings tab
The active embedding model decides which files RAG retrieves on every chat turn. The bundled default is Jina v2 Base Code, a code-tuned embedder that runs on any machine (4 GB+ RAM). The curated featured list lets you swap it: Nomic Embed Text v1.5 for general text, or Nomic Embed Code for maximum retrieval quality on capable hardware. Nomic Embed Code needs 16 GB+ RAM(a ~4.4 GB model that builds a larger, slower index), so it is hidden on machines that can’t run it and offered as an opt-in upgrade where they can.
External backend (Ollama / LM Studio / OpenAI-compatible)
AI Settings → Models tab → Connect to External Server. Point Onyx at any OpenAI-compatible endpoint (http://localhost:11434 for Ollama, http://localhost:1234 for LM Studio). Onyx never silently polls the external endpoint at startup; the probe runs only when you open the section or click Connect.
{
// Bundled engine ports (defaults)
"onyxcode.ai.port": 12345,
"onyxcode.ai.embeddingPort": 12346,
// Models directory
"onyxcode.ai.modelsPath": "~/.onyxcode/models/",
// GPU offload (number of layers, or "auto")
"onyxcode.ai.gpuLayers": "auto"
}Codestral first-load UX
When the wizard recommends the ~14 GB Codestral model, Onyx installs a ~1 GB starter (Qwen 2.5 Coder 1.5B) in the foreground so chat works in ~2 minutes; the big model streams to disk in the background. A status-bar pill shows progress. When the big model finishes, a notification offers Switch / Keep current.
Bundled inference engine
Onyx bundles the llama.cpp llama-server binary. Two processes run: chat (default port 12345) and embedding (default port 12346). Flash-attention 2 forced on, KV cache prefix reuse enabled.
Codebase indexing and RAG
Onyx indexes your workspace into a local vector store so the AI can retrieve the most relevant code blocks per chat turn without you mentioning them.
Index lifecycle
- Background indexing runs on workspace open if
onyxcode.index.enabledis on. - Watch mode keeps the index incrementally updated as files change.
- Persisted snapshot survives restarts;
/reindexrebuilds from scratch,/reindex-clearwipes both the in-memory index and the on-disk snapshot.
How retrieval works
On every chat turn, Onyx embeds the user message, runs cosine similarity against the vector store, and injects the top-5 most relevant code blocks into the system prompt. The /workspace <query> slash command widens that to top-15 for harder questions.
Workspace primer
A compact snapshot of the workspace (top-level layout, README excerpt, manifest summary) is auto-generated on first chat in a workspace and injected into every system prompt. Run /primer to inspect or refresh it.
Settings
{
"onyxcode.index.enabled": true,
"onyxcode.index.maxFileSizeKB": 512,
"onyxcode.index.maxTotalFiles": 5000,
"onyxcode.index.concurrency": 4,
"onyxcode.index.persistEnabled": true,
"onyxcode.index.watchEnabled": true,
"onyxcode.index.excludeGlobs": {},
"onyxcode.ai.rag.enabled": true,
"onyxcode.ai.rag.excludePatterns": [
"node_modules", ".git", "dist", "build"
]
}Project configuration files
Onyx reads a small set of files at the workspace root that customize how the AI behaves on this project. Run /init once to scaffold all of them with starter templates.
ONYX.md - project overview
Human-readable overview of the project (what it is, key folders, conventions, how to run). Injected into every chat system prompt so the AI starts each turn with project context.
# acme-dashboard
Next.js 14 + Prisma + Postgres dashboard for internal ops.
## Layout
- `app/` - App-router routes; server components by default.
- `lib/db.ts` - Prisma client singleton.
- `scripts/` - One-off migrations and admin helpers.
## Conventions
- TypeScript strict; no `any`.
- Server actions over client-side fetch.
- Tailwind utilities; one shared `Button` in `components/ui/`.
## How to run
- `pnpm dev` - local dev server on :3000.
- `pnpm test` - Vitest, integration tests hit a local Postgres..onyxrules - project rules
Plain-text rules loaded into every chat (naming conventions, framework choices, what to avoid, testing commands). 16 KB max. If Onyx finds a .cursorrules instead, it loads that file unchanged so existing Cursor users get zero-friction parity.
# Stack
- TypeScript strict mode, React 19, Tailwind v4.
- Server actions only; no client-side fetch.
# Style
- Match my tab indentation.
- Don't add JSDoc unless I ask.
# Don't
- Edit anything under dist/ or .next/.
- Suggest npm install for packages already in package.json..onyxnoai - privacy excludes
Gitignore-syntax patterns the AI should never see (chat, autocomplete, RAG indexing). Built-in defaults already cover common secrets (**/.env, **/secrets/**, **/*.pem, **/.aws/**, **/.ssh/**, **/id_rsa*). Use !pattern to negate.
# Project-specific privacy excludes (gitignore syntax).
# Built-in defaults already cover .env, secrets/**, *.pem, .aws/**, .ssh/**.
# Whole directories
infra/private/**
ops/runbooks/**
# Specific files
docs/internal-launch-checklist.md
# Negate the default so a sample env file *is* visible to the AI
!**/.env.example.onyxignore - whole-codebase mode excludes
Gitignore-syntax patterns to exclude from the onyxcode.chat.wholeCodebaseMode snapshot only. Distinct from .onyxnoai (which hides files from the AI entirely). Use this to keep large generated files, fixtures, or vendored code out of the whole-repo prompt.
# Drop generated + vendored content from whole-codebase mode prompts.
**/*.generated.ts
**/__generated__/**
docs/**/*.md
fixtures/large-corpus/**
# But re-include the architecture overview if it lives under a
# .gitignore'd folder.
!docs/internal/architecture.md.onyx/instructions.md - extended instructions
Long-form structured instructions (standing rules, things to avoid, testing strategy). Injected into every system prompt. Probe order: configured instructionsFile → .onyxrules → ONYX.md → .cursorrules → .onyx/instructions.md. First match wins. 4 KB cap by default.
/init - scaffold all four files
Running /init from chat scaffolds the four files above in one pass. Existing files are left untouched. Onyx asks Use AI to Generate, Use Template, or Cancel. Quick (template) is the trailing-edge primary on macOS so the default Enter key gets a deterministic outcome.
Agent mode
The agent mode picker chooses how much autonomy the AI has. The chat-input pill (next to the model selector) shows the current mode; the slash commands /plan, /ask, /edit, /auto switch it.
Modes
- Plan - AI proposes changes, drafts code, and lists actions, but never edits files or runs commands. Read-only by design.
- Ask before edits (default) - AI confirms each file write, shell command, and mutating tool call before executing.
- Edit automatically - AI auto-applies file edits but still confirms shell commands and mutating tool calls.
- Auto - runs unattended. Available only inside a worktree; falls back to Ask outside one. The status bar shows a brand-prominent
→ Auto mode · <branch>pill while active so the unattended state is visible even when you switch files.
Permissions
Three layers, top to bottom (deny tiers always beat allow tiers, regardless of mode):
.onyxnoai+ built-in defaults (deny tier) -.env, secrets, private keys, plus user-listed patterns. The agent host vetoes matching reads even in Auto / Bypass-Approvals mode.- File-based rules in
.onyx/permissions.json(committable, fine-grained per command / path / tool) - the recommended layer for everything else. - Settings-based
onyxcode.agent.alwaysAllow.*(legacy, all-or-nothing per tool kind, kept for migration parity).
A deny pattern always wins over every allow above it - including session-level Bypass Approvals - so a careless local override can never re-enable something the team explicitly denied.
.onyx/permissions.json - AI approval rules
Two files, both at the workspace root under .onyx/:
| File | Status | Purpose |
|---|---|---|
.onyx/permissions.json | committed | Team-wide rules, reviewed in PRs. |
.onyx/permissions.local.json | gitignored (auto-appended on first write) | This machine's overrides - host-specific paths, your personal allowlist. |
Both files share the shape below. It is intentionally aligned with Claude Code's .claude/settings.json so you can paste snippets verbatim:
{
"version": 1,
"permissions": {
"allow": [
"Shell(git log:*)",
"Shell(npm test)",
"Shell(npm run build:*)",
"Read(./src/**)",
"MCP(filesystem:listDirectory)",
"MCP(github:*)"
],
"deny": [
"Shell(rm:*)",
"Shell(curl:*)",
"Shell(git push:--force*)",
"Read(./.env*)",
"Write(./.env*)",
"Write(./node_modules/**)"
]
}
}Pattern grammar
Shell(<command>)- exact command-line match.Shell(<prefix>:*)- word-boundary prefix match.Shell(git log:*)matchesgit log,git log -3,git log --oneline -10; does not matchgit logger.Read(<glob>)/Write(<glob>)- workspace-relative glob (**and*supported). Leading./is stripped.MCP(<server>:<tool>)- exact MCP tool match;MCP(<server>:*)matches every tool on a server.Bash(...)is accepted as an alias forShell(...)so Claude Code snippets paste cleanly. The parser normalizes to the canonicalShell(...)form on first edit.
Precedence (highest to lowest)
.onyxnoaipatterns + built-in.env/ private-key defaults (read tier only; reads matching these are denied even in Auto / Bypass-Approvals).denypatterns in.onyx/permissions.local.json.denypatterns in.onyx/permissions.json.- Session Bypass Approvals / Autopilot (still beaten by any deny above).
allowpatterns in.onyx/permissions.local.json.allowpatterns in.onyx/permissions.json.- Built-in heuristics (working-directory read auto-approve, shell allowlist, protected-glob write checks).
- Fallback: prompt the user with the confirmation card.
Recommended starter content
Seed your .onyx/permissions.json with at least these deny entries to protect secrets and the dependency tree:
{
"version": 1,
"permissions": {
"deny": [
"Read(./.env*)",
"Write(./.env*)",
"Read(./.git/config)",
"Write(./node_modules/**)"
]
}
}.onyx/permissions.json deny patterns for explicit, committed AI read denials AND list the same paths in .onyxnoai to also hide them from the embedding indexer, FIM, and RAG context assembly. Since 2026-05-15 .onyxnoai also gates direct AI reads at the deny tier, beating Auto mode and Bypass-Approvals, so the two systems cover overlapping but complementary surface area.Quick open and editing
Type /permissions in the chat panel to open the file (creates it from a starter deny list - recursive remove, force push, curl, .env, and node_modules/ writes - if it is missing). Any text editor works; the file is plain JSON and ships with a registered JSON schema, so editing it inside Onyx Code gives inline validation, autocomplete on the pattern strings, and hover-help with the grammar reference.
Carousel scope picker
When a confirmation card appears in the chat input carousel, the Always Allow submenu offers four file-based actions for both shell and MCP tools:
- Always allow this command (project) - writes
Shell(<cmd>)orMCP(<server>:<tool>)to.onyx/permissions.json. - Always allow this prefix (project) / Always allow all server tools (project) - writes the wildcard form.
- The same two with (on this machine) - writes to
.onyx/permissions.local.jsoninstead.
Each click is one file write, debounced 250 ms to coalesce rapid clicks. The rule survives across windows, sessions, and (for project scope) across teammates via git.
Try it yourself
# 1. In a workspace, create .onyx/permissions.json:
{ "version": 1, "permissions": { "allow": ["Shell(echo hello:*)"], "deny": ["Shell(rm:*)"] } }
# 2. Open the chat panel in "Ask before edits" mode.
# 3. Ask the AI to run `echo hello world` -> tool runs silently, no card.
# 4. Ask the AI to run `rm -rf /tmp/some-file` -> denied; the file is untouched.
# 5. Ask the AI to run `curl example.com` -> confirmation card (file unknown).Migration from legacy approvals
The first time a post-2026-05-15 build runs in a workspace that had old chat/autoconfirm approvals, three sources are silently migrated into .onyx/permissions.local.json:
| Legacy source | Migrated pattern |
|---|---|
| Workspace chat/autoconfirm for run_in_terminal | Shell(*) (broad, mirrors what the storage key actually granted) |
| chat/autoconfirm-combination entries with args | Narrow Shell(<command>) per entry |
| chat/servers/autoconfirm MCP server allowlists | MCP(<defId>:*) per server |
Settings-based fallback (legacy)
For migration parity, the all-or-nothing settings still work and live alongside the file- based system:
{
"onyxcode.agent.mode": "ask", // plan / ask / editAuto / auto
"onyxcode.agent.alwaysAllow.fileRead": true,
"onyxcode.agent.alwaysAllow.fileWrite": false,
"onyxcode.agent.alwaysAllow.shellExec": false,
// Bypass confirmation for specific MCP tools
"onyxcode.agent.alwaysAllow.mcp": [
"filesystem:listDirectory",
"git:status"
]
}Worktree-sandboxed agents
When the user picks Run in worktree from the chat toolbar, Onyx creates an isolated git worktree. The agent runs inside the worktree with Auto-mode permissions, so file writes and shell commands can run without prompting, without affecting the main branch.
- Apply menu: Apply / Discard / Keep choices route through the worktree back to the main tree.
- Resume on launch: worktrees that survived a hard quit prompt with [Keep] / [Discard All] on next launch.
- Stuck-state recovery: if a previous run crashed and left an on-disk
.onyx-agents/<sessionId>/directory that git no longer tracks, the next Run in worktree click cleans up automatically. - .gitignore auto-suggestion: after the first worktree creation in a repo, Onyx offers to add
.onyx-agents/to.gitignore. - Prerequisites: workspace must be a git repository.
MCP support
Model Context Protocol (MCP) servers are subprocesses that expose tools (filesystem, git, search, custom integrations) the agent can call. Onyx ships a curated bundle and supports custom servers.
/mcp slash command
/mcp # List every configured server with status badges
/mcp restart filesystem # Restart a server by id
/mcp stop git # Stop one
/mcp logs sqlite # Print recent stdout/stderr
/mcp add # Interactive add flowBundled MCP server pack
Four ready-to-use stdio presets, each one click to install from the /mcp panel's Bundled Servers subsection:
- filesystem - read / list files within the workspace. Backed by
npx @modelcontextprotocol/server-filesystem. - git -
git status,git log,git diff,git show. Backed byuvx mcp-server-git. - sqlite - query a local SQLite database from the agent. Backed by
uvx mcp-server-sqlite. - fetch - GET arbitrary HTTP(S) URLs. When Air-Gap Mode is on, the Install button is replaced by a red Blocked by Air-Gap pill.
Air-Gap interaction
localhost / 127.0.0.1 / ::1 / unix: / pipe: are also allowed under Air-Gap.OAuth-protected MCP servers
Onyx Code defers to VS Code's native OAuth handshake. The MCP server responds 401 with a WWW-Authenticateheader, Onyx discovers the authorization server via RFC 8414 metadata, performs dynamic client registration if needed, opens your system browser at the provider's /authorizepage, captures the auth code via a localhost redirect, exchanges it for a token, and stores the token via VS Code's auth provider.
Project memory
Long-term context the agent maintains across chat sessions. Memory files live under the user profile (not the workspace) so they survive git clean.
/memory slash command
/memory # Print MEMORY.md index + every memory file in this workspace
/memory show user_role.md # Print one memory file
/memory delete feedback.md # Remove onereadMemory and writeMemory agent tools
The agent calls these directly when running. writeMemory(filename, type, body) persists a YAML-frontmatter Markdown file with id, type, created_at, updated_at. readMemory(filename) returns the contents. Visible in the activity log (kind agent_tool) but not in the chat surface.
Use cases
- Remember the user's role / preferences across chats.
- Track architecture decisions the user explained once.
- Carry forward known issues or workarounds.
Smart Apply and proposed changes
When the AI returns code that targets a file, Onyx stages it as a pending change instead of writing to disk. Cursor-style: nothing on the filesystem moves until the user explicitly accepts.
Apply modes
- Auto (default) - diff editor opens for review with inline Keep / Discard buttons per file.
- Manual - code blocks render with copy / apply buttons; you trigger each apply individually.
Switch via onyxcode.chat.applyMode.
Partial-edit merging and reindent
When the AI returns a code block that clearly targets only part of a file (e.g. one function rewritten with a leading // ... existing code ... marker), Smart Apply merges it into the file in place rather than replacing the whole document. The merged result is reindented to match the surrounding indentation style.
Keyboard shortcuts and status glyphs
Cmd+Shift+Enter/Ctrl+Shift+Enterkeeps every pending change.Cmd+Shift+Backspace/Ctrl+Shift+Backspacediscards them all.- Each pending file in the panel renders a status glyph (added / modified / deleted / conflict).
Code-block path annotations
When the AI emits a fenced code block like the example below (language + colon + relative path), Onyx routes the block to that file directly, skipping the language-match fallback.
```typescript:src/foo.ts
export function foo() {}
```Quality guardrails
A set of automatic defenses that catch common small-model failure modes before they reach the user or the filesystem. All run on every chat reply; none require setup.
Repetition / loop guard
Small (1.5B-3B) coder models occasionally spiral into infinite repetition. Onyx runs a mid-stream loop check (after the buffer crosses ~1 KB, every ~512 chars thereafter) and a post-stream within-line list check. When a loop fires, the stream aborts and the pre-loop content is salvaged.
Repetition penalty
Every chat completion sends repeat_penalty to the inference engine. Default 1.1 is almost imperceptible on capable models but reliably stops small models from looping. Tunable via onyxcode.chat.repeatPenalty (1.0-1.5).
Destructive-edit guard
Before Smart Apply auto-stages a proposed file replacement, two triggers can suppress auto-stage and prompt the user instead.
- Shrink trigger- proposed content is under 30% of the original (catches the small-model “blanked the imports” case).
- Large-rewrite trigger - actual line-diff (LCS-based) shows 100+ add+remove lines on a 50+-line file.
System-prompt hardening
The base chat system prompt carries explicit rules: when producing a code block intended to replace a file, output the FULL file content with only the requested changes; never delete imports, declarations, or unrelated code unless asked; do not repeat the same sentence, phrase, or list item.
Privacy and security
Onyx runs locally by default and exposes structured controls for users with stricter requirements.
Air-Gap mode
Blocks all outbound network traffic from Onyx Code. Model downloads, marketplace, auto-update, external server probes, MCP HTTP servers - all fail closed. Localhost stays available, so the bundled inference engine works.
- Toggle: Command Palette → Onyx: Toggle Air-Gap Mode, or click the status-bar pill.
- Status pill:“AIR-GAPPED” in brand green when on.
- Setting:
onyx.privacy.airGapMode(default off).
Three enforcement layers.
- In-app
gatedFetchwraps every outbound call from Onyx code paths (HuggingFace browser, model downloads, local AI client, external context probe, embedding service, MCP gallery, auto-update). Calls throwAirGapBlockedErrorbefore the network stack is touched. - Extension-host air-gap check runs inside every MCP HTTP and SSE transport (
McpHTTPHandle._fetchInternal, both the common ext-host path and the desktop Node runtime path). The air-gap callback is a required constructor parameter onMcpHTTPHandle, so any future MCP transport subclass that forgets to wire it up is a compile-time TypeScript error - not a silent privacy leak. - Electron
session.webRequest.onBeforeRequestaborts any non-loopback HTTP/HTTPS/WS/WSS request that slips past the first two layers and logs it tomain.logas[Air-Gap] Blocked outbound request: .... Note:0.0.0.0is nottreated as loopback (it's a wildcard bind address that routes to LAN interfaces on Linux/macOS), so SSRF attempts via crafted MCP URLs tohttp://0.0.0.0:<port>/are correctly blocked.
Verify Air-Gap (try this yourself)
# 1. Toggle Air-Gap on; confirm the green AIR-GAPPED pill at bottom-left.
# 2. Open AI Settings -> Models -> Browse Models and search anything.
# Expect "Search failed. Check your internet connection."
# 3. Confirm main.log recorded the block:
tail -20 ~/Library/Application\ Support/code-oss-dev/logs/*/main.log | grep "Air-Gap"
# 4. lsof socket check - proves no outbound socket was opened:
PIDS=$(pgrep -f "Onyx Code.app/Contents" | paste -sd, -)
lsof -nP -iTCP -a -p "$PIDS" -sTCP:ESTABLISHED | grep -v "127\.0\.0\.1\|::1\|localhost"Workspace AI kill switch
Disables every AI surface (chat, autocomplete, RAG, agent tools) for one workspace. Useful when you open a regulated codebase and don't want anything calling out to a model. Toggle: Command Palette → Onyx: Toggle Workspace AI, or status bar pill. Status pill: AI: off or, when partial via .onyxnoai, AI: limited.
Prompt sanitizer
Every chat send and attached file is scanned locally for secret patterns (AWS keys, GitHub PATs, OpenAI keys, Slack tokens, JWTs, PEM private keys, certificates, env-style secrets, plus a high-entropy fallback). On detection, a non-blocking dialog offers Redact and Send / Send anyway / Cancel. Redacted spans are replaced with <REDACTED:patternId> markers before the prompt leaves the renderer.
{
"onyxcode.privacy.promptSanitizer.patterns": {
"aws-access-key-id": false // I never paste these; reduce noise
},
"onyxcode.privacy.promptSanitizer.customPatterns": [
{
"id": "internal-employee-id",
"regex": "EMP-[0-9]{6}",
"description": "Internal employee identifier"
}
],
"onyxcode.privacy.promptSanitizer.entropyThreshold": 4.7
}What gets sent (after Redact and Send):
The token is <REDACTED:github-pat>. Why does the OAuth flow fail?Activity log and audit PDF
Every AI interaction (chat / autocomplete / model download / MCP tool call / agent file edit) appends one line to a local JSONL audit log. The schema is metadata only - no prompt text, no completion text, no file contents.
- Storage:
~/.onyxcode/activity-log/<YYYY-MM>.jsonl(monthly rotation). - Settings:
onyx.privacy.activityLog.enabled(default on),onyx.privacy.activityLog.retentionDays(default 365). - Commands: Onyx: Show AI Activity Log, Onyx: Export AI Activity Audit (PDF).
{"kind":"chat","ts":"2026-05-09T14:32:11.482Z","workspace":"acme-dashboard","model":"qwen2.5-coder-7b-instruct-q5_k_m","tokens_in":1842,"tokens_out":612,"latency_ms":4318,"net":false}No prompt, response, content, text, body, message, or completion field ever appears, by _sanitise() construction. The audit PDF is rendered offscreen with nodeIntegration:false and inline-only CSS, so it generates correctly under Air-Gap.
Event kinds: chat, fim, embed, download, license_refresh, agent_tool (built-in agent tools), mcp_call (MCP server tool calls), redaction, chat_loop_trim, chat_destructive_guard, next_edit_pred. MCP tool invocations are logged separately as mcp_call so operators can filter activity by MCP server usage independently of first-party tool use.
Binary integrity (SHA-256)
The bundled llama-server binary is SHA-256 verified at every spawn against a pinned .sha256 sidecar file. Hash mismatch refuses to spawn with a logged error. The binary path is resolved at build time, never via $PATH - preventing PATH-hijacking attacks. All three inference processes (chat 12345, embedding 12346, next-edit 12347) spawn with --host 127.0.0.1 and cannot accept LAN connections. spawn() calls pass args as arrays - no shell interpolation.
Children are SIGKILL-reaped on graceful Electron shutdown, on synchronous process.on('exit'), and via a constructor-side lsof + ps basename scan at startup. Non-Onyx processes on the same port are never touched (basename exact-match on 'llama-server').
No telemetry
Every upstream VS Code telemetry endpoint has been emptied at the product.json level. The telemetry toggles are still present in settings (for compatibility with upstream extensions that read them), but they have nowhere to send data even if turned on. The network-layer Air-Gap and the empty-endpoint stripping are independent defense layers - either alone guarantees no Onyx-authored telemetry leaves your machine.
Audit posture
Onyx maintains a canonical security checklist (~60 numbered items across 12 sections: network egress, process spawning, file system, IPC/Electron, injection, config security, privacy, MCP trust, supply chain, DoS, error disclosure, Air-Gap integrity). An automated audit skill walks the entire checklist and records a finding (pass / warn / fail + file:line evidence) for every item. The checklist and findings live in the repo and are open for review.
Workflow helpers
Small AI-powered actions that sit alongside the editor's source-control and PR flows.
Draft commit message from staged changes
Command Palette → Onyx: Draft Commit Message from Staged Changes. Reads git diff --cached, sends to the active model, drafts a commit message, and inserts it into the source-control input box (or copies to clipboard if no SCM provider is registered).
conventional format (default - type(scope): subject):
feat(chat): persist loop-trim original on the message
Previously the loop-guard chip lost its "show what was trimmed" content
on session reload. Snapshot the pre-trim model output (capped at 4 KB)
on a new loopTrimmedOriginal field so the toggle survives.
Drafted with Onyx Codefreeform format (no type/scope, no enforced subject prefix):
Persist the loop-trim original on the message so the chip's "Show what
was trimmed" toggle survives a session reload.
Drafted with Onyx CodeThe Drafted with Onyx Code trailer is gated by onyxcode.git.appendSignature; the drafter skips re-appending if the model already wrote one.
Draft PR description from this branch
Command Palette → Onyx: Draft PR Description from This Branch. Computes git diff base..HEAD against the configured base (typically main), sends to the model, drafts a PR description with Summary + Test Plan sections, and copies to clipboard. Rejects model output that's missing the structured sections (catches small-model failures) with a “try a stronger model” hint.
Status bar indicators
All in the bottom status bar; clicks open the relevant settings or panel.
| Pill | When | Click |
|---|---|---|
| AIR-GAPPED | onyx.privacy.airGapMode is on. | Opens Privacy settings. |
| AI: off / AI: limited | Workspace AI kill switch on, or .onyxnoai patterns active. | Opens Privacy settings. |
| Index status | onyxcode.index.enabled is on. | States: scanning, indexing N%, indexed N blocks, failed. |
| Model download | Any model download in flight. | Opens AI Settings → Browse Models with the active download highlighted. |
| AI status | Always when AI service is enabled. | Model name + health dot (green / amber / red). |
| → Auto mode · <branch> | Agent mode is set to Auto AND at least one chat session has an active worktree. | Persistent visual signal that the AI is running unattended. Lists every active branch on hover when more than one session is in Auto. The pill disappears the moment you exit Auto or the worktree is removed. |
| → Onyx Tab | Always (or hidden if next-edit prediction is disabled). | Opens Browse Models. Two states: ready (Zeta-2 installed) or (Get) (not installed). |
Slash commands reference
Type / at the start of a chat input. The command list and their args:
| Command | What it does |
|---|---|
/help | Show every command in the chat. |
/init | Scaffold ONYX.md, .onyxrules, .onyxnoai, and .onyx/instructions.md at the workspace root. |
/onyxrules | Open or create .onyxrules. |
/onyxnoai | Open or create .onyxnoai. |
/permissions | Open or create .onyx/permissions.json (committed AI approval rules). Creates from a starter deny list if missing. |
/instructions | Show the project-specific instructions the AI receives. |
/primer | Show the workspace primer. |
/new | Start a new chat; save the current to history. |
/clear | Reset the AI's view of the conversation; visible messages stay. |
/summarize | Compress earlier turns into a model-generated summary now. |
/attachments | List every file attached to the current chat. |
/file <path> | Attach a file by path. |
/search <query> | Semantic search over the codebase index - no AI call. |
/workspace <query> | Same as a normal chat turn but with wider RAG (top-15 instead of top-5). |
/diff | Print the current uncommitted git diff. |
/export | Export the conversation to .md or .json. |
/stats | Active chat model, embedding model, index status - all in one view. |
/context | Live context-window usage breakdown. |
/model | Show the active chat model details. |
/compare <prompt> | Pro. Run the prompt across 2 to 5 models side by side (locally one model loads at a time), then keep the best answer or make a model active. |
/embedding-model | Show the active embedding model + index status. |
/tab | Show Onyx Tab status (Zeta-2 install / running, paths, settings). |
/reindex | Rebuild the codebase index from scratch. |
/reindex-clear | Wipe the index and on-disk snapshot (no rebuild). |
/plan | Switch agent mode to Plan. |
/ask | Switch agent mode to Ask before edits. |
/edit | Switch agent mode to Edit automatically. |
/auto | Switch agent mode to Auto (requires worktree). |
/mcp [sub] [id] | Manage MCP servers; subcommands: list, start, stop, restart, logs, add. |
/memory [sub] [name] | Show / read / delete project memory files. |
/license | Open the License Panel: tier badge, license details, and one-click buttons for every license action. |
/activate | Open the activation dialog for a 16-character code plus email verification. If Pro is already active on this device, short-circuits to an 'already activated' dialog with View License / Manage Devices / Close buttons instead of presenting the input form. |
/activate-file | Open the OS file picker to activate from a .onyxlicense file (offline activation, no network call). |
/deactivate | Clear the cached license on this machine AND release its slot server-side. The license itself is preserved; you can re-activate any time, on this or another machine. |
/manage-devices | List devices bound to your Pro license and request removal of one. Removal requires a 15-minute email-confirmation link opened on this device. |
Command Palette reference
Press F1 (or Cmd+Shift+P / Ctrl+Shift+P). All Onyx commands sit under the Onyx category.
| Command | What it does |
|---|---|
| Onyx: Toggle Onyx Code Chat | Show / hide the chat panel. |
| Onyx: Browse Models | Open AI Settings - Browse Models tab. |
| Onyx: Open Embeddings | Open AI Settings - Embeddings tab. |
| Onyx: Toggle Air-Gap Mode | Block / unblock outbound network. |
| Onyx: Open Privacy Settings | Jump to the Privacy settings group. |
| Onyx: Toggle Workspace AI | Disable / enable AI surfaces in the active workspace. |
| Onyx: Show AI Activity Log | Render the audit log as a Markdown table. |
| Onyx: Export AI Activity Audit (PDF) | Generate a signed audit PDF. |
| Onyx: Draft Commit Message from Staged Changes | Insert a commit message into the SCM input. |
| Onyx: Draft PR Description from This Branch | Copy a PR description to the clipboard. |
| Onyx: Generate Tests for Selection | Send the editor selection to chat with a tests prompt. |
| Onyx: Rebuild Codebase Index | Force a full reindex. |
| Onyx: Clear Codebase Index | Wipe the index and the on-disk snapshot. |
| Onyx Code: Show Onboarding Wizard | Re-run the first-run wizard. |
| Onyx: Import Settings from VS Code | Run the VS Code import flow outside the wizard. |
| Onyx: Activate Pro | Open the centered modal dialog for a 16-character activation code plus email verification. If Pro is already active on this device, short-circuits to an 'already activated' dialog with View License / Manage Devices / Close buttons. |
| Onyx: Activate from Offline File | Open the OS file picker for a .onyxlicense file. Verifies the embedded JWT against the bundled public key with no network call. |
| Onyx: Show This Device's ID | Open a dialog with the SHA-256 hash of the local install identifier and a Copy ID button. Needed for offline activation. |
| Onyx: Deactivate This Device | Clear the cached license on this machine AND release its slot server-side. The license itself is preserved. |
| Onyx: Refresh License Now | Force-refresh the cached JWT against the licensing server. The background scheduler normally handles this in the token's last week. |
| Onyx: Resend Activation Code by Email | Lost-your-code recovery. Constant-time response and a 60-second client cooldown; non-disclosing wording so the toast cannot be used to enumerate purchase emails. |
| Onyx: Manage Devices | List the devices bound to your Pro license and request removal of one (other than the current device). Removal requires a 15-minute confirmation link opened on this device. |
| Onyx: Open License Panel | Open the unified License panel: tier badge, license details for Pro users, machine ID, and one-click buttons for every license action above. |
Keyboard shortcuts
| Shortcut (macOS) | Shortcut (Win/Linux) | Action |
|---|---|---|
Cmd+L | Ctrl+L | Toggle Onyx Code Chat (primary) |
Cmd+I | Ctrl+I | Toggle Onyx Code Chat (secondary) |
Cmd+Shift+Enter | Ctrl+Shift+Enter | Keep All Proposed Changes |
Cmd+Shift+Backspace | Ctrl+Shift+Backspace | Discard All Proposed Changes |
Tab | Tab | Accept the current inline autocomplete suggestion |
Esc | Esc | Dismiss the current inline autocomplete suggestion |
All standard VS Code shortcuts apply unchanged. Customize via Preferences → Keyboard Shortcuts.
Settings reference
Every setting lives under the unified Onyx Codeparent in the Settings Editor's left tree.
Privacy
| Key | Default | Notes |
|---|---|---|
onyx.privacy.airGapMode | false | Block all outbound network. |
onyx.privacy.workspaceAiDisabled | false | Resource-scoped kill switch. |
onyx.privacy.activityLog.enabled | true | Master toggle for the audit log. |
onyx.privacy.activityLog.retentionDays | 365 | 1-3650. |
onyxcode.privacy.promptSanitizer.enabled | true | Pre-send secret scan. |
onyxcode.privacy.promptSanitizer.patterns | {} | Per-id overrides. |
onyxcode.privacy.promptSanitizer.customPatterns | [] | User-defined regex patterns. |
onyxcode.privacy.promptSanitizer.entropyThreshold | 4.5 | Shannon entropy threshold for the high-entropy fallback. |
onyxcode.privacy.promptSanitizer.highEntropyFallback | true | Toggle the entropy fallback. |
AI
| Key | Default | Notes |
|---|---|---|
onyxcode.ai.modelsPath | ~/.onyxcode/models/ | Where downloaded GGUF files live. |
onyxcode.ai.port | 12345 | Bundled chat server port. |
onyxcode.ai.embeddingPort | 12346 | Bundled embedding server port. |
onyxcode.ai.embeddingModelPath | (blank) | Advanced override; auto-discover. |
onyxcode.ai.embeddingPoolingMode | per model | mean / cls / last. |
onyxcode.ai.activeBackend | (UI managed) | Do not hand-edit. |
onyxcode.ai.fimTemplate | auto | auto / qwen / deepseek / starcoder / codestral. |
onyxcode.ai.speculativeDecoding.enabled | true | |
onyxcode.ai.draftModelPath | (blank) | Auto-discover when blank. |
onyxcode.ai.draftMax | 8 | 2-16 speculative tokens. |
onyxcode.ai.gpuLayers | auto | Number of layers to offload to GPU. |
onyxcode.ai.rag.enabled | true | |
onyxcode.ai.rag.excludePatterns | (see code) | Default excludes node_modules etc. |
Chat
| Key | Default | Notes |
|---|---|---|
onyxcode.chat.enabled | true | Show the panel. |
onyxcode.chat.maxTokens | 4096 | Max response length. |
onyxcode.chat.temperature | 0.7 | 0-2. |
onyxcode.chat.repeatPenalty | 1.1 | 1.0 disables. |
onyxcode.chat.warnOnLightModel | true | Once-per-session notice. |
onyxcode.chat.applyMode | auto | auto (diff editor) / manual (buttons). |
onyxcode.chat.contextWindow | auto | auto or numeric override. |
onyxcode.chat.gitDiffMode | auto | auto / never. |
onyxcode.chat.gitDiffMaxBytes | 4096 | Cap on the injected git diff. |
onyxcode.chat.autoSummarize | true | Auto-condense old turns at ~70% context. |
onyxcode.chat.instructionsFile | .onyx/instructions.md | Path probed for project instructions. |
onyxcode.chat.instructionsMaxBytes | 4096 | Cap on the injected instructions file. |
Agent
| Key | Default | Notes |
|---|---|---|
onyxcode.agent.mode | ask | plan / ask / editAuto / auto. |
onyxcode.agent.alwaysAllow.fileRead | true | |
onyxcode.agent.alwaysAllow.fileWrite | false | |
onyxcode.agent.alwaysAllow.shellExec | false | |
onyxcode.agent.alwaysAllow.mcp | [] | Strings of <server>:<tool>. |
Autocomplete
| Key | Default | Notes |
|---|---|---|
onyxcode.autocomplete.enabled | true | |
onyxcode.autocomplete.multiLine | true | |
onyxcode.autocomplete.crossFileContext | true | |
onyxcode.autocomplete.smartTrigger | true | |
onyxcode.autocomplete.predictiveEdits | true | |
onyxcode.autocomplete.debounceMs | 400 | |
onyxcode.autocomplete.maxTokens | 128 | Provider also stops at \n\n. |
onyxcode.autocomplete.temperature | 0.1 | |
onyxcode.autocomplete.nextEditPrediction.enabled | true | Master toggle for Zeta next-edit predictions. |
onyxcode.autocomplete.nextEditPrediction.modelPath | (blank) | Explicit Zeta GGUF path; auto-discover when blank. |
Codebase Index
| Key | Default | Notes |
|---|---|---|
onyxcode.index.enabled | true | |
onyxcode.index.maxFileSizeKB | 512 | |
onyxcode.index.maxTotalFiles | 5000 | |
onyxcode.index.concurrency | 4 | |
onyxcode.index.persistEnabled | true | |
onyxcode.index.watchEnabled | true | |
onyxcode.index.excludeGlobs | {} |
Git Helpers
| Key | Default | Notes |
|---|---|---|
onyxcode.git.commitMessageFormat | conventional | Or freeform. |
onyxcode.git.maxDiffBytes | 32768 | 1 KB - 256 KB. |
onyxcode.git.appendSignature | true | Append "Drafted with Onyx Code". |
Files and folders Onyx writes
| Path | Scope | Purpose |
|---|---|---|
~/.onyxcode/models/ | user | Downloaded GGUF chat / draft / embedding models. |
~/.onyxcode/activity-log/<YYYY-MM>.jsonl | user | Audit log; one event per line. |
~/.onyxcode/memory/<workspace-hash>/ | user | Project-memory files (MEMORY.md + per-topic .md files). |
~/Library/Application Support/Onyx Code/ | user (macOS) | App state, sessions, snapshots of indices. Equivalents on Win / Linux. |
<workspace>/ONYX.md | workspace | Project overview. |
<workspace>/.onyxrules | workspace | Project rules. |
<workspace>/.onyxnoai | workspace | Privacy excludes. |
<workspace>/.onyx/instructions.md | workspace | Extended instructions. |
<workspace>/.onyx/permissions.json | workspace (committed) | Team-wide AI approval rules (allow / deny patterns). |
<workspace>/.onyx/permissions.local.json | workspace (gitignored) | Per-machine overrides; auto-appended to .gitignore on first write. |
<workspace>/.vscode/settings.json | workspace | When workspaceAiDisabled is set, persists there. |
Glossary
- FIM (fill-in-the-middle) - the prompt format used for inline autocomplete: prefix + suffix around the cursor, model fills the gap.
- GGUF - the quantized model file format used by
llama.cpp. Onyx Code uses GGUF for both chat and embedding models. - Quantization- compresses a model's weights to fit in less RAM at a small quality cost. Q4_K_M is the typical “balanced” choice.
- Speculative decoding - a small draft model speculates several tokens ahead of the main model, which verifies them in a single batched step.
- RAG (retrieval-augmented generation) - embed all workspace files, retrieve the most semantically similar chunks per chat turn, and inject them into the prompt.
- MCP (Model Context Protocol) - a JSON-RPC protocol for connecting agents to external tool servers (filesystem, git, web search, custom integrations).
- Worktree - a separate working directory backed by the same git repository, so the agent can edit files and run commands without affecting your main branch.
- Light model - a model with 3 billion parameters or fewer. Onyx surfaces a yellow badge on these and auto-applies extra guardrails when one is active.
- Air-Gap Mode - block-all-outbound for users on regulated networks. When on, only
localhostconnections succeed. - Activity log - append-only JSONL audit trail of every AI interaction. Counts and metadata only - never prompt or completion text.
- Smart-attach - when an attached file is too large to fit raw (16 KB+), Onyx swaps the full content for an outline + top-K RAG blocks view.
- Workspace primer - a compact snapshot of the workspace layout, README excerpt, and manifest summary. Auto-generated on first chat in a workspace.
- Ambient git-diff context - the auto-injected summary of your uncommitted git changes added to the system prompt when there are pending edits.
- Predictive edits - heuristic, no AI call. Same-value matching on structurally similar lines.
- Zeta- Zed Industries' open-source ML model for next-edit prediction; a Seed-Coder-8B-Base fine-tune (Zeta-2) distributed as GGUF, Apache 2.0. Bundled in Onyx as the inline-edit-prediction provider.
- Next-edit prediction- ML-trained at-cursor prediction. After a substantive edit, Zeta-2 reads the last 20 edits and predicts a rewrite of the cursor's line, offered as inline ghost text (Tab to accept, Esc to dismiss).