lossless-claw-enhanced: a deprecated fork of the OpenClaw context plugin
Fork of Martian-Engineering/lossless-claw with CJK-aware token estimation
At a glance
- What is it?
- This fork of Martian-Engineering/lossless-claw added CJK-aware token estimation and CJK trigram search to an OpenClaw plugin that replaces sliding-window compaction with DAG-based summarization. Both of those features have since been merged upstream, the fork is at 0.5.3, and its own README tells new users to go elsewhere. The interesting part is the CJK estimation arithmetic, and the useful part is knowing not to install this.
- Who is it for?
- Adopt Martian-Engineering/lossless-claw directly, not this fork, because the CJK work that justified the fork was merged upstream and this copy no longer compiles against current OpenClaw, with the README pointing existing users on 2026.5.x to upstream as well. Read this fork only if you need the specific upstream pull requests 178, 190 and 172, or the CJK estimation table below, as a reference for how character counting diverges from real tokenizer output.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 149 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The fork's own README says to stop using it
The first thing in this repository is a warning box, and it is unusually direct. The fork is deprecated and readers are asked to use upstream instead. The two original differentiators, CJK-aware token estimation and CJK trigram FTS search, have both been merged into Martian-Engineering/lossless-claw, through pull requests 344 and 219, and as of upstream v0.11.x there is no functional gap between the fork and upstream.
The version numbers make the rest of the story concrete. This fork sits at 0.5.3 and was last adapted to OpenClaw 2026.4.14, which puts it about six minor versions behind upstream. It will not be updated further.
The two audiences are separated explicitly. New users are told to use Martian-Engineering/lossless-claw directly, because it builds clean against current OpenClaw and includes all the CJK fixes this fork pioneered. Existing users on OpenClaw 2026.5.x and later are told to switch to upstream too, because this fork no longer compiles against current OpenClaw, with a link to issue 32 in this repository for the details.
That is a project that has done the honest thing. The fork did real work, upstream absorbed it, and rather than sit on the divergence the author published a deprecation notice with a migration path. The last push was on 2026-05-28 and the repository publishes no GitHub releases.
The underlying project is worth understanding anyway, because the mechanism it implements is the interesting part and the CJK arithmetic is instructive on its own terms.
DAG summarization instead of a sliding window
lossless-claw is a Lossless Context Management plugin for OpenClaw, based on the LCM paper from Voltropy. What it replaces is OpenClaw's built-in sliding-window compaction, and what it puts in its place is a DAG-based summarization system that preserves every message while keeping the active context within model token limits.
The distinction matters. A sliding window discards. When the context fills up, the oldest messages fall out of the window and are gone, which is a lossy operation and one that loses the oldest context, which is often where the task definition lives. The DAG approach summarises rather than discards. Messages become nodes, summaries become nodes that reference the messages they cover, and a summary can itself be summarised, so the structure is a graph rather than a queue.
The practical effect is that a long conversation stays bounded in the token count the model receives while the full history remains queryable. That is what makes the retrieval side of the system necessary rather than optional, since the active context is a window into a larger retained structure, and finding the right node in that structure is a search problem. Hence the hybrid retrieval mentioned in the video tutorial description, and hence the trigram FTS work that the fork contributed.
The audience is OpenClaw users running long agent sessions where the conversation history is the working memory, and where losing the beginning of the session silently breaks the task.
Why character counting is wrong for CJK, and by how much
The fork's first differentiator is the one that taught upstream something, so it is worth reading carefully.
Upstream estimates tokens with Math.ceil(text.length / 4), which assumes roughly four ASCII characters per token. For CJK text this underestimates by 2 to 4 times, because each CJK character maps to roughly 1.5 tokens in modern tokenizers such as cl100k_base and o200k_base.
The fork's table gives the per-character rates side by side. ASCII and Latin characters stay at 0.25 tokens per character in both, unchanged. CJK characters go from 0.25 upstream to 1.5 in the fork, a 6x correction. Emoji and supplementary plane characters go from 0.5 to 2.0, a 4x correction.
The worked example makes the size of the error concrete. For a 14 character Chinese string, upstream computes ceil(14 / 4) and gets 4 tokens, marked as wrong, while the fork computes ceil(14 * 1.5) and gets 21 tokens, marked as accurate, and the real cl100k_base count for the same string is 19 tokens.
Upstream counted four tokens for a string that actually costs nineteen, a factor of nearly five. And the fork's estimate of twenty-one is close to, though not exactly, the real number, which is the point: the method is a character-class heuristic, not a tokenizer call, and it is not exact.
The consequences the README lists are the practical argument for caring. Compaction triggers too late, causing context window overflow. Context assembly budgets are miscalculated. Summary target sizes are wrong. And large file interception misses CJK-heavy files.
That last one is the quiet failure. A user writing in Chinese sees their context overflow, or sees compaction fire at the wrong moment, and has no way to connect it to a character-counting heuristic in a plugin they did not write.
The migration, the consolidation and the test count
The implementation changes were small and mechanical, which is a good sign for a patch of this kind.
A shared src/estimate-tokens.ts holds the CJK and emoji aware estimation, and the fork consolidated five duplicate estimateTokens() implementations into a single import. That second change matters as much as the first on its own, because five copies of a token estimator is five places for the arithmetic to drift.
The migration is idempotent, which is the property that decides whether a patch like this is safe to ship. On upgrade it recalculates token_count for existing CJK messages and summaries, and pure ASCII rows are not touched. Idempotent means running it twice does the same thing as running it once, so a partially migrated database can be re-run safely.
The test count is given as 18 cases, 10 for estimation and 8 for migration. That is a modest suite for a change that rewrites stored counts, and it is a fair thing to hold against the fork as well as a fair thing to credit.
The fork also cherry-picked three upstream bug fixes, and these are worth knowing about because they describe real failure modes rather than cosmetic ones. Pull request 178 prevents false-positive auth errors in stripAuthErrors(), because conversations discussing 401 errors or API keys caused the summariser to falsely report an auth failure and abort compaction. Pull request 190 detects session file rotation in bootstrap, because after a /reset or a session rotation, compaction never triggered on the new session and the context grew without bound. Pull request 172 skips ingesting empty error and aborted assistant messages, because API 500s produced empty messages that accumulated and created a feedback loop that permanently broke the agent.
All the cherry-picks were reviewed by OpenAI Codex with three further fixes applied: a parent_id to parent_summary_id column name correction in the session rotation purge, FTS table operations guarded with try/catch for no-FTS runtimes, and the CJK migration reordered before backfillSummaryMetadata so derived fields use corrected values.
Installing the plugin and setting the context engine slot
The install is a clone plus a plugin install, and the README offers two modes with a meaningful difference between them:
git clone https://github.com/win4r/lossless-claw-enhanced.git
cd lossless-claw-enhanced
npm install
openclaw plugins install --link .Link mode picks up code changes instantly, which is what you want while you are editing the plugin. Copy install, with openclaw plugins install ./lossless-claw-enhanced, takes a snapshot that will not pick up later changes. One caveat is called out explicitly: link mode does not install the plugin's npm dependencies for you, so npm install has to run in the plugin directory first on a fresh clone.
The plugin then has to be wired into OpenClaw by taking the context engine slot, which is done in the OpenClaw configuration:
{
"plugins": {
"slots": {
"contextEngine": "lossless-claw"
},
"entries": {
"lossless-claw": {
"enabled": true,
"config": {
"freshTailCount": 32,
"contextThreshold": 0.75,
"incrementalMaxDepth": -1,
"ignoreSessionPatterns": [
"agent:*:cron:**",
"agent:*:subagent:**"
],
"summaryModel": "anthropic/claude-haiku-4-5"
}
}
}
}
}A few of those values are worth reading rather than copying. freshTailCount of 32 sets how many recent messages are kept verbatim. contextThreshold of 0.75 is the fraction of the context window at which compaction starts. incrementalMaxDepth of -1 is a sentinel for no limit on how deep the incremental summary chain goes. The ignoreSessionPatterns entries exclude scheduled and subagent sessions from the system entirely.
After changing the configuration the gateway is restarted with:
openclaw gateway restartThe 2026.5.x config validation trap and the environment variable path
There is a compatibility trap here that is specific to the OpenClaw version, and it is the same trap that makes the fork uncompilable on current OpenClaw.
Some OpenClaw 2026.5.x builds validate openclaw.json before plugin schemas are loaded. In that case, putting custom plugin config under plugins.entries.lossless-claw.config fails with an invalid input error pointing at the plugins key. The error looks like this:
OpenClaw config is invalid: ~/.openclaw/openclaw.json
x plugins: Invalid inputThe workaround is to keep only the slot and enablement settings in openclaw.json and set the LCM tuning through environment variables instead:
export LCM_SUMMARY_MODEL=minimax/MiniMax-M2.5
export LCM_EXPANSION_MODEL=minimax/MiniMax-M2.5
# Optional when the model string does not include a provider prefix:
export LCM_SUMMARY_PROVIDER=minimax
export LCM_EXPANSION_PROVIDER=minimaxThe plugin still supports summaryModel, summaryProvider, expansionModel and expansionProvider when the host accepts plugin config objects, so the environment variable route is the compatible path for strict validators rather than a downgrade in features.
Updates follow the install mode. With a link install, git pull origin main followed by a gateway restart is enough. With a copy install, the plugin has to be re-installed from the path before the restart.
The repository layout backs up the packaging story. There is an index.ts as the main entry, an openclaw.plugin.json describing the plugin, a src/ directory, a tui/ directory, a test/ directory run by vitest, a docs/ directory with a Chinese configuration document, and a README_zh.md. The package is published under the name @martian-engineering/lossless-claw at version 0.5.3, with a peer dependency on openclaw of at least 2026.4.2. A Dockerfile builds a Node 22 bookworm image that installs openclaw globally, installs the plugin into a workspace and runs the gateway in the foreground.
Editorial conclusion
Adopt Martian-Engineering/lossless-claw directly, not this fork, because the CJK work that justified the fork was merged upstream and this copy no longer compiles against current OpenClaw, with the README pointing existing users on 2026.5.x to upstream as well. Read this fork only if you need the specific upstream pull requests 178, 190 and 172, or the CJK estimation table below, as a reference for how character counting diverges from real tokenizer output. Verify first that your OpenClaw version is at or below 2026.4.14 if you keep the fork, and that your chosen summarisation model is set through the path your host's config validator accepts.
Frequently asked questions
Is lossless-claw-enhanced still maintained?
No. The README marks the fork deprecated, says it will not be updated further, and notes that it sits at 0.5.3, last adapted to OpenClaw 2026.4.14 and about six minor versions behind upstream. The last push was on 2026-05-28.
What does lossless-claw-enhanced do that upstream lossless-claw does not?
Nothing any more. Its two original differentiators, CJK-aware token estimation and CJK trigram FTS search, were merged into upstream Martian-Engineering/lossless-claw through pull requests 344 and 219, and as of upstream v0.11.x the README states there is no functional gap between the fork and upstream.
How do I install the lossless-claw plugin?
Clone the repository, run npm install in the plugin directory, then use openclaw plugins install --link . for a link install that picks up code changes, or openclaw plugins install ./lossless-claw-enhanced for a copy snapshot. Then set the contextEngine slot to lossless-claw in the OpenClaw config and restart the gateway.
Why does my lossless-claw config fail with 'x plugins: Invalid input'?
Some OpenClaw 2026.5.x builds validate openclaw.json before plugin schemas are loaded, so config placed under plugins.entries.lossless-claw.config is rejected. Keep only the slot and enablement settings in openclaw.json and set the tuning through environment variables such as LCM_SUMMARY_MODEL and LCM_EXPANSION_MODEL instead.
How does the CJK token estimation differ from the upstream approach?
Upstream uses Math.ceil(text.length / 4), which counts about four ASCII characters per token and underestimates CJK text by 2 to 4 times. The fork uses a character-class aware estimate: 1.5 tokens per CJK character and 2.0 for emoji, against 0.25 for ASCII, so a 14 character Chinese string is estimated at 21 tokens rather than 4.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/win4r-lossless-claw-enhanced)Was this useful?