v2.16.0

Released July 25, 2026 · View on GitHub →

@mentions inline file context — type @src/file.ts anywhere in your message and the file's contents are attached to that message. No more /add + /drop dance for one-off file references.

Added

new default), kimi-k3-code-highspeed, and kimi-k3-thinking, on the international and China endpoints. K3 carries a 1M context window (vs 256K on K2.x) and the thinking variant returns explicit reasoning traces; both K3 code models are in the sampling-params guard since they fix temperature internally. The tokenTracker context and pricing tables list all three, so the context gauge and cost readout are right — without the entries they fell back to a 128K window, which would have shown the gauge as nearly full at ~1/8 of the real budget and triggered compaction far too early. Pricing follows the Kimi family rate ($0.60/$2.50 per MTok); adjust if Moonshot publishes a different K3 rate.

becomes the default. Same $5/$25 per-MTok pricing and 1M context, with the full lowmax effort ladder. The reasoning-effort gate, the sampling-parameter guard, and the tokenTracker context/pricing tables were all updated in lockstep, so /thinking and the cost readout are correct for it. (Opus 4.8 still routes correctly if a saved session pins it.)

anywhere in your message and its contents are loaded as an [Attached files] block for that message only — no need to /add and remember to /drop afterwards. Works alongside the existing /add (persistent) and pinned-files (Mac) mechanisms. - Forms: @src/file.ts (relative to project root), @./local.ts (relative to cwd), @/abs/path (absolute), @~/path (home), @"file with space.ts" / @'...' (quoted). - GitHub handles (@octocat) and emails (user@host) are left untouched — only paths containing /, ., _, or - are treated as mentions. - Files over 100 KB are skipped with a warning (same cap as /add); binaries (NUL-byte detection) are rejected. - Failures surface inline (@missing.ts: file not found) without aborting the message — the agent still sees the rest. - CLI: src/utils/mentions.ts (+36 tests) — pure parser, integrated into handleSubmit in main.ts. - Mac: CodeepCore/Agent/MentionExpander.swift (+14 tests) — byte-for-byte parity with the CLI, integrated into ChatView.send(agent:).

opens a file picker below the input — arrow keys navigate, Tab inserts the selected path. Skips node_modules, .git, binaries. Cached per-root (5 s TTL) so keystrokes stay snappy on large repos. - detectMentionQuery in components/Autocomplete.ts (+11 tests) tracks the cursor inside an in-progress mention. - suggestMentions in utils/mentions.ts powers the picker; the /command and @mention pickers never compete (one opens at a time depending on cursor position).

@web https://example.com/docs (or @web example.com/docs) and the page is fetched, converted to readable text, and attached to the message — same [Web pages] block shape as file mentions. - Forms: full URLs (@web https://…, @web http://…) and bare hosts (@web docs.example.com/api, auto-https://). - HTML is stripped to text (scripts/styles removed, links kept as text (url)); plain-text and JSON responses pass through as-is. - Output capped at 32 KB; 12 s fetch timeout; binary/PDF content types rejected with a clear reason. - CLI: src/utils/webFetch.ts (+33 tests), integrated into handleSubmit in main.ts. - Mac: CodeepCore/Agent/WebMentionExpander.swift (+14 tests), integrated into ChatView.send(agent:) (now async).

@folder src/components (or @dir …) and every source file under the directory is loaded recursively into a single [Attached files] block, merged with @file mentions. Same ignore rules as the autocomplete scanner (node_modules, .git, binary extensions, dotfiles). 200 KB total cap per mention, 6-level depth limit, deduplicated across overlapping folders. Quoted paths supported: @folder "my dir". - CLI: expandFolderMentions + expandFileAndFolderMentions (merged single-block output) in utils/mentions.ts (+21 tests); main.ts now calls the combined expander. - Mac: CodeepCore/Agent/FolderMentionExpander.swift (+13 tests), wired into ChatView.send ahead of @file/@web.

supports applying a subset of a file diff's hunks, leaving rejected hunks' original lines intact (git add -p-style granularity). - CLI: applyHunks / applyHunksToFiles / countChangeHunks in utils/diffPreview.ts (+17 tests). /apply now shows per-file hunk counts and accepts --only file.ts:0,1 other.ts:2 to apply only the chosen hunks. Without --only the original all-or-nothing behavior is unchanged. - Mac: CodeepCore/Agent/HunkApplier.swift (+11 tests) — same algorithm, Swift-native FileDiff/DiffHunk/DiffLine types. (UI integration — SwiftUI hunk-picker modal — to follow.)

injects git diffs, commit patches, and file-at-ref content into the prompt as a [Git ref] block — same UX family as @folder/@file/ @web. Supported forms: @git diff, @git diff --staged (or staged), @git HEAD / @, @git <sha>, @git main:src/x.ts (file at ref), @git diff a..b (range), or any quoted ref (@git "diff HEAD~3"). Capped at 64 KB/mention (truncated with a marker); unknown refs surface a friendly failure note. - CLI: getGitContent in utils/git.ts (+12 tests), expandGitMentions/extractGitMentions in utils/mentions.ts (+11 tests), wired into main.ts between @file/@folder and @web. - Mac: CodeepCore/Agent/GitMentionExpander.swift (+10 tests), wired into ChatView.send in the same order.

review modal walks you through each change hunk one at a time. Keys: y/Enter accept, n skip, a accept all remaining, q/Esc quit, /↓ navigate. The chosen hunks are applied via the existing per-hunk apply pipeline. Reuses the modal/state plumbing of the inline showConfirm dialog. CLI only (Mac UI modal to follow).

cached for 30 minutes (per session, max 50 entries, LRU eviction) so a second @web for the same URL is instant and free. Failures are never cached. New /web-cache command (alias /webcache) shows stats and /web-cache clear resets. URL keys are normalized (lowercased host, trailing slash stripped, fragment dropped) so example.com/path and https://example.com/path/ share an entry.

(src/acp/session.ts) now expands @file/@folder/@git/@web mentions the same way the TUI does — previously ACP sent the raw prompt with no inline-context resolution. Failures surface as thoughts in the editor. (+2 smoke tests in session.test.ts.)

via the registry's resolveCommand before dispatching, so e.g. /webcache reaches the web-cache handler without a duplicate case label.

is the Mac counterpart to the CLI's /apply --interactive: walks the user through each change hunk, toggling accept/skip, with keyboard shortcuts (y accept, a accept all, arrows navigate). Built on the existing HunkApplier.FileDiff. (+6 unit tests for the pure items(from:) builder + header formatting.)

caches successful fetches for 30 min (per session, max 50 entries, LRU) — full parity with the CLI's webCache. Failures are not cached. URL keys are normalized (lowercased host, trailing slash stripped, fragment dropped). New public API: clearCache(), cacheStats(). (+5 Swift tests.)

with an image on the pasteboard (alongside the existing file picker attach). Images are downscaled + JPEG-compressed through the same ImageResize pipeline, gated by supportsVision.

write_file confirmation prompts now offer a "Review hunks" button that opens HunkPickerSheet over the call's diff. New HunkApplier.diffFromEditCall / diffFromWriteCall builders derive a FileDiff from tool-call arguments. (+5 Swift tests.)

/web-cache shows session cache stats, /web-cache clear wipes it. Aliases: /webcache, reset, flush. (+6 Swift tests.)

onto the input bar attaches it (same resize/JPEG pipeline as paste and the file picker), with a brand-tinted drop affordance ring.

breakdown popover from the composer — parity with the CLI's /usage. Aliases: /stats, /cost. (+2 Swift tests.)

and an agent finishes a turn, the conversation's unread counter bumps and the dock icon shows the total. Clicking the app to bring it frontmost, or selecting the conversation, clears its badge. Conversation.unreadCount is session-only (never persisted — no phantom badges across launches). (+3 Swift tests.)

composer opens a filtered list of commands; ↑/↓ navigate, Tab/Return accept, Escape closes. New SlashCommandHandler.catalog + pure suggestions(for:) filter (boundary-aware — ignores / inside URLs, suppresses after a space when the user is in the argument). (+10 Swift tests.)

the menu bar (Scan, Plan Mode, Show Usage, Show/Clear Web Cache, New Chat) with shortcuts. Wired through a new .codeepRunSlashCommand notification so menu items reuse the composer's dispatch path.

Shortcuts + Siri phrases for "Codeep Plan Mode", "Show Usage", "Clear Web Cache". Reuses a new .slashCommand(raw:) case on PendingIntentAction so intents route through the same slash dispatch as typing the command. (+3 CodeepCore tests.)

Form is now four focused tabs — General (appearance, accent, response language, system prompt, About Me), Model & Agent (confirmation, self-verify, model parameters, limits, hooks), Providers (API keys, endpoints, Ollama, OpenRouter), and Tools & Privacy (privacy/cloud, tool permissions, MCP, skills). Active tab persists across sheet re-opens.

(⌘?) opens a catalog of every shortcut in the app, grouped by surface (App, Conversations, Composer, Chat & tools, Slash commands). Static ShortcutCategory catalog is the single source of truth. (+5 Swift tests.)

pick from 9 preset colors (Codeep Red default + Orange, Amber, Green, Teal, Blue, Indigo, Purple, Pink). Applies live to .tint() across the whole app via a reactive @AppStorage. New AccentChoice enum. (+7 Swift tests.)

horizontally-scrolling strip of pinned one-click starters (seeded with sensible defaults on first launch). Right-click to remove; a "Pin" button appears when there's draft text to save. New QuickPromptStore (UserDefaults-backed, @Observable) + pin sheet. (+14 Swift tests.)

Security

into a string run through /bin/sh, so prompt text containing @git HEAD; <command> ran that command — reachable from anything pasted into a prompt (an issue body, a log, model output routed over ACP). git is now spawned via argv with no shell, and refs are validated; @git diff flags are allow-listed so a ref can't be smuggled in as --output=… either.

*.pem, id_rsa and friends are refused with a pointer to /add, so a pasted mention can't ship credentials to the provider.

that redirects to loopback/RFC1918/link-local (including the cloud-metadata endpoint) is refused. Directly typing @web http://localhost:3000 still works — that's the documented dev-server case. The fetch timeout now covers the response body (a slow-drip reply could hang the chat forever), the body is read with a hard byte cap instead of being buffered whole, and the timer can no longer leak on failure.

Fixed

from the layout snapshot entirely, so the bottom panel measured zero rows while the picker still painted up to eleven — straight over the end of the transcript.

no file cap and a statSync per entry, so opening the picker in a large monorepo blocked the render loop for seconds. Capped at 20k entries and switched to readdirSync(withFileTypes), which drops a syscall per file.

a bare @~foo/bar.ts used to become $HOME/oo/bar.ts and report a confusing "file not found".

Unified-diff context overlaps between adjacent hunks; the applier replayed each hunk in sequence, so shared context lines were written twice — and with a small gap a later hunk's deletion landed inside an earlier hunk's context and was silently dropped. Rebuilt as a per-line union, with a regression test sweeping the hunk gap.

branch fell through to the apply-all path, doing the opposite of what was asked. It now reports the bad spec and applies nothing.

no longer a mention and the file was never attached — the picker broke the feature it exists to serve. The picker's boundary rule is now shared with the expander so the two can't drift apart again.

each mention: the merged file+folder path stripped its own attachment block back out with a lazy regex that removed only the header.

Math.min over the hunk's line numbers blew the argument limit and surfaced as an unhandled rejection. The apply paths also report failures as a toast instead of dying.

Downloads

Install with npm install -g codeep@2.16.0 or brew install vladoivankovic/codeep/codeep.