Back to onyxcode.app

Onyx Code Documentation

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 on Pro. 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, unlimited chat models, every MCP server running at once, project memory, model A/B comparison, 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.

  1. Install - download the installer from onyxcode.app. Open the app; the onboarding wizard runs automatically the first time.
  2. Pick a model - the wizard recommends models that fit your hardware. Confirm a download (or skip and add a .gguf from disk later).
  3. Open the chat - press Cmd+L (macOS) / Ctrl+L (Windows / Linux), or click the speech-bubble icon in the right sidebar.
  4. Ask a question - type in the chat input and press Enter. Reference files in your workspace with @ mentions.
  5. Apply changes - when the AI proposes code, the diff opens for review. Click Keep or Discard per file.
bash
# 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

  1. Welcome - short intro and a hardware-detection summary (e.g. Apple Silicon, 36 GB unified memory).
  2. 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.
  3. Import from VS Code - detects an existing VS Code install and offers to copy five categories with checkboxes: Settings, Keybindings, Snippets, Themes, and Extensions.
  4. Privacy summary - explains Air-Gap, Activity Log, Prompt Sanitizer, and .onyxnoai. Skipping is allowed; Air-Gap can be toggled later.
  5. 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

The free tier needs none of this: no account, no code, no activation step. Pro is a one-time licence covering three machines.

  • Online activation takes a code plus email verification.
  • Offline activation uses a licence file verified against a public key inside the app, so an air-gapped machine never makes a network call.
  • Devices can be listed and removed, and removed ones stop counting against the limit of three.
  • A lost code can be recovered to the email it was issued to.

Licensing and activation covers each flow step by step, plus what a machine ID is and why only its hash leaves your computer.

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) or Cmd+I (secondary).
  • Setting: onyxcode.chat.enabled - hide the panel without uninstalling.
  • Code while it streams:a code block in a reply that is still being written already has its frame and your editor's font, and a long line scrolls inside the block rather than past the edge of the chat.
  • It shows it is working:while a reply is being written, a line with animated dots at its end says what it is doing whenever nothing else moves: “Thinking” while the model reads your question or a result in, “Reading”, “Searching” or “Writing” while it prepares a step, and “Working” while it finishes, with a seconds counter on a longer wait. It shows from the moment you press Send and goes when the reply ends or you press Stop.

Reading and searching your project

Chat opens files, lists folders and searches the workspace while it answers, so you can ask about a file you never attached. A grey line above the reply names what it read, and a Search Results panel below the answer lists every match, one click from the line it came from. Turn it off with onyxcode.chat.tools.

  • It does the search for you.Ask where something is used, how many times a term appears, or what a named constant is set to (“What is MAX_UPLOAD_MB set to?”), and chat searches before it answers, so the answer comes from the file that defines it.
  • It finds the file you meant. When its first guess at the folder is wrong and your project has exactly one file with that name, chat reads that file.
  • A search limited to a folder such as src/services/ covers every file inside it, and chat is asked to search again when the folder matches nothing.
  • It answers from what it found. Within one reply, chat does not repeat a search or a read it has already done.

Chat-input toolbar

A single row of square icon buttons sits below the textarea:

ButtonWhat it does
Air-Gap shieldBrand-green when on; click opens Privacy settings.
.onyxrulesBrand-green when a rules file is loaded; click opens it, or scaffolds .onyxrules from a template if none exists.
.onyxnoaiBrand-green when .onyxnoai is loaded or the workspace AI kill switch is on.
Agent-mode pillPlan / Ask / Edit-auto / Auto. Opens upward-anchored picker.
Apply-mode wandAuto / Manual apply.
WorktreeRun-in-worktree toggle (see Agent mode).
Model selectorActive chat-model picker.
Token counterPill showing how full the next prompt is and the context window the model runs with (for example 15% / 128k ctx).
Send / StopClaude-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.

text
Explain @src/components/Header.tsx and propose a refactor

Refactor @src/index.ts to match the patterns in @src/utils/auth.ts

Sessions 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. Leaving a chat (/new, New Chat, opening another chat or deleting this one) tells you how many changes you had not kept are discarded; files on disk are not touched. After /clear, your earlier messages stay in Chat History as their own chat.

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. A summary belongs to the chat it was written for: if you start or open another chat while it runs, it is dropped rather than carried over. While it runs, an animated line says so, and it goes once the summary is applied, dropped or stopped. Your latest message is always sent, even on a 4K-token context window: older turns make room first.

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. Available on every tier; what it really needs is a long-context model, not a licence.

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 (the messages and attached files, machine-readable) file via a save dialog. A file .onyxnoai excludes, a protected file from outside the workspace or a symbolic link is listed by its path only, without its content.

Inline autocomplete

As-you-type suggestions rendered as ghost text. Tab accepts, Esc dismisses. Three providers fire at different moments, all on the free tier and all running locally.

  • Fill-in-the-middle completes at the cursor, using a model trained for that rather than your chat model, with signatures and imports from open tabs.
  • Predictive edits repeat a change you just made on structurally similar lines. Heuristic, with no model call.
  • Onyx Tab predicts your next edit from recent history and can jump the cursor through the remaining sites of a rename.

Autocomplete and next-edit prediction covers each provider, speculative decoding and the latency it buys, and how to turn individual providers down rather than off.

Models

Onyx ships a bundled llama-server and supports any GGUF model on disk, plus external OpenAI-compatible servers on Pro.

  • Nothing else to install. The inference engine is bundled, so a model file is the only download, and it comes from inside the editor.
  • Sized to your machine. Setup detects your hardware and marks the models that will run well on it. The browser sorts by VRAM and context so you can find the largest one that fits.
  • GPU where we ship one. Metal on Apple Silicon and Vulkan on Windows; Intel Macs and Linux run on the CPU. Override with Onyx: Select AI Processor, /processor, or onyxcode.ai.inferenceBackend.
  • Separate slots per job. Chat, autocomplete, Onyx Tab and embeddings each get their own model rather than sharing one.
  • An engine that keeps up. From 2.3.0 the bundled llama.cpp engine updates itself between releases, tested on your current model first and rolled back automatically if it misbehaves, so new model families load without waiting for an app update. Control it with onyxcode.ai.engineUpdates.

Running local models covers all of this in full: choosing a size for your memory, quantisation, using GGUF files you already have, comparing models with /compare, and connecting an external server.

Codebase indexing and RAG

Onyx indexes your workspace into a local vector store so chat retrieves the relevant code without you naming the file. The index and the embedding model both stay on your machine.

  • On each turn your message is embedded locally and the five most similar blocks join the prompt. /workspace <query> widens that to fifteen.
  • A workspace primer gives the model the shape of the project. Inspect or refresh it with /primer.
  • Kept current by watch mode, persisted across restarts, rebuilt with /reindex or wiped with /reindex-clear.

Codebase indexing and retrieval covers the retrieval budget, the primer, and when changing the embedding model is worth the rebuild.

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.

ONYX.md
# 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). Up to 4,096 characters are sent (comments left out), as for every rules file. If Onyx finds a .cursorrules instead, it loads that file unchanged so existing Cursor users get zero-friction parity.

.onyxrules
# 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 !patternto negate. As in gitignore, a pattern with a slash at its start or in its middle matches from the project's root (/private.md is the file at the root, /infra/private/ that folder), and one without matches the name in any folder (private.md anywhere). On macOS and Windows a pattern matches whatever the case of the name, so .ENV is .env. What it keeps out is listed under Privacy and security.

.onyxnoai
# 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

# Only the file at the root, not one of the same name in a subfolder
/private.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.

.onyxignore
# 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. The first file with rules in it wins: a file holding only headings and comments, such as an untouched template, is skipped. Up to 4,096 characters are sent by default (onyxcode.chat.instructionsMaxBytes), after comments are left out and secrets redacted. The configured path must stay inside the workspace.

/init - scaffold all four files

Running /init from chat scaffolds the four files above in one pass. Existing files are left untouched, including one you create while the AI draft is written. The templates keep their examples inside comments, so nothing reaches the model until you write rules of your own. 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 mode picker chooses how much autonomy the AI has. The pill beside the model selector shows the current one, and /plan, /ask, /edit and /auto switch it. Ask and Edit are on Free; Plan and Auto are Pro.

  • Plan is read-only by design. Ask, the default, confirms every write and command. Edit creates new files itself, stages a change to an existing file for your Keep, and still confirms commands. Auto runs unattended.
  • Auto only runs inside a git worktree, so unattended work happens on a copy of your branch and you review a diff.
  • You decide what is written.Plan writes nothing. Ask and Edit stage every change to an existing file for your Keep (Edit creates new files straight away). Auto writes through its tools, but a code block's change to an existing file still waits for your Keep, and an edit to a file that already has a change waiting for your review joins that change and waits too.
  • Rule files always wait for your Keep. A change to .onyxnoai, a permissions file, .vscode/*.json, a .code-workspace file or .cursor/mcp.json waits for your Keep in every mode that writes, and Keep All leaves it for its own Keep.
  • Deny always beats allow. .onyxnoai and the built-in secret patterns are vetoed even in Auto and even with approvals bypassed.

Agent mode and permissions covers the worktree, the tool loop, and the full .onyx/permissions.json grammar.

MCP support

Model Context Protocol servers are subprocesses exposing tools the agent can call. Onyx ships a curated pack and supports your own. Open the panel with /mcp.

  • Chat calls their tools. Ask about the service a running server connects and chat calls its tool. A tool the server does not mark as read-only asks first, in every mode, and a call that names a file you keep from AI is never run.
  • Four bundled servers, one click each: filesystem, git, sqlite and fetch. Available on Free, which runs one MCP server at a time (the one you start); Pro runs them all at once.
  • Air-Gap Mode is enforced, not advised. An HTTP server that is not on this machine is stopped as it starts; loopback transports are allowed. Stdio servers are allowed too and do their own networking, which Air-Gap does not filter.
  • OAuth serversuse VS Code’s own handshake, so a server your team already uses works unchanged.

MCP servers covers the bundled pack, custom and OAuth servers, and how MCP tools fit the permission model.

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

bash
/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 one

readMemory 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 an existing file, Onyx stages it as a pending change: nothing on disk moves until you Keep it. In Edit and Auto mode a code block for a new file is created straight away, and Auto's own edit tools write inside its worktree.

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.

Files chat creates and edits

Besides code blocks in its reply, chat changes files with two tools: one writes a file's complete contents, the other replaces exact lines in an existing file. The agent mode decides what is written and what waits for your Keep (see Agent mode).

  • No placeholders for your code. An edit that would put a line such as // ... existing code ... or return null; // unchanged where your code was changes nothing, in any mode, and chat is asked for the real code.
  • Files arrive whole. A README with example code, HTML, XML and Vue templates, and code under a numbered step reach disk exactly as the model wrote them, with their indentation and final line break.
  • A file chat just created can be edited in the same reply; reading it shows the version waiting for your review.
  • An edit that can't apply is not retried. Chat is told it would fail the same way and has to try something else, such as reading the file first.
  • A write that did not go through is named. When a reply describes a change that never reached disk, a note under it says so plainly.

Partial code blocks

A code block that restates only part of a file (one function, one CSS rule, one YAML key) is placed only where the file leaves no doubt, and only ever changes or adds lines: it never deletes the code around it. When Smart Apply can't tell where the code goes, nothing is staged and a notice says why, offering Review as Whole File when the block could be the whole file. A block that stands in for code with a comment such as // ... existing code ...is never staged. When a block removes lines, as in “remove the debug log”, Review Removal stages it and opens the review, so you see every line that goes before you Keep.

Keep, Discard and Revert

  • Two changes to one file make one change: Keep writes all of it.
  • A new file's review compares it with an empty file, so you can read it before you Keep it.
  • One click to the change.In the grey steps above a reply, a line that names a file chat proposed or wrote (“Proposed src/app.test.ts”) opens its side-by-side review while it waits for your Keep, and the file once it is written.
  • Revert restores the exact bytes the Keep replaced, byte order mark and line endings included, even after chat proposes another change to the file.
  • Files that aren't UTF-8 text (another encoding, or binary) are never changed from chat, and chat says why.

Keyboard shortcuts and status glyphs

  • Cmd+Shift+Enter / Ctrl+Shift+Enter keeps every pending change except a change to a rule file (.onyxnoai, a permissions file, a .vscode/*.json file, .cursor/mcp.json, a .code-workspace file): those wait, and the notice gives each one a Keep button of its own.
  • Cmd+Shift+Backspace / Ctrl+Shift+Backspace discards 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.

markdown
```typescript:src/foo.ts
export function foo() {}
```

Keep writes the code block you see, tabs and tags included. A block chat only shows as text (inside a quote, cut off, or inside an HTML block such as <details>) is not offered as a file, and a block with no file name is offered only for a file chat may write, never one .onyxnoai protects.

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.

Surface:a yellow chip below the message (“Reply trimmed because the model started repeating itself”) with a primary Switch to a 7B+ model action that opens the Browse Models tab, plus a secondary Show what was trimmed toggle.

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 Onyx Code's own outbound network traffic. AI requests, model downloads, the marketplace, auto-update, engine updates, external server probes, the built-in browser and HTTP MCP servers all fail closed. Localhost and the external model server you configured stay available, so the bundled inference engine works. Only localhost, ::1, a literal 127.x.x.x address and that server count as local; a host name that only looks local, such as 127.0.0.1.nip.io, is blocked like any other. Extensions (including the built-in Git and npm extensions), the integrated terminal and tasks, and stdio MCP servers run their own networking and are not blocked, so on a machine that must never reach the network, block it at the operating system or firewall too.

  • 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.

  1. In-app gatedFetch wraps every outbound call from Onyx code paths (HuggingFace browser, model downloads, local AI client, external context probe, embedding service, MCP gallery, auto-update). Calls throw AirGapBlockedError before the network stack is touched.
  2. 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 on McpHTTPHandle, so any future MCP transport subclass that forgets to wire it up is a compile-time TypeScript error - not a silent privacy leak.
  3. Electron session.webRequest.onBeforeRequest aborts any non-loopback HTTP/HTTPS/WS/WSS request from the app's windows and the built-in browser that slips past the first two layers and logs it to main.log as [Air-Gap] Blocked outbound request: .... Note: 0.0.0.0 is nottreated as loopback (it's a wildcard bind address that routes to LAN interfaces on Linux/macOS), so SSRF attempts via crafted MCP URLs to http://0.0.0.0:<port>/ are correctly blocked.

Verify Air-Gap (try this yourself)

bash
# 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. While AI is off, or no chat model is active, chat says why before anything happens and your message stays in the input box, so nothing is sent later without you.

What .onyxnoai keeps out

Besides the files you attach, chat sends some context on its own: your uncommitted changes, a short project overview, your rules and memory, related code it found, the file open in the editor and, in whole-codebase mode, the whole project. All of it leaves out the files .onyxnoai excludes, and secrets in it are replaced with a placeholder before anything is sent.

  • Attachments: a file .onyxnoai excludes is refused when you attach it, with a notice that says why. Outside your workspace, the built-in protection refuses anything in .ssh or .aws, .env files, keys and anything in a secrets or credentials folder, while ordinary files still attach.
  • Symbolic links:a linked file, or a file in a linked folder of your project, is not attached, not read as context, and never written through, so a link can't bring in or change a file from elsewhere on your computer.
  • Autocomplete and Onyx Tab leave excluded files out of the context they read from your other open files.

Where chat sends your code

The external model server and the active model are set only in your own user settings or the AI Settings panel, never by a project's .vscode/settings.json, so a repository you open cannot point chat at a server of its choosing.

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. Every way of sending gets the same check: a typed message, a quick-action chip, Generate Tests (the selected code too), /workspace and /compare. The context chat adds on its own is redacted silently, with the same patterns, since you never see it before it is sent. The high-entropy fallback reads an ID in a link as an ID: a link whose only random part is a GUID, such as each Azure DevOps project's URL in what an MCP server returns, reaches the model whole, and a key beside it is still redacted.

settings.json
{
  "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):

text
The token is <REDACTED:github-pat>. Why does the OAuth flow fail?

A folder you haven't trusted can't change these settings in its own .vscode/settings.json, so a repository you clone can't turn the scan down. Your own settings apply until you trust it.

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).
2026-05.jsonl (one event per line)
{"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):

text
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 Code

freeform format (no type/scope, no enforced subject prefix):

text
Persist the loop-trim original on the message so the chip's "Show what
was trimmed" toggle survives a session reload.

Drafted with Onyx Code

The 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.

PillWhenClick
AIR-GAPPEDonyx.privacy.airGapMode is on.Opens Privacy settings.
AI: off / AI: limitedWorkspace AI kill switch on, or .onyxnoai patterns active.Opens Privacy settings.
Index statusonyxcode.index.enabled is on.States: scanning, indexing N%, indexed N blocks, failed.
Model downloadAny model download in flight.Opens AI Settings → Browse Models with the active download highlighted.
AI statusAlways 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 TabAlways (or hidden if next-edit prediction is disabled).Opens Browse Models. Two states: ready (Zeta-2 installed) or (Get) (not installed).

Slash commands

Typed into the chat input. They switch agent mode (/plan, /ask, /edit, /auto), control the model and processor (/processor, /compare), manage the index (/reindex, /workspace, /primer) and manage MCP servers (/mcp), among others.

Commands and shortcuts is the full reference: every slash command, every Command Palette entry, and the default key bindings.

Command Palette reference

Everything Onyx contributes to the Command Palette, all prefixed Onyx: so typing that shows the lot.

The full table is in Commands and shortcuts.

Keyboard shortcuts

Onyx adds a small number of bindings on top of the VS Code defaults, and all of them can be rebound in Preferences, Keyboard Shortcuts.

The macOS and Windows or Linux table is in Commands and shortcuts.

Settings reference

Every Onyx setting lives under the onyxcode namespace in normal VS Code settings, so it can be set per user or per workspace and committed like any other editor setting.

Settings reference lists all of them with their defaults, grouped into privacy, AI and the local engine, chat, the agent, autocomplete, the codebase index and git helpers.

Files and folders Onyx writes

PathScopePurpose
~/.onyxcode/models/userDownloaded GGUF chat / draft / embedding models.
~/.onyxcode/activity-log/<YYYY-MM>.jsonluserAudit log; one event per line.
~/.onyxcode/memory/<workspace-hash>/userProject-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.mdworkspaceProject overview.
<workspace>/.onyxrulesworkspaceProject rules.
<workspace>/.onyxnoaiworkspacePrivacy excludes.
<workspace>/.onyx/instructions.mdworkspaceExtended instructions.
<workspace>/.onyx/permissions.jsonworkspace (committed)Team-wide AI approval rules (allow / deny patterns).
<workspace>/.onyx/permissions.local.jsonworkspace (gitignored)Per-machine overrides; auto-appended to .gitignore on first write.
<workspace>/.vscode/settings.jsonworkspaceWhen workspaceAiDisabled is set, persists there.
<workspace>/.onyx-agents/workspaceWorktrees for agent runs; removed once the last one is applied or discarded.
<repo>/.git/info/excludeworkspace (never committed)One .onyx-agents/ line, so agent worktrees stay out of git status.

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- blocks Onyx Code's own outbound traffic for users on regulated networks. When on, only localhost and your configured external model server are reachable from Onyx Code.
  • 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).