Library / SDK
stephenschoettler/hermes-lcm avatar
stephenschoettler/hermes-lcm

Fifteen verdict files at the root, three benchmark directories, and no package to pip install

Lossless Context Management plugin for Hermes Agent, DAG-based context engine that never loses a message.

1,323 stars191 forksPythonMIT

At a glance

What is it?
hermes-lcm replaces the host agent's one-shot context compression with a SQLite-backed summary DAG and a set of fifteen recall tools, and it is installed by symlink into a plugins directory rather than from a package index. Its most revealing files are not the engine: they are a manifest that admits it exists only to pin lint settings, and a dependency contract that explicitly declines to be a security guarantee.
Who is it for?
It fits an operator on Hermes Agent whose sessions lose detail after compaction and who wants a drill-down path back into compacted turns, and who is willing to own a tree of forty flat modules installed by script. It does not fit anyone who wants a versioned package, a supported upgrade path or a bounded tool surface, since there is nothing on an index, the install is a symlink into a home directory, and fifteen retrieval verbs are offered to the model at once.
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 28 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • stephenschoettler/hermes-lcm1,323 ★ · +370
Star history
Repository2026-08-042026-11-14
stephenschoettler/hermes-lcm9531.3k

370 Stars in the last 102 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Five verdict files, a flat module tree, and three benchmark directories

The root is where the project's organisation shows. Five documents sit there as siblings of the README, named FINDINGS-VERDICTS-R4.md, FINDINGS-VERDICTS-R4B.md, FINDINGS-VERDICTS-R6.md, FINDINGS-VERDICTS-R7.md and FINDINGS-VERDICTS-UP1.md, so audit rounds appear to be tracked as separate verdict records rather than folded into a changelog. A `__init__.py` sits at the top level too, and with it around forty flat modules: compaction, dag, engine, engine_registry, fresh_tail, chunking, externalize, escalation, guidance, diagnostics, maintenance, and separate modules for assertions, evidence, message analysis, model routing and codex routing, among others. There is no `src/` directory and no package layout. And there are three benchmark directories whose names differ only by suffix, `bench/`, `benchmarking/` and `benchmarks/`, which is the kind of duplication that usually means a migration happened and the old names stayed.

The manifest exists to pin lint, and says that in its first comment

pyproject.toml opens with an explanation of its own purpose: it exists only to pin lint settings so ruff behaves identically locally and in CI, and it intentionally declares no build-system section and no project metadata, because the plugin is installed through a script rather than pip. That single sentence explains the whole install model. The lint policy is where the file earns its place. `target-version` is `py311`, chosen to match the oldest runtime CI exercises and keep lint aligned with the 3.11 leg. The selected rules are `E4`, `E7`, `E9` and `F`, described as pyflakes plus a focused pycodestyle subset. Two rules are declined on purpose: line length and import sorting, with the note that the codebase predates both and enforcing either would be a large, purely cosmetic reformat with no behavioural benefit. A third, `E402`, is ignored because several modules import after a sys.path or optional-dependency bootstrap, so imports legitimately follow executable statements.

Two optional dependencies, each degrading on purpose instead of substituting silently

There are no required third-party runtime dependencies, and the two optional ones are handled differently on purpose. `tiktoken` is used when present, and when it is not the plugin falls back to character-based token estimates, which is a graceful degradation because the estimate is only used for budgeting. `regex` is used when present to apply timeouts to message ignore patterns. Without it, message-level regex filtering is disabled and a warning is emitted, rather than falling back to the standard library `re` module. That choice is the interesting one: an unbounded standard library match against a user-supplied pattern is a way to hang the host, so the feature is switched off and announced instead of being attempted with a weaker engine. The documentation matches that caution. A versioned dependency contract lists every shipped runtime import, supported host and Python versions, ownership and the mechanical validation command, with a machine-readable `dependency-contract.json` at the root, and it describes itself as an assurance boundary rather than a claim that the host's resolved environment is free of known vulnerabilities.

The README tells its own authors how not to market it

The comparison with the host's built-in behaviour is unusually candid, including what it concedes. Hermes' own compressor, described step by step, prunes older tool results when the prompt crosses its configured threshold, asks an auxiliary model to summarize the middle and older conversation, and rebuilds the active prompt from that summary plus a protected recent tail. The README then states that the original session rows can still live in Hermes' `state.db` and remain reachable through host tools such as `session_search`, so built-in compression is lossy in the active context but not destructive. From there it gives authors three differences to argue from, a plugin-local store and DAG built for drill-down, current-session retrieval through the plugin's own tools rather than an auxiliary cross-session search, and explicit source-lineage and session-boundary rules. And one line is an instruction rather than a claim: position the plugin around retrieval quality, autonomy and drill-down, and do not claim Hermes core has no persisted record of pre-compression history.

Fifteen tools, several of them overlapping retrieval verbs

The tool list is long enough to be a decision in itself. Fifteen names are registered: `lcm_grep`, `lcm_recall`, `lcm_query_state`, `lcm_compute`, `lcm_compile_evidence`, `lcm_evidence_pack`, `lcm_retrieve`, `lcm_recent`, `lcm_load_session`, `lcm_describe`, `lcm_expand`, `lcm_expand_query`, `lcm_status`, `lcm_inspect` and `lcm_doctor`. Several of those verbs describe the same motion at different granularity, retrieve against recall against expand against expand_query against query_state, and an agent choosing among fifteen has to pick correctly before it gets an answer. The design answer to that pressure is stated rather than assumed. Recovery is bounded and paged: raw messages, child summaries and externalized payloads are returned in pages instead of being dumped into the prompt, and oversized tool, media or base64 payloads are externalized to recoverable references so an inline blob does not reach the database or the context window. Retrieval is source-aware, filtering raw rows and summaries by descendant lineage, and session controls take glob patterns so noisy sessions can be ignored or held read-only.

A clone is not an install, and the skill only appears after a second command

There are three install paths and one of them is easy to half-finish. The canonical one clones the repository straight into the global plugin directory:

bash
git clone https://github.com/stephenschoettler/hermes-lcm \
  ~/.hermes/plugins/hermes-lcm

A profile-specific variant clones into `~/.hermes/profiles/myprofile/plugins/hermes-lcm`, and from an existing checkout you can run `./scripts/install.sh`, optionally prefixed with `HERMES_PROFILE=myprofile`. The instruction that matters is the one about ordering: run the install script even when the checkout already sits at the canonical plugin path. The clone leaves you with code on disk and nothing registered. The script leaves that checkout in place and is what exposes the bundled `hermes-lcm` skill in the matching global or profile `skills/` directory, and it preflights both paths and refuses conflicts before creating any links, so a partial install fails loudly rather than leaving one half of the pair pointing at the wrong place.

Two pre-release conventions in consecutive tags, and the design comes from elsewhere

The tag history does not use one scheme. Three recent releases are v0.20.0 on 2026-07-24, v0.21.0-rc2 on 2026-08-06 and v1.0.0-rc.1 on 2026-09-04, so one pre-release writes the suffix as `rc2` and the next as `rc.1`, and the jump from 0.21 to 1.0 means the current line is a candidate rather than a stable release. The branch was pushed on 2026-09-14. Attribution is clear and worth reading for what it implies about the design. The plugin is based on the LCM paper by Ehrlich and Blackman of Voltropy PBC from February 2026, inspired by an earlier implementation called lossless-claw built for OpenClaw, with an external site offering an interactive visualisation of the idea. So the DAG scheme is inherited from a published third-party design rather than invented here, and this is one implementation of it. One more feature is worth reading precisely: sensitive-pattern redaction of API keys, bearer tokens, passwords and private keys happens before the plugin stores or summarises anything, which is the right place for it, but it is optional and driven by named patterns the operator supplies, so there is no built-in detector behind it.

Editorial conclusion

It fits an operator on Hermes Agent whose sessions lose detail after compaction and who wants a drill-down path back into compacted turns, and who is willing to own a tree of forty flat modules installed by script. It does not fit anyone who wants a versioned package, a supported upgrade path or a bounded tool surface, since there is nothing on an index, the install is a symlink into a home directory, and fifteen retrieval verbs are offered to the model at once. Before enabling the redaction feature, write your own patterns rather than assuming a default list exists, because it is optional and named by the operator, and treat the dependency contract as documentation of what is imported rather than as evidence that the host environment is sound.

Frequently asked questions

What does hermes-lcm replace?

It replaces one-shot active-context compression with a SQLite-backed context engine that persists raw messages, compacts older turns into depth-aware summary nodes, condenses those into a hierarchical DAG, and assembles the active prompt from the system prompt, the highest-value summaries and a protected fresh tail.

How is hermes-lcm installed?

By git clone into ~/.hermes/plugins/hermes-lcm, or into a profile directory, followed by ./scripts/install.sh, which is needed even when the checkout is already at the canonical path. It is not installed with pip, and pyproject.toml declares no build system or project metadata.

Does hermes-lcm need any third-party packages?

No required runtime dependencies. tiktoken is used if available and otherwise token counts are estimated from characters. regex is used if available, and without it message-level regex filtering is disabled with a warning rather than falling back to unbounded standard library matching.

Is Hermes context history lost by its built-in compressor?

Not permanently. The README says original session rows can still live in Hermes state.db and stay reachable through host tools such as session_search. hermes-lcm differs by making recall part of its own active context engine rather than a separate cross-session search step.

Is hermes-lcm a stable release?

The newest tag is v1.0.0-rc.1 from 2026-09-04, a release candidate, and the tag before it used a different pre-release spelling, v0.21.0-rc2. The branch was pushed on 2026-09-14.

Official sources

  1. Official README
  2. Project repository
  3. Release notes
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/stephenschoettler-hermes-lcm.svg)](https://hysenlabs.com/projects/stephenschoettler-hermes-lcm)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/stephenschoettler-hermes-lcm.svg)](https://hysenlabs.com/projects/stephenschoettler-hermes-lcm)

Was this useful?