Updated 2026-10-27 · West Mao
How to analyze DeepSeek Harness context usage with dsh-context
Thirty turns into a long session, the ring above the input box has climbed from 3% to 47%, and Harness shows the total and nothing else. dsh-context is a read-only DeepSeek Harness plugin that opens that number up: which component consumed the window, which request grew it, what compaction discarded, and which sub-agent cost the most.
What does dsh-context add to DeepSeek Harness?
Harness reports context as one number, and that number hides the composition. When a window fills, the cause is usually not the conversation itself. It is a large tool result, a verbose plugin's schema, or a skill's injected documentation. The plugin's job is to make that composition visible without leaving the web UI, which is where the rest of your session work already happens.
dsh-context is a TypeScript plugin, licensed Apache-2.0, with about 3,700 GitHub stars and version 0.77.0 on npm as of October 27, 2026. The project lives at github.com/bowenliang123/dsh-context. Context stops being a single percentage and becomes an object you can inspect at request level, category level, file level, and agent level.
You can reach the same data five ways. The Context Insights page in the sidebar covers all sessions. The Context tab inside a session covers that session, and the Fleet tab covers the whole agent family. Typing /context in chat opens an overlay, and a settings card controls where the panel sits and how granular it is.
How do you install it?
Install the plugin from the Harness command line:
Updates use update dsh-context@latest, and dsh web starts the interface. There is no compile step and no restart. Refreshing the page is enough.
Compatibility is the one prerequisite. The plugin reads the V4 session log format. The 0.77.0 package metadata lists @deepseek-ai/dsh 0.2.0-rc.2 and 0.2.1-rc.2 as compatible; earlier releases also documented 0.1.7-rc.2. Below the supported floor the plugin neither crashes nor shows an empty table. It registers fallback units that report zero and displays an upgrade notice. When the probe cannot detect a version at all, the plugin takes the normal path, on the reasoning that a failed probe should not blank out a deployment that works.
dsh plugin --profile web add dsh-context@latestWhy doesn't dsh-context intercept your requests?
It hooks the projection registry instead. dsh-context intercepts nothing and reads no database. The host half is an ordinary Cordis plugin on the Node side; the client half is a browser bundle inside the web UI. The host half registers three projection units on ctx.sessionProjections, a timeline, request headers, and an activity ledger, and Harness pushes the computed values to the browser.
Why must unchanged events return the same object?
Each committed session/event runs apply(state, event) once. The framework compares state with Object.is and pushes only when the reference changes, so an event the plugin does not care about must return the same object it received. Returning anything else re-triggers the entire change stream. State also has to be plain JSON, because it feeds a checkpoint cache.
The cost of this design is defensive code throughout. The registry has no error boundary, so a single throw inside a unit would freeze its pushes and leave the browser showing a spinner forever.
Which numbers are anchored and which are estimated?
Both ends of every chart are anchored. Top-line occupancy and category shares read Harness's official contextPressure and contextBreakdown projections. They therefore always match the ring above the input box; you will never see the plugin report 47% while the input box says 52%.
The fine-grained split is estimated, using the same accounting as the Harness token meter: four characters per token, plus four for each content block, plus four for role framing. Images are priced separately through the vision model's pixel formula. The estimated numerator is then scaled against the official total, so the estimate sets the proportions and the official figure sets the scale.
How does it handle very large session logs?
Heavy work runs on demand, behind a gate. Pushing a full log to the browser is not viable: a session with ten thousand events decodes into an object graph of several hundred megabytes. The browser receives a thin header and pulls details per card when you open one. Every cold read decodes the entire log, so a global gate admits one read at a time and only while V8 heap usage stays below two-thirds of its limit. Under pressure the read is skipped, the card reports no data, and nothing errors out or blocks the interface.
What do the eight cards in the Context tab show?
The Context tab holds eight cards. The denominator for every figure is the current model's window, not a fixed value: models such as deepseek-flash and MiniMax-M3 expose 1M windows, and switching to a smaller window stretches the same conversation's bar immediately.
The composition bar answers a familiar complaint: you barely typed anything, and the window is full. In one observed session, tool results held 65% of the window while user messages held 0%. The two striped segments at the end are compaction reserve. They hold headroom plus the output window the next request needs, they stay out of the occupancy figure, and they cap what space remains.
| Card | Question it answers |
|---|---|
| Context Stats | Turns, steps, tool calls, and cost so far |
| Token Stats | Where billed tokens went, split by category, with the cache hit rate in the corner |
| Timing Stats | How active time divides between model calls, tool runs, and overhead |
| Current Context | What the window holds right now |
| Context Trend | How big each request was and how the window grew |
| Context Browser | What any single request is made of |
| Context Events | When the window changed and why |
| File Activity | What the agent did to your files |
What can you read from the trend chart and the browser?
The trend chart cuts by model request: one bar per request, not one per message. A tool result that returns fifty thousand words counts as one new message in message terms, and as a jump from, say, 30k to 80k tokens in request terms. The request view is the one that hits the ceiling. Compaction events get their own markers, so a bar that suddenly drops comes with its reason attached. The chart switches between Step and Turn views and between Total and Delta, and three lines of plain-language summary underneath cover what you said, what was added, and what the reply called. Clicking a line jumps to the matching message.
The browser splits every request into seven categories: system prompt, tool definitions, user messages, injected context, skill injections, assistant replies, and tool results. Skills get their own category on purpose. The available_skills catalog, the documentation a slash command pulls in, and anything a skill tool loads are all injections. Merging them into the other categories would make it impossible to answer why installing one skill raised the bill.
The tool source column is determined at runtime. Session logs record each tool's schema but not who registered it, so the plugin listens on Cordis's internal/get channel and captures the owner's name the moment a plugin reads the tools service. When that fails, it walks the call stack to the nearest package.json. MCP tools are labeled mcp:<server> directly. Once a few plugins have doubled your tool count, this column is the only place that answers where forty-odd tools came from.
File Activity lists which files the agent touched and groups them per file. Native tools, the Minimal preset's str_replace_editor, and calls nested inside PTC run_code all land in the same row.
What does the Fleet tab add for multi-agent runs?
Fleet draws one picture: the current agent, its parent, and every child agent as a network. The accounting matters more than the drawing. The main session's Context tab counts only its own usage, and what the sub-agents spent never appears there. Fleet is the only place where that total becomes visible.
When is it worth opening dsh-context?
Four situations come up again and again. Each maps to a specific card.
| Situation | Where to look |
|---|---|
| The window jumps and you cannot say why | Current Context: check which segment grew. The cause is usually tool results, such as a cat of a large file or a failed test's output. |
| The same question costs more on the second turn | Trend in Delta view: find the bar with the largest net gain, then read the browser's vs previous turn badge to see which category added items or tokens. |
| Compaction made the agent forget | Context Events: open the Compact entry to see what was reclaimed. Steps from before compaction can be rebuilt from the removed-messages archive, so you can compare what was dropped. |
| You suspect a plugin of quietly eating context | Sort tool definitions by size and read the skill injection segment. Those two places hold most of the hidden overhead. |
What does dsh-context not do?
It only reads. Apart from the Prefix and Suffix fields in settings, which wrap every session's system prompt (sub-agents included), it will not slim your context. Seeing clearly and cutting down are different jobs.
The estimates are estimates. Category splits assume four characters per token, and the official numbers guarantee only the total. One example request showed an estimate of 104.5k against an actual of 108.5k, a 3.8% gap. That is precise enough to identify the dominant category and too loose for invoice reconciliation.
It serves dsh only. There is no OpenAI SDK adapter, no support for other harnesses, and no export interface. Where the session lives, the data lives.
The codebase is substantial. At version 0.74.0 it spanned 160 source files at 1.37 MB, of which the client bundle was about four fifths, plus 193 test files at 2.18 MB, larger than the source itself. For a tool whose numbers have to be right, that coverage is appropriate. The price is that contributing means a long reading investment first.
FAQ
Which Harness versions does dsh-context support?
The 0.77.0 package metadata lists @deepseek-ai/dsh 0.2.0-rc.2 and 0.2.1-rc.2 as compatible, and earlier releases documented 0.1.7-rc.2. Older builds get zeros plus an upgrade notice, and undetectable versions follow the normal path.
Does the plugin slow Harness down?
Cold reads are gated to one at a time and are skipped entirely once V8 heap usage passes two-thirds of the limit. The browser receives a thin header first and pulls detail per card, so ordinary interaction stays light.
Are the token counts exact?
The totals are, because they come from Harness's own contextPressure and contextBreakdown projections. The per-category splits are estimates; one example landed 3.8% below the official total.
Can dsh-context reduce context usage?
No. It is read-only by design, and its only settings are the Prefix and Suffix fields. Use it to find the category worth cutting, then cut it in your own workflow.
Context used to be something you could feel but not query: visibly full, visibly expensive, with no place to point at the cause. dsh-context makes the cause pointable at request, category, file, and agent level. If you run long sessions, read the breakdown before you tune anything; knowing where the window goes decides which fix matters.