Everything recovered from reading the published command-code npm package: the taste subsystem
end to end, every system prompt, the tool catalogue, the wire protocol, the model catalogue, and
the telemetry.
Read as shipped on 19 September 2026, pinned to one version. Later releases may differ.
| package | command-code@1.58.0 |
| file | dist/cli.mjs , 2,635,431 bytes |
| sha256 | aab2bec800371953112d18472bb7383992ef264cca22558bdcda77e7d0dc0f14 |
Line numbers below refer to dist/cli.mjs after npx prettier --parser babel, which produces
115,067 lines. See reproducing this.
taste-1is marketed as a "meta neuro-symbolic AI model with continuous reinforcement learning." No such model exists in the package. Taste is a prompt sent to whichever ordinary model you have selected, and the output is a markdown file that gets prepended to later prompts.- Taste feeds on three sources: your git history, your live conversation, and your saved transcripts from Claude Code, Codex and Cursor.
- The git path mines up to 200 commits and applies no secret-filename filter, although the package ships one and uses it in six other places. See below .
- Taste learning defaults to on.
- The in-product privacy text says taste "stores learning data in your project and on your local machine only." Storage is local. Processing happens on the vendor's servers and your code is uploaded to reach it.
From commandcode.ai/docs/taste, archived 2026-09-07, 2026-03-13, 2025-12-09:
Taste is powered by our meta neuro-symbolic AI model taste-1 with continuous reinforcement learning (RL). We combine reasoning with neural intuition to create an invisible architecture of your choices, structures, patterns and tooling preferences.
Bullets on the same page: "Meta Neuro-Symbolic AI model taste-1 enforces the invisible logic of
your choices" and "Reflective Context Engineering of a self-aware RL feedback loop to build
skills." The page embeds an architecture diagram at /docs/mns.png whose alt text is
meta neuro-symbolic ai model taste-1.
The string taste-1 occurs five times in the shipped bundle, across four locations:
| Location | Line | Kind |
|---|---|---|
| FAQ string (twice in one string) | 9371 | marketing copy |
/taste help text |
64741 | marketing copy |
| billing text | 64749 | pricing label |
| TUI status bar | 97801 | UI string literal |
There is no model ID, routing entry or catalogue record named taste-1. The same bundle carries
about eighty real model IDs with context windows and provider routing. The runtime occurrence is:
y = Boolean(o && byokProviderId({ model: o })) ? "" : " · taste-1",
The badge is appended when you are not using your own API key. Supply your own provider key and it disappears while taste behaves identically.
The billing text at line 64749 reads: "Premium requests: Any request that uses a premium model (like taste-1) during your coding session." Calling it a premium model is what sets the rate.
runTasteLearningAgent (55352), extractAllSignals (55392), compileTasteContext (55686).
git show --format= -U3 --diff-algorithm=histogram -b --ignore-blank-lines -M <hash>
Caps recovered from the constants:
| Constant | Value | Meaning |
|---|---|---|
maxCommits |
200 | commits cloned and scanned |
Bx |
50 | maximum signals extracted |
Wx |
50 | maximum commits with usable diffs |
Hx |
10 | commit batch size |
Gx |
5 | diff concurrency |
Vx |
5 | grouped patterns kept per commit |
zx |
200 | maximum lines per side of a hunk |
Jx /Yx |
3 / 5 | snippet line budget |
Each surviving hunk goes through buildSnippet2 (55612), which emits your source verbatim:
Snippet:
<context line, indented two spaces>
→ <changed line, verbatim>
<context line, indented two spaces>
compileTasteContext concatenates these under two headings, quoted verbatim:
## Correction Diffs — What Wrong→Right Looks Like
It appends the instruction block quoted below and posts the result to
https://api.commandcode.ai/alpha/generate.
It also accepts a GitHub URL or owner/repo and will git clone --depth 200 --single-branch a
public repository to mine it.
The package ships a sensitive-filename denylist (68900):
.env .env.* *.pem *.key *.crt .npmrc .pypirc .netrc
id_rsa id_rsa.* id_ed25519 id_ed25519.* id_ecdsa id_ecdsa.*
credentials credentials.*
hasSensitiveBasename() consumes that list at six call sites:
| Line | Call site |
|---|---|
| 17640 | isGuardedWritePath , tool write guarding |
| 17728 | path-safety set |
| 17773 | path-safety check |
| 74588 | telemetry file list filter |
| 74600 | IDE active-file filter |
| 74606 | IDE file list filter |
The taste extractor is not among them. The only filter applied while mining diffs is
isNoiseFile (called once, at 55556; list at 77172):
package-lock.json pnpm-lock.yaml yarn.lock CHANGELOG.*
.versionbot/ *.min.js *.min.css dist/ *.map
That is a relevance filter, which excludes lockfiles and build output because they make poor style signals. It excludes no secret-bearing filename.
Two details make this worse than a missing check on the working tree:
- Taste reads history, not HEAD. It runs
git showacross up to 200 commits. A.envor private key that was committed once and deleted later is still inside that range. Removing a secret from the current tree does not remove it from what taste reads. .gitignoreis irrelevant here. Ignoring a file today does nothing about the commit that added it before it was ignored, which is the common way secrets enter a repository at all.
So a repository that ever committed a .env, *.pem, id_rsa or credentials file will have
those hunks extracted verbatim by buildSnippet2 and uploaded to api.commandcode.ai with
everything else, on a feature that is enabled by default.
The filter is applied to six paths and missing from the one path that ships historical file contents off the machine.
createLearner / runLearningLoop (72820 onward), system prompt mS at 72872.
Your conversation messages are JSON-serialized and sent to the model:
`Current taste structure:\n${m}\n\n` +
`Previously analyzed conversation (context only — already processed in earlier passes, ` +
`do NOT learn from it again):\n${JSON.stringify(k, null, 2)}\n\n` +
`NEW messages to analyze (learn ONLY from these):\n${JSON.stringify(C, null, 2)}`
stripInjectedMetaForLearning and stripReasoningPartsForLearning remove injected metadata and
reasoning blocks first. The loop runs up to dS = 20 model turns, with a window of uS = 20
messages, calling read_taste_file, write_taste_file and edit_taste_file to write results.
The model reaches this path through the taste tool, described to the model at 20801 as:
Record or update the user's coding preferences and taste. Use this whenever the user states a preference or asks you to remember something.
The base system prompt instructs the model to call it (73838):
TO RECORD OR UPDATE A PREFERENCE, USE THE taste TOOL: When the user states a preference or
asks you to remember/save something ("prefer X over Y", "always do Z", "save this to my taste"),
call the taste tool with the instruction in the user's words.
The model decides when your conversation gets mined during a normal session.
createSessionImporter (40333), agent table uC:
[ { agent: "claude-code", find: findClaudeCodeSessions, extract: extractClaudeCodePrompts },
{ agent: "codex", find: findCodexSessions, extract: extractCodexPrompts },
{ agent: "cursor", find: findCursorSessions, extract: extractCursorPrompts } ]
Locations read from disk:
| Agent | Path |
|---|---|
| Claude Code | ~/.claude/projects/<encoded-project-dir>/*.jsonl |
| Codex | ~/.codex/sessions/** rollout files |
| Cursor | Cursor transcripts directory, <id>/<id>.jsonl |
extractClaudeCodePrompts pulls every entry with type === "user" and a string
message.content, which is your prompt text. The same shape applies to the Codex and Cursor
extractors. The prompts are batched by splitPromptsIntoLearnBatches and each batch is sent
through learn() to /alpha/generate.
The UI string for this, at 64521, is:
Learn taste from sessions with other coding agents (Claude Code, Cursor, etc)
and at 86541:
Learn from your previous sessions - updates your taste profile
Command Code reads your saved conversations with competing coding agents and uploads them to its own API.
| Location | Contents |
|---|---|
.commandcode/taste/taste.md |
project taste, category headings, bullets with confidence scores |
.commandcode/taste/<category>/taste.md |
a category once it exceeds 5 learnings |
~/.commandcode/taste/ |
global taste, -g flag |
commandcode.ai/<username>/taste |
remote taste packages, npx taste push |
Remote package upload is a multipart POST built by prepareUpload (56570), with fields name,
description, type, isPublic, overwrite and file parts files[taste.md] and
files[<category>/taste.md]. Endpoints: /beta/taste/packages/:namespace and
/alpha/taste/:projectSlug.
Taste reaches the model through the system prompt rather than the request body. The taste field
in the /alpha/generate body is always null on the model-client path; the content is injected by
renderTasteSection2 into the cached system section instead.
getTasteLearningSettings (19650 onward):
const s = n.tasteLearning ?? !0, // global default: ON
i = resolveProjectOverride(r, o),
a = i?.value;
return { global: s, project: a, effective: a ?? s };
Taste learning is on unless turned off. Controls:
| Control | Effect |
|---|---|
/taste in session, orcmd taste disable |
toggle taste learning |
tasteLearning: false in~/.commandcode/config.json |
global off |
| project shared or local settings | per-project override |
DO_NOT_TRACK=1 |
disables telemetry and fingerprinting, not taste |
CMD_ZDR |
zero data retention header, s title generation and taste onboarding |
The onboarding scan is gated behind checkOnboardingConditions and presents a banner with a skip
option, so the transcript import is offered rather than silent. Taking no action leaves it
enabled.
Line 55706. ${a} interpolates for <author> when an author is targeted.
## Instructions for Taste Learning
You are analyzing code change patterns from a real repository${a}. Based on the correction diffs above, generate deeply personal and opinionated coding taste.
**Critical guidelines:**
1. **Be specific, not generic.** Instead of "Use TypeScript", write "Use branded types for IDs and explicit return types on every function. Prefer `readonly` arrays and objects by default."
2. **Extract the WHY from patterns.** If you see verbose names being replaced with concise ones, don't just say "use short names" — say "Prefer concise variable names that derive meaning from context rather than encoding type information."
3. **Look for recurring themes.** If multiple substitutions show the same pattern (e.g., nested if→guard clauses), that's a strong taste signal worth capturing.
4. **Make it actionable.** Every taste entry should be specific enough that another developer could follow it and produce code that looks like it belongs in this repository.
5. **Prioritize quality corrections** — these are the purest taste signals (wrong→right pairs with explicit WHY context from commit messages).
6. **Capture anti-patterns too.** If you see code being removed in refactors, note what the developer avoids: "Never nest deeper than 2 levels — flatten with early returns."
7. **Don't repeat generic tool preferences** like "Use pnpm" or "Use TypeScript" unless the substitutions show something specific about HOW they use those tools.
8. **Prioritize opinionated preferences.** The goal is taste that makes someone's code distinctly theirs — not industry best practices.
Write the taste entries to the taste.md file using the standard format with confidence scores.
Header prepended to the diffs, line 55692:
Repository: ${n}
${s}Commits analyzed: ${o}
Signals extracted: ${t.length}
This analysis was generated by examining actual code changes (diffs, substitutions, refactoring patterns) rather than static file contents. Every signal below comes from real commits.
Line 72872, used as the system parameter.
You are the taste-learning agent for Command Code. Review the NEW messages and the user's current taste files, then record DURABLE, generalizable preferences the user revealed — coding style, tooling, workflow, and communication preferences — not one-off task details.
Learn ONLY from the NEW messages. The previously analyzed conversation was already mined by earlier passes — it is provided so you can resolve references, never to be re-learned. Do NOT re-record a preference that already exists in the taste files, and do NOT raise or lower an existing learning's confidence unless the NEW messages themselves contain fresh evidence for it. Seeing the same preference again in the previously analyzed context is not evidence.
Use the tools to update taste files. A taste file path MUST be either "taste.md" (the root file) or "{category}/taste.md" (a single category folder) — never any other name or nesting:
- write_taste_file to create/replace a file.
- edit_taste_file to amend an existing file.
- read_taste_file to inspect a file before editing.
Record each learning as a markdown bullet ending in a confidence score, e.g.
- Prefers tabs over spaces. Confidence: 0.9
Only record clear, repeated, or explicitly-stated preferences. Prefer amending existing files over creating near-duplicates. When the new messages reveal nothing durable, make no tool calls and reply "no changes".
Line 73841, injected into the system prompt of every session that has taste enabled.
<taste_guidance>
IMPORTANT - Taste System (Learned Preferences):
WHAT IS TASTE:
Taste is a system of continuously learned preferences that captures how the user wants code written in this specific project. These preferences are learned automatically from past interactions and corrections, covering areas like:
- Technology choices (e.g., "Use TypeScript", "Use Commander.js for CLIs")
- Code style (e.g., "Use const instead of let", "Use object parameters for functions with 2+ params")
- Workflow patterns (e.g., "Always run tests before committing")
- Project-specific conventions
WHERE TASTE IS STORED:
All taste preferences are stored in the .commandcode/taste/ directory in the project root:
- Main file: .commandcode/taste/taste.md - Contains all learnings organized by category headings (# Category Name)
- Category files: .commandcode/taste/{category}/taste.md - When a category grows beyond 5 learnings, it's moved to its own subdirectory
HOW TASTE IS ORGANIZED:
The main taste.md file contains category sections with H1 headings (# Category Name). Each category can be in two states:
1. INLINE (≤5 learnings): Category heading followed by bullet points with learnings
Example:
- Use const instead of let for non-reassigned variables. Confidence: 0.90
- Use object parameters for functions with 2+ params. Confidence: 0.85
2. REFERENCED (>5 learnings): Category heading with a reference link to category file
Example:
See [cli/taste.md](./cli/taste.md)
WHY TASTE MATTERS:
These preferences represent the user's actual requirements learned from real interactions. When a user corrects you (e.g., "use TypeScript not JavaScript", "use Commander.js for CLIs"), that correction is captured as taste. Following taste prevents you from making the same mistakes repeatedly and ensures consistency across the project.
HOW TO USE TASTE:
1. Your learned preferences are provided in the <taste> section below
2. BEFORE starting ANY work, carefully read the taste content
3. If you see a category reference like "See [category/taste.md]", you MUST use read_file to read .commandcode/taste/{category}/taste.md to get the full preferences
4. Apply ALL relevant preferences to your work - these are REQUIREMENTS, not suggestions
5. If working on a specific domain (e.g., CLI, TypeScript, testing), check if there's a category for it and read the full preferences
6. Taste preferences override general best practices - if taste says "Use X", you use X even if you would normally prefer Y
CRITICAL RULES:
- When you see "See [cli/taste.md]" for a CLI task, IMMEDIATELY read .commandcode/taste/cli/taste.md before writing any code
- NEVER ignore taste preferences - they represent explicit user requirements
- If a taste preference conflicts with the user's current request, follow the current request (it may be updating the preference)
- The same applies to any other domain-specific category - ALWAYS read referenced taste files before starting work in that domain
- **NEVER EDIT OR WRITE TO TASTE FILES**: Do not use edit_file or write_file on any files in .commandcode/taste/ or ~/.commandcode/taste/. These files are managed automatically by the learning system. You can READ them, but never modify them.
</taste_guidance>
Line 35886, populated, and 35887, empty.
<taste>
Below is the complete content of the .commandcode/taste/taste.md file.
This shows you what preferences are available and which categories might have additional details in separate files.
If you see references like "See [category/taste.md]", you MUST read that file using read_file to get the full preferences.
--- Content of .commandcode/taste/taste.md ---
${t}
--- End of .commandcode/taste/taste.md ---
</taste>
<taste>
No preferences learned yet for this project. The .commandcode/taste/taste.md file is empty or doesn't exist yet. Preferences will be learned automatically as you work.
</taste>
Line 20801, with its one parameter at 20808.
Record or update the user's coding preferences and taste. Use this whenever the user states a preference or asks you to remember something.
The preference or taste change to record, in the user's words.
Line 64741, the text behind /taste.
Taste is powered by the meta neuro-symbolic AI model taste-1 with continuous reinforcement learning (RL). It combines reasoning with neural intuition to learn your coding preferences.
How taste works:
- Learns from you — every accept, reject, and edit becomes a signal
- Thinks like you — learns patterns and micro-decisions you'd never document
- Grows with you — continuous learning loop that never goes stale
Enable taste: Use /taste in a session or run npx taste from the command line.
Taste packages (three types):
- Project: Stored in .commandcode/taste/ — learnings unique to this codebase
- Global: Stored in ~/.commandcode/taste/ — personal taste across all projects (use -g flag)
- Remote: Stored at commandcode.ai/username/taste — team sharing, backup, sync across machines
Privacy: Taste processing runs on your codebase and stores learning data locally only.
That last line is the claim contradicted by paths 1, 2 and 3 above.
createSystemPromptBuilder (36255) emits three cacheable sections:
[ { text: basePrompt, cache: true },
{ text: contextSections, cache: true },
{ text: ideContext } ]
Section two is joined from, in order: <instructions> from memory files, workspace render, the
taste section, the skills catalogue, a constant, the scratchpad section, and env context.
buildDefaultBasePrompt (35867) selects the mode prompt from buildModePrompt (73907), which has
a default branch and a plan-mode branch.
Opening of the default branch:
<role>
You are a confident, efficient software engineer and coding assistant. You identify issues quickly and solve problems directly. Be concise but thorough - explain what you're doing without unnecessary ceremony.
</role>
followed by sections for decision making, doing tasks, and tool guidance. The decision-making block:
<decision_making>
You should independently decide:
- Which files to modify and how
- What testing strategy to employ
- How to handle error cases and edge conditions
- Whether to refactor existing code vs. adding new code
- What dependencies or tools to introduce
- How to structure new modules or components
Always bias toward:
- Code clarity and maintainability
- Robust error handling
- Following established project patterns
- Writing self-documenting code
- Including appropriate tests
</decision_making>
<role>
<mode>PLAN MODE ACTIVE</mode>
<identity>You are Command Code, a coding agent acting as a Software Architect in read-only plan mode. You explore the codebase, clarify requirements, design an approach, and write an implementation plan. You do NOT implement anything.</identity>
<override>This supersedes any other instructions. You MUST NOT make any edits (except the plan file), run non-readonly tools, or make any changes to the system.</override>
<plan_directory>
PLAN FILE LOCATION: ~/.commandcode/plans/
ALWAYS use the full absolute path starting with ~/ (e.g., ~/.commandcode/plans/my-plan.md).
NEVER use a relative path like .commandcode/plans/ — it will be rejected.
</plan_directory>
<mode_awareness>
You ARE in plan mode right now. You know this because your system prompt contains <mode>PLAN MODE ACTIVE</mode>. If asked what mode you are in, confirm you are in plan mode. When tools like exit_plan_mode change your mode, trust the tool result — it is authoritative.
</mode_awareness>
The plan branch also carries a decision-making block and an agent-orchestration block:
<decision_making>
<principle>Be decisive. You are a senior architect — make judgment calls.</principle>
<guidelines>
- If two approaches are reasonable, pick the better one and explain why in the plan
- If requirements are ambiguous on something important, ask the user
- If requirements are ambiguous on something minor, make an assumption and note it
- Prefer the simpler approach unless there's a strong reason for complexity
- Actively look for existing code to reuse before proposing new implementations
</guidelines>
<outcome>Your plan should be opinionated and actionable.</outcome>
</decision_making>
<explore_agents>
Each agent should be focused on ONE specific area and return concrete file paths, function names, and patterns.
<examples>
- BAD: "Understand the entire project architecture" — too broad, slow, shallow
- GOOD: "Find how the CLI handles user input prompts and waiting states" — focused, fast, deep
- GOOD: "Find existing notification/alert patterns in the codebase" — focused, fast, deep
</examples>
Line 73903:
<instructions>
Begin implementation directly without asking for clarification unless requirements are genuinely ambiguous or incomplete.
REMINDER: Use the todo_write tool for complex tasks that benefit from tracking and planning. This ensures proper progress tracking and transparency with the user. Always use todo_write (not TodoWrite) as the correct tool name.
</instructions>
Line 71966:
You compress a Command Code conversation into a handoff brief so a fresh assistant can pick up the work without rereading the original transcript.
38 built-in tools. builtinTools at 71076; several are registered through deferred(...), which
supplies a one-line description and fetches the full schema on demand.
| Group | Tools |
|---|---|
| Files | read_file ,write_file ,edit_file ,read_directory ,glob ,grep |
| Shell | shell_command ,run_command ,powershell ,shell_output ,shell_tasks ,kill_shell |
| Agents | agent ,task ,agent_output ,task_create ,task_update ,task_list ,task_get ,task_stop ,task_output |
| Planning | todo_write ,exit_plan_mode ,plan_review |
| Web | web_search ,web_fetch (server-side, metered) |
| Skills | activate_skill ,search_tools /tool_search |
| Taste | taste ,read_taste_file ,write_taste_file ,edit_taste_file |
| Other | vision ,ask_user_question ,monitor_command ,monitor_events ,schedule_wakeup ,cron_create ,cron_delete |
Tools serialize as {name, description, input_schema}. tool_search is renamed to search_tools
in transit by toWireToolName (37569). defangMonitorOutput wraps monitor output in an
UNTRUSTED_MONITOR_OUTPUT marker. Writes into the taste directory are denied by isTasteDirWrite.
Seven Agent Skills ship as markdown under dist/bundled/: agent-browser,
command-code-knowledge, config, design, loop, mod-builder, skill-builder.
resolveApiBaseUrl (2632), table at 62528.
| Env | URL |
|---|---|
| prod | https://api.commandcode.ai |
| staging | https://staging-api.commandcode.ai |
| local | http://localhost:9090 |
Selection: --local / --staging argv, then COMMANDCODE_API_ENV, else prod.
COMMANDCODE_API_URL overrides everything only when COMMANDCODE_SANDBOX=true, which is the
supported way to point the client at your own server.
One opaque bearer token with a user_ prefix, in ~/.commandcode/auth.json, mode 0600. The token
carries no expiry and the client performs no refresh, request signing or proof of work. Validated
against GET /alpha/whoami.
Constants at 72706.
| Header | Required |
|---|---|
Authorization: Bearer user_… |
yes |
Content-Type: application/json |
yes |
x-command-code-version |
yes on /alpha/generate |
x-cli-environment ,x-session-id ,x-project-slug ,x-taste-learning ,x-oss-primary-provider ,traceparent ,User-Agent |
no |
x-cmd-zdr: 1 whenCMD_ZDR is set |
no |
x-cmd-provider-deepseek-internal: 1 whenCMD_PROVIDER_DEEPSEEK_INTERNAL=1 |
no |
x-oauth-token /x-oauth-provider |
no |
Omitting x-command-code-version, or sending an unparseable value, returns
403 "Your Command Code CLI is out of date." Tested live: 1.58.0, 1.57.0, 1.0.0 and
99.0.0 all pass, garbage and absence both fail. The gate checks that the header is present and
version-shaped, not that it is recent.
| Endpoint | Purpose |
|---|---|
/alpha/whoami |
validate key, identity |
/alpha/generate |
inference, streaming |
/alpha/agent/generate |
sub-agent generation |
/alpha/learn |
taste learning |
/alpha/taste/:projectSlug (+/update ) |
remote taste |
/beta/taste/packages/… |
taste package registry |
/alpha/web-search ,/alpha/web-fetch |
server-side tools, metered |
/alpha/billing/credits ,/alpha/billing/subscriptions ,/alpha/usage/summary |
billing |
/alpha/fingerprint/record |
machine fingerprint |
/alpha/lifecycle-events |
telemetry |
/alpha/sandbox/start ,/alpha/sandbox/stream |
remote sandbox |
/alpha/share/{create,append,delete} |
session sharing |
Built at 37946. Every config field is required; the server returns full zod paths on a bad body.
{
"config": {
"workingDir": "/abs/path", "date": "2026-09-19", "environment": "cli",
"structure": [], "isGitRepo": false,
"currentBranch": "", "mainBranch": "", "gitStatus": "", "recentCommits": []
},
"memory": null, "taste": null, "skills": null,
"permissionMode": "standard", // standard | auto-accept | plan
"threadId": "<uuid, optional>",
"mode": "agent", // optional, enum-validated when present:
// agent|learning|custom-agent|custom-agent-create
// |title-gen|tool-desc|compact|vision
"promptCache": true,
"params": {
"model": "deepseek/deepseek-v4-pro",
"messages": [ /* Vercel AI SDK ModelMessage */ ],
"tools": [ { "name", "description", "input_schema" } ], // Anthropic shape
"system": [ { "type":"text", "text":"…",
"cache_control": {"type":"ephemeral"} } ], // Anthropic blocks
"max_tokens": 64000, "stream": true,
"temperature": 0.0, // optional
"reasoning_effort": "high" // optional
}
}
The dialect is mixed: messages follow the Vercel AI SDK, while tools and system follow
Anthropic. toWireMessages (37572) maps tool_use to {type:"tool-call", toolCallId, toolName, input}, tool_result into a separate role:"tool" message, thinking to reasoning, and images
to data: URLs.
NDJSON, one JSON object per line, with no data: prefix and no [DONE] terminator. Consumed by
consumeStream (37731).
type |
Payload |
|---|---|
text-delta |
{text} |
reasoning-start /reasoning-delta /reasoning-end |
{text} on delta |
tool-call |
{toolCallId, toolName, input, providerExecuted?} |
tool-result |
{toolCallId, toolName, output, isError?} |
provider-metadata |
{providerMetadata:{anthropic:{usage:{cache_creation:…}}}} |
finish |
{finishReason, rawFinishReason, totalUsage:{…}, systemPromptTokens} |
error |
{error: string | {message, statusCode, isRetryable}} |
abort |
none |
A stream that ends with no finish event is treated as truncated and raises a retryable 502.
rawFinishReason === "_turn" makes the client re-issue and continue.
About eighty models, all routed through /alpha/generate. Upstream routing shows in ID prefixes
such as baseten:, novita:, anthropic: and openai:. The service resells Baseten, Novita and
first-party APIs.
| Family | Examples |
|---|---|
| DeepSeek | deepseek/deepseek-v4-pro ,-v4-flash ,-v4-flash-fast ,-v4-flash-vision-exp ,-v4.1-flash |
| Moonshot | moonshotai/Kimi-K3 ,Kimi-K2.7-Code ,-Code-Highspeed ,Kimi-K2.6 ,Kimi-K2.5 |
| Z.ai | zai-org/GLM-5.3 ,GLM-5.2 ,GLM-5.2-Fast ,GLM-5.1 ,GLM-5 |
| MiniMax | MiniMaxAI/MiniMax-M3 ,-M2.7 ,-M2.5 |
| Qwen | Qwen/Qwen3.8-Max ,3.8-Flash ,3.8-27B ,3.8-Omni-Flash ,3.7-* ,3.6-* |
| OpenAI | gpt-6-astra ,gpt-5.6-{luna,sol,terra} ,gpt-5.5 ,gpt-5.4 ,gpt-5.3-codex |
| Anthropic | claude-opus-5 ,claude-sonnet-5 ,claude-fable-5 ,claude-opus-4-8/4-7/4-6 ,claude-haiku-4-5 |
google/gemini-3.8-flash down togemini-3.1-flash-lite |
|
| xAI | xai/grok-4.6 ,grok-4.5 |
| Other | meta/muse-spark-1.* ,tencent/Hy3 ,stepfun/Step-3.7-Flash ,xiaomi/mimo-v2.5 ,nvidia/nemotron-3-ultra-550b-a55b ,sakana/fugu-ultra ,thinkingmachines/inkling ,meituan/LongCat-2.0 ,poolside/laguna-s-2.1 |
Eight models carry badge: "free", most with hidden: true. All of them return
403 "the free … tier has been retired" when called.
Background requests billed to the user, on fixed models (63536):
| Feature | Model |
|---|---|
| title generation | deepseek/deepseek-v4-flash |
| compaction | deepseek/deepseek-v4.1-flash |
| tool descriptions | deepseek/deepseek-v4-flash |
| taste onboarding | deepseek/deepseek-v4-flash |
| branch summarization | deepseek/deepseek-v4-pro |
| vision | xiaomi/mimo-v2.5 |
applyPremiumCreditsFallback silently switches to moonshotai/Kimi-K2.5 when premium requests run
out, with the message "Auto switched model to Kimi K2. Plan Premium requests used."
gatherRawSignals / buildMachineFingerprint / recordCliFingerprint (44694 to 44836). Runs once
per process in the background, POST /alpha/fingerprint/record, only when an auth key exists.
Salted SHA-256 of: /etc/machine-id or /var/lib/dbus/machine-id, every MAC address, OS username,
hostname, and git email.
Plaintext: platform, arch, osRelease, cpuModel, cpuCount, memGiB, isContainer,
timezone.
A stable thumbmark derives from machine ID plus sorted MACs, falling back to hostname plus CPU
model.
The salt is a constant shipped in the package:
Fb = "command-code:device-fingerprint:v1"
function hashSignal(e) {
const t = e.trim();
if (t) return E("sha256").update(Fb).update("\0").update(t.toLowerCase()).digest("hex");
}
Because the salt is published, testing a candidate value against an observed hash costs one sha256 call. A git email is guessable and a MAC address space is enumerable, so the hashing pseudonymizes these values against a casual reader rather than against anyone holding the package.
Disable with DO_NOT_TRACK=1 or "telemetry": false in ~/.commandcode/config.json.
The published package also hardcodes (62785) three Axiom ingest tokens for the
command_code_cli_tracing dataset at https://api.axiom.co/v1/traces, and an OTLP token for
https://ingestion.claicode.com/v1/inference-events. A redaction list strips apikey, api_key,
token, secret and authorization from span attributes. The token values are in the public
package and are deliberately not reproduced here.
~/.commandcode/:
| File | Mode | Contents |
|---|---|---|
auth.json |
0600 | vendor user_ API key and user ID |
credentials.json |
0600 | BYOK provider keys and OAuth tokens |
providers.json |
0644 | custom provider declarations |
config.json |
global config, telemetry ,tasteLearning |
|
settings.json ,settings.local.json |
settings and hooks | |
mcp.json ,projects/*/mcp.json |
MCP servers | |
keybindings.json |
key rebinding | |
plans/ ,skills/ ,taste/ |
plan output, user skills, global taste | |
telemetry-install-id |
install UUID |
providers.json accepts an arbitrary baseURL in three dialects, openai-completions (default),
openai-responses and anthropic-messages, so the whole CLI runs against any endpoint with no
patching:
{ "provider": { "mine": {
"api": "openai-completions",
"baseURL": "http://localhost:8080/v1",
"apiKey": "$MY_KEY",
"models": { "some-model": { "contextWindow": 200000 } } } } }
The parser rejects literal secrets in providers.json and accepts only "$ENV_VAR",
"{env:VAR}" or "!command" references. npm: provider packages are not loaded.
npm pack command-code@1.58.0
curl -s https://unpkg.com/command-code@1.58.0/dist/cli.mjs | shasum -a 256
npx prettier --parser babel cli.mjs > cli.pretty.mjs # 115,067 lines
Greps that land on the claims above:
grep -n 'taste-1' cli.pretty.mjs # 4 locations, 0 model ids
grep -n 'runTasteLearningAgent' cli.pretty.mjs # git history path
grep -n 'Instructions for Taste Learning' cli.pretty.mjs # the mining prompt
grep -n 'taste-learning agent for Command Code' cli.pretty.mjs # conversation path
grep -n 'findClaudeCodeSessions\|findCodexSessions\|findCursorSessions' cli.pretty.mjs
grep -n 'hasSensitiveBasename' cli.pretty.mjs # 6 sites, none in taste
grep -n 'isNoiseFile' cli.pretty.mjs # the only taste filter
grep -n 'tasteLearning ?? !0' cli.pretty.mjs # default on
grep -n 'buildMachineFingerprint' cli.pretty.mjs
Quotations from vendor material are reproduced for identification and commentary. Archive links are given so the originals can be read in full.
This documents what the package does. Whether the gap between the marketing and the implementation is deliberate is not something a bundle read can establish, so this sticks to what the code shows.
Corrections welcome. Anything here that a counter-grep contradicts gets fixed.
Shorter writeup focused on taste-1 alone:
https://gist.github.com/safzanpirani/5bd7a77ce304edb16f768982bb26bcc0