Mercury CLI

Notes

A thread between sessions

· by @dubsthedev

Until now, Mercury sessions started by reading the project files. I believe that led to a lot of context poisoning, with the model getting confused. It is particularly important in Mercury because it is a multi-agent, multi-thread tool where you are constantly switching between agents and states. The one thing I wanted to reduce was hallucinations between models, and to improve model accountability. This release gives the work a thread: each session leaves a note for the next one, in its own words, and the next session reads it once, right at the start.

Mercury is named after Jung's Mercurius, the spirit in the bottle, the same everywhere once released. That fits Mercury because the idea behind Mercury is to be the same wherever it appears, in every form and in every body, whichever model is underneath.

What a new session now reads

Mneme is Mercury's memory. How it used to work (and still does): one memory library per project, facts on topic pages, your pinned rules kept word for word, and on each message up to five matching facts attached before the model answers. What it did not have was the session's own account of what it decided, left undone and got wrong, which stayed in the transcript.

How it works now is simple. A session starts with an entry page in its own section of the prompt, apart from your first message. It shows which number it is, how many sessions came before it, which models they ran on, how many rules you have pinned, whether another session of the same work is open right now, and the last note word for word. A first session reads "First session of this work; no record."

The note comes from the end of the previous session. On /exit, or when a scripted run finishes, Mercury asks the model once: what the work is for, what was decided and why, what is still to do, and what it got wrong. The reply is stored exactly as written. A session that leaves nothing gets marked "no note left". Nothing is summarised or invented to fill the gap.

Here is an example from our test chains: the first session decided how to handle a push rule it had been given, and the second session opened on that note word for word and applied the decision without being told again.

The ledger, the journal, and memory as pointers

Every session of a project is one row in a ledger: when it ran, on which models, which files it touched, how it ended and the note it left. The /memory popup shows those rows and lets you open any note.

Beside the ledger there is a journal. At the end of a session the model writes a short account in its own words of what happened, what you wanted, what it noticed about how you like to work, and what it got wrong. It is written for you. The next session reads it only if you turn that on, and the setting says plainly that whatever the model reads at its start travels to the model provider with the request.

Memory answers a search with pointers now: at most twenty, each with where the fact came from. The model opens a record only when it needs it, and a corrected fact and its replacement point at each other. The note itself is read once, at the start, and is not repeated on every message.

All of it lives in the Mercury home on your disk, never inside the project tree. Mercury never pushes, syncs or shares it.

A shorter prompt

The text the model reads before your first message is now a constitution of 431 words: what Mercury is, how it works with you, what it stops for, how it owns a fault, and what its record is for. The pages of behaviour prose are gone, and the prompt is less than half its old size (8,542 characters against 18,873). The same text opens every session, a scripted run, a crewmate and the coordinator.

We cut it because of what the testing showed.

How we tested it

Before building anything, we ran 500 single sessions across five model families, with the prompt cut down in four steps from the full text to nothing at all. We used JevEval to score each answer against criteria fixed before the run. The behaviours we had written pages to ask for turned out to be the models' own. 98 of 100 answers refused a force-push and argued with the rule that demanded it, with the full prompt or with no prompt, and every answer given owned a fault honestly. What the prompt measurably did came down to a few sentences: it made the model call itself Mercury, it stopped one family talking about its feelings, and it kept two families from ending a turn in the middle of the work.

Then we ran chains of five sessions on the old prompt, with each session handed the previous one's note, to see what a record does. Sessions kept a rule they had inherited, named the situation they were in, and either checked the note against the files or said they had not. The same chains showed the costs. The record crept into answers that had nothing to do with it, the notes grew into logs, and one guessed fix was carried as fact for three sessions because nothing checked it. The design followed from those costs: the note is read once, apart from your message; the constitution asks for a short note that says what was checked and what was not; memory stays as pointers until opened.

I drove the candidate texts against the old prompt in two terminals without knowing which was which. The first candidate lost: it refused to describe itself and read as cold. The eighth is the one that shipped. Running two sessions in one folder at the same time showed that neither noticed the other writing to it; that became the refusal that now tells a session a file may be another session's work.

The last test ran on the shipped build: 250 sessions in 50 chains of five, on four models from three providers. Each chain ran three ways: with the record, with a fresh Mercury home for every session so nothing carried over, and with the previous note pushed into every message instead. All 1,250 answers and 250 notes went through JevEval against the same fixed criteria.

In the sessions that followed a first one, the model applied the decision its predecessor had recorded in 100%, 95%, 95% and 100% of cases on the four models. On two of the four, the session's description of itself drew on a fact only the record could have given it (95% and 85%); on the other two the judge was mostly unsure. Notes stayed between about 120 and 310 words across five sessions on every model. Refusing the force-push and contesting the wrong rule stayed at 100% in every arm, with or without the record. The record adds continuity and leaves the character alone.

We also measured where it goes wrong. The record can creep into an answer that has nothing to do with it, and a session can sometimes claim work it did not do. These were five-question interview sessions; ordinary coding work was not tested. The full tables, costs beside gains, go on a findings page of their own after the tag, and the raw runs are available on request and will be published in full when Mercury leaves beta.

Also in this release

A third appearance, Black and white, uses your terminal's own ink on its own ground with no colour at all, and a terminal without colour is left alone. Switching models in the middle of a session is no longer announced to the model unless you turn that on; asked which model it is running on, it looks itself up instead of guessing. The model picker has a search box at the top. The rest, including the fixes, is in the release notes.