{"slug": "deepseek-v4-1-flash-on-opencode-pretty-good", "title": "DeepSeek v4.1 flash on OpenCode pretty good", "summary": "A developer tool called shev, distributed as the npm package @noorslvt/shev, turns a single pasted message into one JSON decision containing an actionable string, a take_action boolean and a confidence integer constrained to the range [34, 100], running on either DeepSeek over the network or a small ternary MLX model locally. The tool records each decision to responses.json as response1, response2 and so on, and exposes those records to other models over MCP; it installs via a curl script, npm, or cargo, and the author warns that the unscoped npm name shev belongs to an unrelated project.", "body_md": "**A simple Jev-like decision maker. Without the hype.**\n\nHand it one whole message — an email, a ticket, a review, a doc, whatever you\npasted out of the support queue — and tell it what you want done with it. It\nhands back **one** decision, as JSON:\n\n```\n{\n  \"actionable\": \"Reply to Sam and cc finance about the overdue March invoice.\",\n  \"take_action\": true,\n  \"confidence\": 95,\n  \"generated_response\": \"Hi Sam, ... (the reply, written out)\"\n}\n```\n\nThat's the whole thing. No agents. No orchestration. No prompt engineering. No five-hundred-token preamble to memorise. One message in, one decision out, in a file you can just read.\n\n- **Whole message, judged once.** It doesn't chop the thing into paragraphs and\nit doesn't go line by line. One message, one decision.\n- **You say what you want.** It asks before it answers, and what you want done\nis what drives the reply it writes.\n- **The answer has a shape.**`actionable` (a string),`take_action` (a\nboolean),`confidence` (an integer, always in`[34, 100]` ). No tuple you have\nto guess at.\n- **Runs on your Mac if you want.** DeepSeek over the network, or a small\nternary MLX model sitting right there on the machine. Switch whenever.\n- **It writes it all down.** Decisions pile up in`responses.json` as`response1` ,`response2` , … and other models can read them over MCP.\n\nOne line, copy-pasteable:\n\n```\ncurl -fsSL https://raw.githubusercontent.com/aditauqir/shev/main/install.sh | bash\n```\n\nThen type **`shev`**. The installer uses a user bin directory already on PATH\nwhere possible. Otherwise it adds a small, removable PATH block to your shell\nprofile; open a new terminal and type `shev`—no manual shell edits needed.\n\nPrefer npm?\n\n```\nnpm install -g @noorslvt/shev\nshev\n```\n\nThis installs the package **`@noorslvt/shev`**, with the terminal commands\n`shev` and `shev-cli`. The unscoped npm registry name `shev` belongs to an\nunrelated project; **do not use `npm install -g shev`** for this tool. You can\nalso install straight from the repo without the registry:\n\n```\nnpm install -g git+https://github.com/aditauqir/shev.git\n```\n\nBoth installers prefer a matching prebuilt release and otherwise build with\nRust (installing the minimal Rust toolchain if necessary). npm runs a\n`postinstall` step that fetches the right binary or builds it; macOS/Linux are\nsupported by the npm launcher, and Windows users can use WSL.\n\nRecent npm releases gate install scripts. If your install is skipped, `shev`\ntells you what to run; you can also fix it up front:\n\n```\n# if npm blocked the install scripts:\nnpm approve-scripts @noorslvt/shev   # or:\nnpm rebuild -g @noorslvt/shev --foreground-scripts\n```\n\nGot Rust already? Same thing, just as short:\n\n```\ncargo install --git https://github.com/aditauqir/shev\n```\n\nFor full cleanup, whether installed with curl or npm, close other running shev sessions first:\n\n```\nshev --uninstall --dry-run  # preview paths; delete nothing\nshev --uninstall            # confirm before removal\n# or: shev --uninstall --yes\n```\n\nThis removes registered shev binaries, its saved keys/config, local model data, tracked chat records, unchanged tracked shev MCP registrations, and the exact PATH blocks added by its installer. A full npm-backed uninstall also runs npm's package removal. Modified binaries/profile blocks, externally managed weights, host recovery backups, unrelated host settings, non-chat metadata in export files, source checkouts, and shared tools/caches (Rust, Node, uv, Codex, OpenCode) are not deleted.\n\nYou can also remove the npm package directly:\n\n```\nnpm uninstall -g @noorslvt/shev\n```\n\nThis removes the npm package and its binaries. **Modern npm does not execute\nuninstall hooks**, so it cannot also remove persistent settings/models/history\nor external MCP registrations. Use **`shev --uninstall`** for full cleanup;\nit handles the npm package removal too. Persistent npm data deliberately lives\noutside the package so a normal npm upgrade does not erase private keys,\nhistory, or model downloads. No background uninstall watchers or npm overrides\nare installed.\n\n- **Best for local use:** Apple Silicon —**M1 or newer, 16 GB of RAM and up** .\n- **8 GB** will fit the local model too, but it's tight.\n- **Everything else:** runs anywhere with a DeepSeek API key. No Mac required.\n\n<sub>Only the local model cares about the Mac. It runs on MLX, and MLX is Apple\nSilicon only, so \"run it on your machine\" means \"run it on a Mac\". Point shev at\na DeepSeek key instead and the work goes over the network — then it builds and\nruns on any platform Rust does.</sub>\n\n```\nshev\n```\n\n1. Bonsai is the default. Install it through `/model` if needed; no API key is\nrequired. DeepSeek is optional through`/model` ; its key is stored at`~/.config/shev/config.json` as`0600` .\n2. Type or paste the whole message. **enter** sends it,**ctrl+j** drops a new\nline in the middle of a multi-line one.\n3. Say what you want done with it — \"draft a short reply\", \"does this need me today\", \"where's the risk here\".\n4. Read the decision. **enter** starts the next one, or click`▸ open responses.json in Finder` and go look at the file.\n\nAfter the first run it's just: run `shev`, type, done.\n\nThe home/start screen has a white ASCII wordmark directly over the wallpaper, without a background box or JSON pane. Once a chat starts, two windows appear:\n\n- **Left, the model output.** Every decision as a clean field list. The prompt box sits flush at the\nfoot, with its mode line (\"Build · bonsai (local) · …\") on the last row.\n- **Right, this turn's JSON only.** The raw record for the decision you are on,\nso you can read the file without leaving the screen. Drag across JSON text to\nselect it; releasing the mouse copies exactly the selection and shows**✓ copied to clipboard** at the top center. The mouse wheel scrolls the JSON\nindependently.`/copy json` copies the complete record, including off-screen text.\n\nText panels use **`#0F0E08`** over the dimmed photo wallpaper. Type `/` for commands:\nPanels are inset from the terminal edges. Skills/tools menus show names only;\nlong menus scroll around the selected row instead of clipping it off-screen.\n\n| Command | What it does | \n|---|---|\n| `/file <path>` | Load a message from a file (drag-and-drop works too) | \n| `/copy [json]` | Copy selected JSON or the last response; `json` copies the complete record | \n| `/key` | Enter or replace the DeepSeek API key | \n| `/cancel` | Abort the request in flight | \n| `/clear` | Clear the visible chat and input; keep saved history | \n| `/reset` | Confirm clearing the chat, all saved history, loaded context and counters; keep keys/models | \n| `/help` | Show the keybindings | \n| `/model` | Pick the model and manage it (keys, install, uninstall) | \n| `/home` | Back to the home screen (the transcript is kept) | \n| `/history` | Jump through the decisions so far | \n| `/mcp` | Install, remove, or report the local MCP bridge | \n| `/skills` | Load existing skill guidance; `/skills off` clears supporting context | \n| `/tools [server]` | Connect to a registered MCP server and inspect read-only tools | \n| `/tool server/tool <JSON>` | Call a read-only tool and attach its result to the next decision | \n| `/plugins` | Show host-plugin compatibility limits | \n| `/quit` | Leave | \n\nHandy keys:\n\n| Key | What it does | \n|---|---|\n| `enter` | Send the message, then the intent | \n| `ctrl+j` | Newline inside the box | \n| `ctrl+t` | Switch the model (DeepSeek ↔ Bonsai) | \n| `ctrl+h` | Open the history (same as `/history` ) | \n| `ctrl+d` in history | Confirm deletion of only the selected saved entry | \n| `ctrl+y` | Copy selected JSON, or the last generated response | \n| `ctrl+c` | Quit | \n\n`/clear` starts a fresh chat view; `/history` can reopen retained records.\n`/reset` and history deletion default to **cancel** in their confirmation menus.\nConfirmed changes update the responses file, so MCP clients see them too.\n\n`/model` switches between two backends and manages each one.\n\n**DeepSeek** — the secondary, explicitly selected remote option; needs an API key. Options: enter a new\nkey, remove the stored key, or cancel.\n\n**Bonsai (default)** — `prism-ml/Ternary-Bonsai-2-2B-mlx-2bit`, a small ternary model that\nruns on Apple Silicon through MLX. Options: install it from the internet\n(about 1.2 GB, into `~/.local/share/shev/models`) or uninstall it.\n\nThe Bonsai pack ships its own loader, because its weights can't be loaded by\nstock `mlx-lm`/` mlx-vlm` (they report `Unsupported model type: prism_hadamard_qwen35`). So shev runs the pack's bundled runtime in a resident\nworker, using `uv` with the pack's pinned requirements. Repeated requests in the\nsame session reuse the loaded model; a one-shot loader remains as fallback.\nNothing listens on a port. The first local request\ninstalls the MLX stack into a `uv` environment, which can take a few minutes.\n\nThis pack ties its output to `language_model.model.embed_tokens.as_linear`;\nthere is no separate `language_model.lm_head`. Its native 2-bit operation\nrequires the pack's Hadamard transform. Changing a `bits` parameter alone is\nnot a valid conversion.\n\n`tools/bench-bonsai-head.py` compares native 2-bit with a correctly repacked\n4-bit output head **in memory**, leaving input embeddings and installed files\nuntouched. Run with the pack's `runtime/requirements.txt`, after a local shev\nrequest has created `~/.local/share/shev/models/shev_bonsai_worker.py`:\n\n```\nuv run --python 3.12 --with-requirements \\\n  ~/.local/share/shev/models/Ternary-Bonsai-2-2B-mlx-2bit/runtime/requirements.txt \\\n  python tools/bench-bonsai-head.py\n```\n\nWith the current deterministic prompt, one local run measured 1.55 ms/head and 669 ms/decision for native 2-bit, versus 2.29 ms/head and 734 ms/decision for repacked 4-bit. Both scored 6/6 action labels on a tiny smoke test; an earlier prompt/sampled baseline scored 3/6. This is not evidence of general accuracy, and the improvement is from the prompt/sampling changes, not from repacking. Repacking cannot recover precision already lost in the 2-bit checkpoint. Native 2-bit therefore remains the default. Hardware, prompts and output length affect these timings; existing explicit provider selections are preserved.\n\nShev's MCP server lets **another assistant read your saved decisions**. It does\nnot run Bonsai/DeepSeek or edit your files. No API key, OAuth login, terminal,\nnetwork port, or separately started TUI is required: the MCP host starts shev\nas a subprocess and talks JSON-RPC over stdin/stdout.\n\nSave at least one decision using an explicit file path, for example:\n\n```\nshev --file \"$HOME/shev-responses.json\"\n```\n\nInside that TUI run **`/mcp install`** (or `/mcp` → install). This writes a\ndescriptor under `~/.config/shev/mcp/` and registers the executable and absolute\nhistory path in an existing global OpenCode config, with a private backup.\n`/mcp status` reports the registration; `/mcp uninstall` removes shev's own\nunchanged registration. It does not delete your decisions.\n\nFor OpenCode, reconnect **shev** from `/mcps` or restart the client after\ninstallation. Alternatively, register it explicitly from a shell (replace\nthe executable path if you built from source):\n\n```\nopencode mcp add shev --global -- \"$HOME/.local/bin/shev\" --mcp --file \"$HOME/shev-responses.json\"\nopencode mcp list\n```\n\nThe equivalent OpenCode V2 configuration is:\n\n```\n{\n  \"mcp\": {\n    \"servers\": {\n      \"shev\": {\n        \"type\": \"local\",\n        \"command\": [\"/absolute/path/to/shev\", \"--mcp\", \"--file\", \"/absolute/path/to/responses.json\"],\n        \"enabled\": true\n      }\n    }\n  }\n}\n```\n\nFor Codex, add this to `~/.codex/config.toml` (or your `CODEX_HOME` config),\nreplacing the paths, then restart Codex and check `codex mcp list`:\n\n```\n[mcp_servers.shev]\ncommand = \"/absolute/path/to/shev\"\nargs = [\"--mcp\", \"--file\", \"/absolute/path/to/responses.json\"]\n```\n\nBoth `shev --mcp` and `shev-cli --mcp` work. For a source build, use\n`/absolute/path/to/repository/target/release/shev` after `cargo build --release`.\nDo not put shell expressions such as `$(pwd)` inside a JSON/TOML command array.\n\nExample prompts in OpenCode/Codex:\n\n- “Use shev's `latest_decision` tool and summarize my most recent decision.”\n- “Use shev's `search_decisions` with query`invoice` and limit`10` .”\n- “Read `response2` using shev's`get_decision` tool.”\n\n| Tool | Example arguments | Result | \n|---|---|---|\n| `list_decisions` | `{\"limit\": 20}` | Most recent records, oldest first | \n| `latest_decision` | `{}` | Latest saved record | \n| `get_decision` | `{\"key\": \"response2\"}` or`{\"index\": 2}` | One saved record | \n| `search_decisions` | `{\"query\": \"invoice\", \"limit\": 10}` | Matching saved decisions | \n\nResources are `shev://decisions` (all records) and\n`shev://decisions/latest` (latest record). Reads use the file afresh, so decisions\nsaved by an open TUI become available without restarting the MCP process.\n\n**Troubleshooting:** `unknown option --mcp` means the host is launching an old\nTUI binary. Update/rebuild the **exact executable in the MCP command** and\nreconnect shev. Current releases dispatch `--mcp` before terminal setup. If\nconnection succeeds but no decisions appear, check that the host and TUI use\nthe same absolute history path. Starting `shev --mcp` manually will wait quietly\nfor protocol input; this is normal, not a frozen chat window.\n\n`/skills` reads existing `SKILL.md` files from Codex, Claude, shared\n`~/.agents/skills`, `~/skills`, OpenCode's XDG config directory, and ancestor\nproject `.opencode`, `.agents`, and `.codex` skill folders, plus local skill\ndirectories configured in OpenCode. It loads guidance\ninto memory; it does not install, edit, or execute skill scripts.\n\n`/tools` reads MCP registrations from Codex's `config.toml` and OpenCode's\nglobal/project JSON or JSONC, including V2 `mcp.servers`. `CODEX_HOME` and\n`XDG_CONFIG_HOME` are respected. Selecting a server connects and lists tools;\nselecting a tool shows its argument schema and prepares `/tool server/tool {}`.\nEdit the arguments, then enter to call it. Successful results become reference\ncontext for the next decision; `/skills off` unloads them. Supporting context\ndoes not replace the user's original intent in history.\n\nOnly tools with `readOnlyHint: true` and without `destructiveHint: true` can\nbe called. Unknown/mutating tools are blocked, not silently approved. **MCP\nannotations are declarations from your trusted server, not a security sandbox**;\nonly use servers you trust. Starting a configured server can run its startup\ncode. Calls have time/output limits and cannot request sampling or approvals.\nStdio and streamable HTTP (JSON/SSE) are supported. Configured headers and\nenvironment-based tokens are reused without logging them; host-managed OAuth\ncredentials are not copied. An OAuth-only server reports an authentication\nrequirement rather than claiming success.\n\nThe top of the right pane names the loaded skill or successfully called tool and its source. Integration identity is also stored with its decision. Merely discovering/selecting a server is not reported as a successful tool call.\n\nOpenCode's configured JavaScript plugins are listed with compatibility notices.\n**Host-specific plugins cannot run natively in shev**; they require their host\nruntime. Their MCP interfaces, where registered, can be used through `/tools`.\nshev never rewrites host configuration during discovery or tool use. Explicit\n`/mcp install` is separate and backs up configuration before registration.\n\nThe TUI is the friendly front door. The line CLI is `shev-cli` and it's meant\nfor pipes:\n\n```\necho \"Your invoice is 30 days overdue.\" | shev-cli -i \"draft a polite reminder\"\nshev-cli \"Should I ship this today?\" -i \"answer yes or no and why\"\nshev-cli --mcp                       # serve decisions over MCP on stdio\n```\n\n| Option | Meaning | \n|---|---|\n| `-c` ,`--once <message>` | Judge one message and exit | \n| `-i` ,`--intent <text>` | What you want to do with it | \n| `-f` ,`--file <path>` | Where decisions are appended (default `responses.json` ) | \n| `--mcp` | Serve the recorded decisions over MCP (stdio) | \n\nUseful environment variables:\n\n| Variable | Meaning | \n|---|---|\n| `DEEPSEEK_API_KEY` | Use this key instead of the stored one | \n| `SHEV_RESPONSES_FILE` | Where decisions are appended | \n| `SHEV_INTENT` | Default intent for a non-interactive run | \n| `SHEV_MODELS_DIR` | Where local models live | \n| `SHEV_HOME` | Managed npm state root (set automatically by the npm launcher) | \n| `SHEV_BONSAI_MAX_TOKENS` | Local worker token cap (default `256` ; cold fallback`2048` ) | \n| `SHEV_BONSAI_STREAM` | `1` enables worker token-delta protocol messages | \n| `SHEV_BONSAI_TEMPERATURE` | Local sampling temperature (default `0` , deterministic) | \n\nThe footer shows token usage and the last decision's elapsed milliseconds. The resident worker reports real local token counts; the cold fallback has no usage metadata and reports zero rather than guessing. The concise summary and generated response remain alongside the JSON. A measured warm run took about 750 ms versus 2500 ms including initial model loading—not a claim of Jev's sub-100-ms latency. Malformed local decisions receive at most two format-correction retries; usage includes those attempts. Retries can add latency and still fail rather than silently recording invalid JSON.\n\n| Path | What it is | \n|---|---|\n| `~/.config/shev/config.json` | API key and the selected model ( `0600` ) | \n| `responses.json` | The decisions, appended as `response1` ,`response2` , … | \n| `~/.local/share/shev/models/` | Downloaded local models | \n| `~/.config/shev/install.json` | Installer-owned binaries/PATH blocks and history paths for scoped cleanup | \n\nThe npm launcher isolates its config, default history, and models under\n`~/.local/share/shev-npm/state/` (or `$XDG_DATA_HOME/shev-npm/state/`) instead\nof the paths above. This data survives npm upgrades. Shell\nand MCP integrations still read your existing host configuration without\ncopying credentials. Explicit `--file`/` SHEV_RESPONSES_FILE` paths stay where you\nchose them and are tracked for explicit `shev --uninstall` cleanup.\n\nApache-2.0. See `LICENSE`.", "url": "https://wpnews.pro/news/deepseek-v4-1-flash-on-opencode-pretty-good", "canonical_source": "https://github.com/aditauqir/shev", "published_at": "2026-10-17 03:47:50+00:00", "updated_at": "2026-10-17 03:57:09.325955+00:00", "lang": "en", "topics": ["ai-tools", "ai-agents", "agent-protocols", "large-language-models"], "entities": ["shev", "@noorslvt/shev", "DeepSeek", "OpenCode", "MLX", "MCP", "npm", "Rust"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/deepseek-v4-1-flash-on-opencode-pretty-good", "markdown": "https://wpnews.pro/news/deepseek-v4-1-flash-on-opencode-pretty-good.md", "text": "https://wpnews.pro/news/deepseek-v4-1-flash-on-opencode-pretty-good.txt", "jsonld": "https://wpnews.pro/news/deepseek-v4-1-flash-on-opencode-pretty-good.jsonld"}}