# EONYX memory: AGENTS.md, sessions and context compaction


Every agent turn starts with the model receiving context. In EONYX it is built from three mechanisms: **AGENTS.md** — the project's persistent instructions, **sessions** — the full conversation history on disk, and **auto-summarization** — compaction of older turns once the history approaches the limit of the context window.

<!--more-->

## AGENTS.md: project instructions

`AGENTS.md` is a file with the project's rules and context. EONYX finds such files automatically while building the system prompt: it walks **up the directory tree** from the working directory and collects `AGENTS.md` at every level.

### Traversal rules

- The walk stops at the **project root** (the directory with `eonyx.json`), at a directory with `.git`, or at the filesystem root.
- Files are attached from the outermost to the closest: **the one nearest to the working directory comes last**, so local instructions refine the general ones.
- Each file goes into the system prompt under the heading `# Project context: <relative path>`.

Keep the general rules at the repository root and subdirectory specifics next to the code:

```text
my-project/
├── AGENTS.md            ← stack, conventions, prohibitions
└── services/
    └── billing/
        └── AGENTS.md    ← specifics of a particular service
```

### What to write

```markdown
# Project: My App

## Stack
- Go 1.26, PostgreSQL via pgx.

## Rules
- Run `go test ./...` and `go vet ./...` before committing.
- Do not refactor what you were not asked to.

## Prohibited
- Do not edit .env directly.
- Never run migrations without confirmation.
```

{{< admonition type="note" title="Replacing the prompt entirely" >}}
If the generated system prompt does not suit you, it can be replaced wholesale: the `system_prompt` field in `eonyx.json` or the `--system-prompt` flag of `eonyx run` (the flag beats the field, the field beats generation — in that case AGENTS.md files are not attached).
{{< /admonition >}}

## Conversation memory

Everything you discussed with the agent lives in sessions on disk, and once the history approaches the context limit it gets compacted by auto-summarization.

### Sessions on disk

Every conversation is a **session**, fully persisted to disk. The format is JSONL: one message (including tool calls and their results) per line.

| File                     | Contents                                          |
| ------------------------ | ------------------------------------------------- |
| `sessions/<id>.jsonl`    | messages of a single session                      |
| `sessions.json`          | index: id, title, message counter, dates          |

The storage is shared across all projects and sits next to the global data: on Windows `%LOCALAPPDATA%\eonyx\`, on Linux/macOS `$XDG_DATA_HOME/eonyx/` (`~/.local/share/eonyx/` by default). The session id is sortable: `20260705T091500-1a2b3c4d`.

Writing is the source of truth: if a message could not be saved, the turn is aborted rather than continuing "past the disk". Empty sessions (those that never got beyond the system prompt) are cleaned up automatically.

### Working in the TUI

On startup EONYX **resumes the most recent session**. From there:

| Action                | How                                                       |
| --------------------- | --------------------------------------------------------- |
| Session manager       | `Ctrl+S` or `/sessions`                                   |
| Search across sessions| `/sessions <query>` — over titles and message text        |
| New session           | `/new`                                                    |
| Clear the context     | `/clear` — wipes the history, keeping the id and title    |
| Rename                | `r` in the session list or `/rename <title>`              |
| Fork                  | `f` in the session list or `/fork` — a conversation branch|
| Delete                | `d` in the session list                                   |
| Export to markdown    | `/export` → `.eonyx/exports/eonyx-<id>.md`                |

New sessions get simple sequential titles — `1`, `2`, `3`… — until you rename them explicitly; the title never changes automatically.

### Working from the console

```bash
eonyx sessions                  # list: id, date, message count, title
eonyx sessions --search parser  # search over titles and text
eonyx sessions delete <id>      # delete

eonyx run -c "continue"         # continue the most recent session
eonyx run -s <id> "and now…"    # continue a specific one
```

{{< admonition type="tip" title="A fork as a save point" >}}
`Fork` copies the message file into a new session — the original is left unchanged. Handy before a risky direction: fork the conversation, give it a try, and if it did not work out, go back to the original session.
{{< /admonition >}}

### Auto-summarization

If a model has `context_window` set in the config, EONYX tracks the size of the history (estimating ~4 characters per token) and shows a `{ctx N%}` indicator in the header. At **80%** the indicator is highlighted — and summarization triggers at that same threshold.

How it works:

- The last **3 user turns** are kept verbatim; everything older is sent to the model with a request to compact it into a running summary (decisions, facts, changed files, open tasks).
- The summary is appended to the system prompt under the heading `# Summary of earlier conversation`; the next compaction takes the previous summary into account.
- The compaction boundary runs **only along user messages**, so "tool call → result" pairs are never split.
- All of this happens **in memory only**: the JSONL on disk keeps the full history losslessly — an export or a reopened session sees the whole conversation.

{{< admonition type="warning" title="Without context_window there is no summarization" >}}
A model's `context_window` field is the switch for this machinery. If you do not set it, the history grows until the API rejects it. Set the model's real window size in `eonyx.json`.
{{< /admonition >}}

## Summary

{{< admonition type="abstract" title="Cheat sheet" >}}
- **AGENTS.md**
  - project rules; collected up the tree to the project root or `.git`
  - the closest file comes last
- **Sessions**
  - JSONL on disk, shared across all projects
  - resuming (`-c`/`-s`), search, fork (`f`), rename (`r`), export (`/export`)
  - titles are sequential `1`, `2`, `3`; they change only via an explicit `/rename`
- **Summarization**
  - at 80% of `context_window`: older turns are compacted into a summary in the system prompt
  - the disk keeps everything; watch `{ctx N%}` in the header
{{< /admonition >}}

