eval

DeepSeek Harness vs OpenCode vs Aider: A 17x Token Gap

I tested DeepSeek Harness, OpenCode, and Aider on the same local model. The newest, most-hyped harness had the lowest pass rate and highest cost.

11 min readUpdated Sep 11, 2026
DeepSeek Harness vs OpenCode vs Aider: A 17x Token Gap

Short answer

I ran DeepSeek Harness (dsh), OpenCode, and Aider on the same 8 coding tasks, the same local model (Qwen3 14B, Q4_K_M, fixed 16K context), and the same M2 24GB Mac — swapping only the harness. Aider passed 7 of 8 tasks at an average of 3,202 tokens and 217 seconds per run. OpenCode passed 5 of 8 at 42,269 tokens (13x Aider) and 635 seconds. DeepSeek Harness — released 2026-08-13 and the fastest-growing open-source agent harness on GitHub at the time of writing — passed 4 of 8 at 54,900 tokens (17x Aider) and 546 seconds [Observed]. The newest, most-hyped harness was the least reliable and most expensive of the three on this test.

The question

DeepSeek Harness shipped on 2026-08-13 as an open-source, MIT-licensed, "everything is a plugin" agent runtime. By 2026-08-17 — four days later — it had passed 141,000 GitHub stars, against OpenCode's roughly 160,000 stars accumulated over its entire history to that point: a much faster growth rate, even if not yet a bigger absolute number. Within weeks, several sites published "DeepSeek Harness vs OpenCode" comparisons. None of them held the model constant. The most rigorous one I found — AtlasCloud, running Composio across 8 harnesses — explicitly excluded DeepSeek Harness because it launched two days after that benchmark published, and ran everything through a cloud API, not a local model. So: does the newest, most-hyped harness actually get more done per token when the model behind it is fixed, local, and identical across all three tools?

Why this matters

A coding-agent harness is a thin layer around a model: it decides how to read files, when to search, how much context to resend each turn, and when to stop. Two harnesses driving the identical model can produce wildly different cost and reliability, and most public benchmarks change the model and the harness at the same time, so you can't tell which one you're actually measuring. If you're picking a harness to pair with a model you're self-hosting, the harness's own overhead is the only variable that matters — and it's the one variable almost nobody isolates.

Methodology

Hardware

  • MacBook Pro, Apple M2, 24GB unified memory, macOS 15.0 (arm64)
  • Docker Desktop 24.0.6

Software

  • Model: Qwen3 14B, Q4_K_M quantization, served by Ollama 0.33.3, tagged as qwen3-14b-ctx16k with num_ctx fixed to 16,384 via a custom Modelfile — this pins the context window identically across all three harnesses regardless of each tool's own default, since Ollama otherwise defaults to a 4,096-token context window that some harnesses override and others don't [Documented; Observed, my fixed override].
  • Harnesses: DeepSeek Harness (@deepseek-ai/dsh) 0.1.2-rc.1, verified against the official deepseek-ai/deepseek-harness GitHub repository; OpenCode (opencode-ai) 1.18.4; Aider (aider-chat) 0.86.2.
  • Each harness ran in its own Docker container (Node 22 + Python 3.12 base) with no other tools installed, mounted to a fresh copy of the task repo, network-isolated except for a path to the model.

Workload

Each (harness, task) pair ran once, serially — one Ollama instance can't be usefully shared across concurrent runs on this hardware, so this is a pilot, not a repeated-trial benchmark (see Limitations). 8 tasks across 3 categories, each a small git-initialized repo with a task prompt and a pytest/mypy check that fails in the unmodified repo and passes only on a correct fix — verified in both directions before any harness touched them:

  • Isolated (3): single-file fixes — an off-by-one bug, adding input validation, adding type hints that must pass mypy --strict.
  • Tightly coupled (3): a change spanning 2-3 files with shared state — a cross-file rename, adding a field to a dataclass used by a caller, and extracting a duplicated constant into a shared config file.
  • Sequential (2): a later step depends on an earlier one in the same task — implement a function then write its own tests; add a required field to a schema then update every constructor call site.

Metrics

A transparent logging reverse proxy sat between every harness and Ollama, forwarding requests untouched and scraping token usage from whichever wire protocol the harness picked. This mattered more than expected: Aider's ollama/ model prefix calls Ollama's native /api/generate endpoint, while OpenCode's and DeepSeek Harness's custom-provider configs call the OpenAI-compatible /v1/chat/completions endpoint — two different response shapes for token counts. The proxy normalized both into {prompt_tokens, completion_tokens} so all three harnesses are measured the same way, rather than trusting each tool's own (inconsistent, and in two of three cases absent) self-reported numbers [Observed].

Grading ran in a separate container (pytest + mypy only, no agent tools) against whatever was on disk when the harness container exited — including after a timeout kill, since the mounted volume survives the container.

Results

Harness Pass rate Avg. tokens/run Avg. wall-clock
Aider 0.86.2 7/8 (87.5%) 3,202 217s
OpenCode 1.18.4 5/8 (62.5%) 42,269 (13.2x) 635s (2.9x)
DeepSeek Harness 0.1.2-rc.1 4/8 (50%) 54,900 (17.1x) 546s (2.5x)

[Observed, n=1 per cell, 24 runs total]

Task Category Aider OpenCode dsh
coupled_new_field tightly coupled PASS PASS PASS
coupled_rename tightly coupled fail fail PASS
coupled_shared_constant tightly coupled PASS fail fail
isolated_offbyone isolated PASS PASS PASS
isolated_typehints isolated PASS PASS PASS
isolated_validation isolated PASS PASS fail
sequential_feature_then_test sequential PASS fail fail
sequential_migrate_then_update sequential PASS PASS fail

Aider swept both the isolated and sequential categories, losing only the cross-file rename. Nobody swept tightly-coupled work, and that's the more interesting result: it reads less like a harness ranking and more like all three hitting the same model capability ceiling, just from different angles.

Failure cases

Aider undershoots on multi-file changes. On coupled_rename (rename a function used in order.py, receipt.py, and a test file), Aider renamed the function in order.py, committed, and stopped — never touching receipt.py, which still imported the old name. Result: ImportError [Observed]. Aider's cheap, fast pattern on every other task was to make one focused edit and commit; here that same pattern meant it treated the first file as the whole task.

OpenCode overshoots the effort but still misses call sites. On the same rename task, OpenCode spent 57,853 tokens — grepping and reading all three files — updated the import line in receipt.py to the new function name, but left the function call three lines below still referencing the old name: NameError. It then reported: "All instances of compute_total have been renamed... The test file... now passes" — which was false; it never re-ran the test to check [Observed]. On sequential_feature_then_test (implement is_palindrome, write your own tests), OpenCode actually executed its own test file and hit a genuine logic bug — its palindrome check failed on "Madam Arora, a madam" — and left it unresolved rather than debugging further [Observed]. That's a real reasoning failure in the underlying model, not a scaffolding gap.

DeepSeek Harness is slow to converge, sometimes confidently wrong, and once refused to run at all. On coupled_rename, its reasoning trace shows roughly ten turns spent re-running glob after misreading empty results as "the files don't exist," before it located the files it needed; it hit my 900-second default cap having only edited one of three files, and needed a 1,800-second cap to finish correctly at 98,844 tokens — the single most expensive run in the entire pilot. On isolated_validation (add a ValueError on divide-by-zero), it declared "The input validation has been successfully added... this change ensures that a ValueError is raised... I don't need to run the tests myself" — and the fix in fact failed the grader with a collection error [Observed]. On sequential_feature_then_test, it never got the chance to try: its file-sandbox plugin requires bubblewrap or a Landlock-enforcing kernel, neither of which is present in my minimal Debian container, and it refused to write a new file at all: "I cannot proceed under workspace-write due to the absence of required sandboxing tools... blocked from completing the task." [Observed]. That's a real operational rough edge for anyone running dsh in a bare container — and arguably the harness failing safe rather than writing files without the sandbox it expects is the correct security default, even though it cost it a point in my pass rate. See Security below.

Production considerations

  • Token cost compounds. At any non-trivial usage volume, a 13-17x token multiplier is the difference between a side project and a real hosting bill, even against a free local model — it still burns wall-clock time, context budget if you're proxying to a paid model behind the same interface, and electricity.
  • "Passed" isn't the whole story. One of OpenCode's failures and one of DeepSeek Harness's were confident, plausible-sounding final messages claiming success on a broken fix. If you're running any of these unattended, don't trust the harness's own sign-off — run the test suite yourself as a gate, which is exactly what my grader container did.
  • Timeouts need headroom for newer harnesses. DeepSeek Harness needed double my default cap to finish a task the other two resolved (or failed) well inside it. If you adopt a very new harness, budget more wall-clock per task until you've seen its actual convergence pattern.
  • Sandbox requirements are a deployment dependency, not a footnote. DeepSeek Harness's default file-write path assumes bubblewrap or Landlock. If you're containerizing it, that's an extra package to install, not something you'll discover until it refuses to write a file.

Security

Aider and OpenCode, as configured here, write to the mounted workspace directly with no additional in-process sandboxing — my isolation boundary was the Docker container itself, not the harness. DeepSeek Harness ships its own file-system sandbox plugin and, when it can't set that sandbox up (as in my minimal container), refuses to write rather than falling back to unsandboxed writes. That's the safer default of the three, even though it's the reason one of its four failures happened at all. If you're giving any of these harnesses write access to a real codebase rather than a disposable container, prefer whichever one fails closed like this over one that fails open.

Limitations

  • n=1 per cell. 24 runs total, one trial per (task, harness) pair. This is a pilot aimed at direction and rough magnitude, not a statistically powered result — a harness that "failed" here might pass on a repeat run, and vice versa [Unknown].
  • Single model. Everything here reflects Qwen3 14B's capability paired with three harnesses' scaffolding. A larger or more capable model might narrow or erase these gaps entirely — I did not test that [Hypothesized].
  • Two timeout policies. One run (coupled_rename × dsh) was rerun at a 2x longer cap after its own reasoning log showed real, if slow, progress toward a correct fix. Every other run used the same 900-second default. This is disclosed, not hidden, but it means the comparison isn't perfectly uniform on wall-clock for that one cell.
  • Container environment, not bare metal. DeepSeek Harness's sandbox failure is specific to my minimal Docker image lacking bubblewrap/ Landlock — a bare-metal or differently-configured container might not hit this at all. I'm reporting what happened in the environment I built, not a universal claim about dsh's reliability.
  • Versions are pre-1.0 and moving fast. DeepSeek Harness was on 0.1.2-rc.1 at time of testing, three and a half weeks after its first release. These numbers are a snapshot, not a permanent verdict.
  • External corroboration, different conditions. A separate benchmark from AtlasCloud, run before DeepSeek Harness existed, measured OpenCode at 692,000 tokens and a 46.7% pass rate per task across 30 complex multi-app workflows on DeepSeek V4 Flash via a cloud API — a different model, task set, and environment from ours, so not directly comparable. It's not evidence for my specific numbers, but it's a second, independent data point showing OpenCode's token appetite is a recurring pattern, not an artifact of my task suite [Documented].

Conclusion

Holding the model, hardware, and task suite constant, Aider came out both the cheapest and the most reliable of the three — the opposite of the "cheap and sloppy vs. expensive and careful" story I expected going in. DeepSeek Harness — the one with by far the most hype and GitHub momentum at launch — was the most expensive and least reliable on this specific model and task set. That doesn't make it a bad harness: its plugin architecture and fail-closed sandboxing are real design choices with real value. It does mean the hype cycle and the actual per-token, per-task output are two different things, and right now, nobody publishing a "new agent" comparison is holding the model still long enough to see the gap between them.

FAQ

Does this mean DeepSeek Harness is bad?

No — it's three and a half weeks old at time of testing and still at 0.1.2-rc.1. This is a snapshot on one local 14B model and 8 small tasks, not a verdict on its architecture or its ceiling with a stronger model [Documented].

Why test local models instead of the cloud APIs everyone else uses?

Every existing "DeepSeek Harness vs X" piece I found either used a cloud API or synthesized vendor-reported numbers — never a controlled, reproducible test with the model held constant. Local and reproducible is the gap nobody else filled [Observed].

Why only 8 tasks instead of a larger suite?

This is a deliberate pilot: cheap enough to run on a laptop between sessions, sized to sanity-check the hypothesis before committing to a larger, statistically powered run. See Limitations for exactly what that does and doesn't support.

Would a bigger model change these results?

Unknown — I didn't test one. It's plausible a stronger model narrows the reliability gap since fewer of these failures looked like harness overhead and more looked like the model missing a call site or a logic case [Hypothesized].

Is Aider always the right choice, then?

On this measure — cost and pass rate with a self-hosted 14B model on small Python tasks — yes. Harness choice also depends on things I didn't measure: multi-language support, IDE integration, plugin ecosystems, and team workflow fit.

FAQ

Does this mean DeepSeek Harness is bad?

No — it's three and a half weeks old at time of testing and still at 0.1.2-rc.1. This is a snapshot on one local 14B model and 8 small tasks, not a verdict on its architecture or its ceiling with a stronger model [Documented].

Why test local models instead of the cloud APIs everyone else uses?

Every existing "DeepSeek Harness vs X" piece I found either used a cloud API or synthesized vendor-reported numbers — never a controlled, reproducible test with the model held constant. Local and reproducible is the gap nobody else filled [Observed].

Why only 8 tasks instead of a larger suite?

This is a deliberate pilot: cheap enough to run on a laptop between sessions, sized to sanity-check the hypothesis before committing to a larger, statistically powered run. See Limitations for exactly what that does and doesn't support.

Would a bigger model change these results?

Unknown — I didn't test one. It's plausible a stronger model narrows the reliability gap since fewer of these failures looked like harness overhead and more looked like the model missing a call site or a logic case [Hypothesized].

Is Aider always the right choice, then?

On this measure — cost and pass rate with a self-hosted 14B model on small Python tasks — yes. Harness choice also depends on things I didn't measure: multi-language support, IDE integration, plugin ecosystems, and team workflow fit.

deepseek-harness
opencode
aider
coding-agent
benchmark
ollama
local-llm