mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 10:39:32 +01:00
Merge origin/master into relprep/pr-753
Conflict in src/session-cli-registry-bridge.ts: kept the PR's gateVersion() (gates measured against the gated CLI's own version) and added master's Discord startup hint engine value. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
35ff4e886c
138 files changed
+17441
-502
No files matched your search
@@ -15,6 +15,7 @@ A fixed list of files from the data directory (`~/.codeman/`, or the directory o
|
||||
| `clis.json` | CLI enable/disable and custom CLI entries. |
|
||||
| `custom-model-hosts.json` | Saved custom model endpoints. **Holds API keys.** |
|
||||
| `webhook.json` | Webhook notification target. |
|
||||
| `discord.json` | Discord bridge settings. **Holds a bot token.** |
|
||||
| `intents.json` | Read My Mind per-case profiles. |
|
||||
| `linked-cases.json` | Registered cases. |
|
||||
| `remote-hosts.json`, `remote-cases.json`, `docker-hosts.json`, `docker-cases.json` | Remote SSH and Docker overlay configuration. |
|
||||
@@ -188,15 +189,15 @@ that are the same are listed on one line. A file that is not JSON shows only tha
|
||||
a file with more than 200 changes is cut short, so use the files themselves for a full diff. The
|
||||
self-rewritten fields listed under "When a backup is made" are not counted as changes.
|
||||
|
||||
**Credential values are never shown.** `.env`, `users.json`, `push-keys.json`, `webhook.json` (the
|
||||
URL is a bearer secret) and `intents.json` (captured prompts) list only the names that changed, and in every other file a key that looks like a token, secret, password,
|
||||
**Credential values are never shown.** `.env`, `users.json`, `push-keys.json`, `webhook.json` (the URL is a bearer secret), `discord.json` (the
|
||||
bot token) and `intents.json` (captured prompts) list only the names that changed, and in every other file a key that looks like a token, secret, password,
|
||||
credential or key is shown as "changed" without its value. URL values lose any `user:password@`,
|
||||
query and fragment.
|
||||
|
||||
## Security
|
||||
|
||||
- Some tracked files carry credentials (`.env`, `users.json`, `custom-model-hosts.json`,
|
||||
`push-keys.json`, `webhook.json`). Each backup folder is mode `0700` and its files `0600`, so the default
|
||||
`push-keys.json`, `webhook.json`, `discord.json`). Each backup folder is mode `0700` and its files `0600`, so the default
|
||||
location exposes nothing the data directory does not already.
|
||||
- **A custom folder is your decision.** Putting it on a shared drive, a synced folder or a
|
||||
network share copies those credentials there, with whatever permissions that location has.
|
||||
|
||||
@@ -22,11 +22,11 @@ Codeman-side configuration:
|
||||
Three ways to get one, all under **New or link a case…** at the bottom of the case picker
|
||||
(the case dropdown in the bottom toolbar; on a phone, the case sheet's **Create New Case**):
|
||||
|
||||
| How | Result |
|
||||
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Create New** | A fresh `~/codeman-cases/<name>` with a scaffolded `CLAUDE.md`, or with **Create in a custom folder**, a new folder inside a parent you choose, scaffolded the same way and registered in place like a linked case. |
|
||||
| **Clone Repo** | A repo cloned into `~/codeman-cases/<name>` and registered as a case. Private repos need this machine's own git credentials (see below). |
|
||||
| **Link Existing** | An existing folder anywhere on disk, registered in place. Nothing is copied or moved. |
|
||||
| How | Result |
|
||||
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Create New** | A fresh `~/codeman-cases/<name>` with a scaffolded `CLAUDE.md`, or with **Create in a custom folder**, a new folder inside a parent you choose, scaffolded the same way and registered in place like a linked case. |
|
||||
| **Clone Repo** | A repo cloned into `~/codeman-cases/<name>` (or straight into a folder you choose, which must be empty or not exist yet) and registered as a case. Private repos need this machine's own git credentials (see below). |
|
||||
| **Link Existing** | An existing folder anywhere on disk, registered in place. Nothing is copied or moved. |
|
||||
|
||||
Linked cases keep living where they are. Deleting a case in Codeman removes the
|
||||
registration, and for a linked case that is all it removes.
|
||||
|
||||
@@ -27,14 +27,20 @@ hosts — these are machine-level infra, not a per-user setting.
|
||||
shows up without another manual click of **Discover**. One endpoint being unreachable on a
|
||||
given cycle (powered off, wrong network) never blocks the others from refreshing.
|
||||
|
||||
**Context length is picked up automatically where it can be, safely.** Against a
|
||||
llama.cpp/llama-swap server, discovery also learns each _currently loaded_ model's real
|
||||
context window and applies it to the launched session (Claude Code today — see below), so
|
||||
the harness stops assuming a large default window for a model name it doesn't recognise and
|
||||
overflowing a much smaller real one. It's deliberately never probed for a model that isn't
|
||||
already loaded, since asking a llama-swap server about an unloaded model can trigger an
|
||||
actual, slow model swap as a side effect — a model just not currently loaded keeps whatever
|
||||
context length an earlier cycle already learned for it instead.
|
||||
**Context length is picked up automatically where it can be, safely.** Every model's own
|
||||
listing entry is read for a stated context figure (`context_length`, then `context_window`,
|
||||
which current llama.cpp, llama-swap and gateway-style servers state to varying degrees);
|
||||
against a llama-swap server the stronger figures from its launch command and from llama.cpp's
|
||||
`/props` probe win where they exist, and those probes only ever run for a model the server
|
||||
already reports loaded, since asking about an unloaded model can trigger an actual, slow model
|
||||
swap as a side effect. A model that states no figure keeps whatever an earlier cycle learned:
|
||||
the stored figure always beats the endpoint's **Default context length** field
|
||||
(`modelContextLengths[id] ?? defaultContextLength`), which only applies where no figure was
|
||||
ever learned (that number is the model's whole window, never a per-slot figure). A model
|
||||
neither covers simply gets no override, never a guess. The window is applied to the launched session by the harnesses
|
||||
that can take it: Claude Code today (see below), OpenCode as the model's context limit, and
|
||||
Codex as a `model_context_window` entry in its generated config file, which also sets Codex's
|
||||
own auto-compact point via `model_auto_compact_token_limit` at 75% of the window.
|
||||
|
||||
## Running a session against one
|
||||
|
||||
@@ -48,15 +54,20 @@ pointed at.
|
||||
|
||||
**Which model it uses depends on how many the endpoint has discovered.** With exactly one,
|
||||
the session launches straight away on that model — nothing to choose. With two or more, a
|
||||
small dialog asks which one to use for this launch before starting the session; the
|
||||
small dialog asks which one to use for this launch before starting the session; a search box
|
||||
at the top narrows a long list with a case-insensitive substring match, so a server hosting
|
||||
hundreds of models stays usable. The
|
||||
endpoint's default model, if set, is marked but not auto-picked, so a launch can deliberately
|
||||
use a different one without changing the saved default. The list is not raw discovery order
|
||||
either: the model llama-swap reports loaded and ready is moved to the top and tagged
|
||||
**Currently loaded**, and when nothing is loaded, the model you last launched on this harness
|
||||
and endpoint pair is moved up instead and tagged **Last used** (a per-device browser value, so
|
||||
another device starts from its own history). The default model keeps its own **Default** pill
|
||||
in both cases, and nothing is ever auto-chosen: the promoted row is simply the one under your
|
||||
thumb.
|
||||
**Currently loaded**. When nothing is reported loaded, the model one of your own running
|
||||
sessions is using on that endpoint is moved up instead and tagged **In use by a session** (it
|
||||
beats **Last used**, never **Currently loaded**), and failing that the model you last launched
|
||||
on this harness and endpoint pair is moved up and tagged **Last used** (a per-device browser
|
||||
value, so another device starts from its own history). With none of those, a line under the
|
||||
search box says nothing is marked, so the plain list is not mistaken for an answer. The default
|
||||
model keeps its own **Default** pill in every case, and nothing is ever auto-chosen: the
|
||||
promoted row is simply the one under your thumb.
|
||||
|
||||
**For opencode, Codex, Gemini, Pi, Grok, DeepSeek, OMP and GitHub Copilot, picking an entry launches
|
||||
straight onto the endpoint** — no restart, because the endpoint is applied before the
|
||||
@@ -186,7 +197,7 @@ read is treated as one slot, never guessed.
|
||||
| **Claude Code, opencode, Pi, Grok, OMP** | Verified end-to-end against a real local server. |
|
||||
| **Codex** | Config is correct, and plain chat can work against a server that speaks the Responses API — but a real tool-call attempt comes back as inert text instead of running, so it's still not usable for real coding work. |
|
||||
| **Gemini** | Fails with an auth error gemini-cli raises once redirected. Unresolved; don't rely on it yet. |
|
||||
| **DeepSeek** | The original 404 is root-caused and fixed (DeepSeek Harness's own code was missing a `/v1` most local servers require) — not yet re-run against a real `dsh` install to confirm end-to-end. |
|
||||
| **DeepSeek** | Verified end-to-end against a real `dsh` install (dsh 0.1.1-rc.2, dsh-TUI 0.10.0-beta.1): the original 404 is root-caused and fixed, and the redirect is now a generated per-session patch file whose prompt reaches the endpoint as `POST /v1/chat/completions`. Such a session does not carry over your home-level `cordis.patch.yml`, your own `llm-pi-ai` providers, or a profile-level `effort`/`preset`. |
|
||||
| **Antigravity** | No known custom-endpoint mechanism at all. Not offered. |
|
||||
|
||||
Which harnesses show up in the Run-menu picker is read live off Codeman's own CLI registry,
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
# Discord Bridge
|
||||
|
||||
Answer a blocked agent from your phone, from anywhere. Codeman posts to a private Discord
|
||||
server when a session needs you, gives every tab its own thread, and types your reply in that
|
||||
thread into that tab. It only makes outbound connections, so nothing is exposed to the internet
|
||||
and it works when you are away from your network.
|
||||
|
||||
**Opt-in, off by default. One server, one channel, threads per tab.**
|
||||
|
||||
> **Treat the Discord account like a login to the machine.** A reply from an allowed account is
|
||||
> typed into agents that can run shell commands. Turn on 2FA and use a strong, unique password.
|
||||
|
||||
## What it does
|
||||
|
||||
- **Alerts** for permission prompts, questions, idle sessions, errors and a stopped crash loop. A
|
||||
question or permission prompt shows what is on the tab's screen right now, so you can see what is
|
||||
being asked; a finished turn or an error carries the CLI's whole last message.
|
||||
- **One thread per tab** in a parent channel, so a reply always reaches exactly one session.
|
||||
- **Replies** from an allowed user are typed into that tab as one line plus Enter (a single digit answering a waiting permission or question goes as the key alone, without Enter).
|
||||
- **Files** you attach are saved in the tab's folder and the agent is given the path. An agent can
|
||||
send a file back.
|
||||
- **Agents can ask for you.** `codeman notify "Press the reset button on the case" --urgent`
|
||||
posts to the tab's thread. Sessions from the installer or an npm install have the command (a git checkout run without the installer does not); see [below](#telling-the-agents).
|
||||
|
||||
## Set it up
|
||||
|
||||
The full least-privilege walkthrough (private server, bot, the exact permissions, IDs, token
|
||||
handling) is in [docs/discord-bridge.md](https://github.com/Ark0N/Codeman/blob/master/docs/discord-bridge.md).
|
||||
In short:
|
||||
|
||||
1. Make a private Discord server with one text channel, and copy the server, channel and your user IDs.
|
||||
2. Create an application with a bot. Turn **Public Bot** off, turn **Message Content Intent** on, and
|
||||
invite it with the `bot` scope and only the permissions the guide lists (no Administrator).
|
||||
3. In **App Settings → Notifications → Discord**, paste the bot token and the three IDs, press **Save**,
|
||||
then **Send test**, then turn **Talk to your sessions from Discord** on and **Save** again.
|
||||
|
||||
The token is a secret: it is kept in its own file (`~/.codeman/discord.json`, readable by its owner
|
||||
only), never in the shared settings, and never shown again once saved.
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Choices | Default |
|
||||
| ---------------------------------------- | ------------------------------------------- | --------------- |
|
||||
| Create threads | On the first alert, or for every new tab | First alert |
|
||||
| When a tab is deleted | Keep, archive or delete the thread | Archive |
|
||||
| Stale threads | Keep, archive or delete threads no tab uses | Keep |
|
||||
| @ ping | Never, critical events only, every post | Critical only |
|
||||
| Which events | Needs attention, or everything | Needs attention |
|
||||
| Tell Claude how to reach you | On or off | On |
|
||||
|
||||
A finished turn, and an error, is posted as the CLI's whole last message, with its formatting and questions
|
||||
kept, split over several posts if it is long. A shell, and permission or question dialogs, show the last lines
|
||||
of the screen instead.
|
||||
|
||||
Only some CLIs raise a turn end. Claude Code does (an idle alert by default, and a stop alert when **Which
|
||||
events** is Everything), and DeepSeek Harness sends a stop. The others (Codex, OMP, OpenCode, Gemini,
|
||||
Antigravity, Pi, Grok, Copilot) send none, so their messages reach Discord with an error or `codeman notify`;
|
||||
Codex's dialogs are read off its screen.
|
||||
|
||||
The stale-thread setting also archives or deletes threads that **When a tab is deleted** kept or archived, because a
|
||||
deleted tab's thread leaves the bridge's map.
|
||||
|
||||
Deleting a thread needs the **Manage Threads** permission on the channel. "Critical" means a
|
||||
permission prompt, a question, an error, or a post an agent marked urgent.
|
||||
|
||||
## Telling the agents
|
||||
|
||||
An agent only posts deliberately if it knows it can:
|
||||
|
||||
- **Claude** is launched with the instruction as part of its system prompt (**Tell Claude how to reach you**, on by default), so nothing shows in the chat. This reaches local tabs only (remote and Docker tabs have no `codeman` command).
|
||||
- **Every other CLI** is not told. It can still run `codeman notify` if you tell it to.
|
||||
|
||||
Tabs that were already open when you turned the bridge on are not told. The alerts still reach
|
||||
Discord for them; only the agent-initiated `codeman notify` habit is missing.
|
||||
|
||||
## Files
|
||||
|
||||
- **You to the agent:** attach a file to a reply. It is saved as
|
||||
`<tab folder>/.codeman-discord/<message id>-<name>` and the line the agent sees ends with
|
||||
`[attached: <path>]`. At most 5 files of 8 MB each. The folder ignores itself, so nothing in it is committed.
|
||||
- **Agent to you:** `codeman notify "message" --file <path>` uploads a file of at most 8 MB that lies
|
||||
inside the tab's folder. Credential files such as `.env` are refused.
|
||||
- Remote (ssh) tabs have no local folder, so they neither send nor receive files.
|
||||
- A file you send is untrusted content to the agent that opens it.
|
||||
|
||||
## Safety
|
||||
|
||||
- Only user IDs on the allowlist, in your server, inside a thread Codeman made, are acted on.
|
||||
Everything else is dropped.
|
||||
- A reply is cut to one printable line (1000 characters) and limited to one per second per tab.
|
||||
- Posts can ping only the allowlisted users, so agent output cannot ping the whole server.
|
||||
- A Discord outage or a bad token never affects a session; it backs off, and the last error shows in Settings.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Check |
|
||||
| ------------------------------------------------ | -------------------------------------------------------------- |
|
||||
| Send test says 401 | The token is wrong or was reset. Paste the current one. |
|
||||
| Send test says the bot cannot see it | Check the bot's role and the channel ID. |
|
||||
| Posts arrive but replies do nothing | Message Content Intent is off, or your user ID is not allowed. |
|
||||
| Status line says "Message Content Intent is off" | Turn it on in the Developer Portal, Bot tab. |
|
||||
| A thread is not deleted | The bot lacks Manage Threads on the channel. |
|
||||
|
||||
See also: [Notifications And Approvals](Notifications-And-Approvals) for the other ways to hear
|
||||
from an agent, and [Security](Security) for how secrets are handled.
|
||||
@@ -79,6 +79,7 @@ codeman web # then open http://localhost:3000
|
||||
| ------------------------------------------------------------- | --------------------------------------------------- |
|
||||
| [Keeping Agents Running](Keeping-Agents-Running) | How does it run unattended overnight? |
|
||||
| [Notifications And Approvals](Notifications-And-Approvals) | How do I know an agent needs me, and answer from my phone? |
|
||||
| [Discord Bridge](Discord-Bridge) | How do I answer a blocked agent from Discord, in a thread per tab? |
|
||||
| [Cron Jobs](Cron-Jobs) | How do I run an agent on a schedule? |
|
||||
| [Autonomous Loops](Autonomous-Loops) | What are the Ralph and Orchestrator loops for? |
|
||||
| [Watching Agents Work](Watching-Agents-Work) | How do I see what the subagents are doing? |
|
||||
|
||||
@@ -13,6 +13,7 @@ opening the session.
|
||||
| Desktop notification | Another window on the same machine | Opt-in |
|
||||
| Push notification | Anywhere, even with no tab open | Opt-in |
|
||||
| Webhook (ntfy, Slack, Discord) | Anywhere, with no browser or subscription at all | Opt-in |
|
||||
| Discord bridge (two-way) | Anywhere, and you can answer in a thread per tab | Opt-in |
|
||||
| Approvals Inbox | One queue for Claude, Codex and DeepSeek prompts | Opt-in |
|
||||
| Phone overview | Phone home screen, NEEDS YOU section | On |
|
||||
| Away Digest | Afterwards, as a summary | Opt-in |
|
||||
@@ -66,6 +67,11 @@ Setup:
|
||||
|
||||
Once subscribed, a blocking prompt reaches your phone even from a locked screen.
|
||||
|
||||
## Discord bridge: answer from your phone
|
||||
|
||||
A webhook is one-way. To also **reply** to a blocked agent, use the [Discord Bridge](Discord-Bridge): a
|
||||
thread per tab, your reply typed into that tab, files in both directions.
|
||||
|
||||
## Webhooks: ntfy, Slack, Discord
|
||||
|
||||
**Opt-in, off by default. One channel for the whole server.**
|
||||
|
||||
@@ -62,7 +62,7 @@ supervised by systemd or launchd; npm installs report as non-updatable. See
|
||||
Chips for every optional header control, with a live preview of the resulting header:
|
||||
|
||||
Run, Font Size, System Stats, Redraw Terminal, Response Viewer, Away Digest, Session
|
||||
Manager, Attachments, File Viewer, Multi-monitor, Split, Tiles, Plan Usage, Lifecycle Log, Monitor,
|
||||
Manager, Attachments, Edit history, File Viewer, Multi-monitor, Split, Tiles, Plan Usage, Lifecycle Log, Monitor,
|
||||
Project Insights, File Browser, Subagents, Approvals Inbox, Read My Mind, Ultracode Agents,
|
||||
Ultracode Windows, Cron.
|
||||
|
||||
@@ -106,6 +106,12 @@ nothing waits for a login, and that is a default, never an override: your own `G
|
||||
repository's `core.sshCommand`, is used when either is set. ⚠️ The default's `StrictHostKeyChecking=accept-new`
|
||||
records an unknown host key in `~/.ssh/known_hosts` without asking: BatchMode stops a prompt, not a write.
|
||||
|
||||
**Edit history** (per device, off by default, never on phones) adds a header button for the
|
||||
active session's edit history: every edit the agent and its subagents made, with its diff, and
|
||||
images it produced. Local Claude sessions only. Nothing is read until you open the window, and it
|
||||
stores those diffs (secrets included) under `~/.codeman/edit-history/`; see
|
||||
[Working With Files](Working-With-Files#edit-history).
|
||||
|
||||
Most default to off. The stock desktop header is system stats, File Viewer, Tiles, and the gear.
|
||||
**Header Stats Style** picks how the system stats and plan usage are drawn: *Compact*
|
||||
(default; two pills with a ring beside every value), *Tiles* (label over value with a bar underneath) or *As before* (the bars and the `5H · 7D` chip). Desktop only, per device.
|
||||
@@ -214,8 +220,9 @@ how long a desktop notification stays up before Codeman closes it (**Browser
|
||||
notification display time**, default 8; both per device, and your OS may close a
|
||||
desktop notification sooner), the idle
|
||||
threshold that decides when a quiet session counts as needing you, and the server-wide
|
||||
webhook (ntfy, Slack, Discord or generic JSON; admins only in multi-user mode). See
|
||||
[Notifications And Approvals](Notifications-And-Approvals).
|
||||
webhook (ntfy, Slack, Discord or generic JSON; admins only in multi-user mode), and the
|
||||
Discord group for the two-way bot (token, IDs, thread and ping options; see
|
||||
[Discord Bridge](Discord-Bridge)). See [Notifications And Approvals](Notifications-And-Approvals).
|
||||
|
||||
### Voice
|
||||
|
||||
|
||||
@@ -87,7 +87,10 @@ detected at once would fork ten multi-minute converter processes.
|
||||
|
||||
File paths in a session are links. That works in two places:
|
||||
|
||||
- **In the terminal**, on any absolute path an agent prints.
|
||||
- **In the terminal**, on any path an agent or a command prints. A relative path (`src/app.ts`,
|
||||
`../notes.md`) resolves against the directory the session's pane is in now, so after a `cd`
|
||||
in a shell it opens the file there; until the pane reports a directory, and always for remote
|
||||
SSH and Docker cases, it resolves against the session's working directory.
|
||||
- **In the response viewer**, where paths are usually written as prose or in backticks. They
|
||||
render as underlined monospace links. A Markdown link whose target is a path
|
||||
(`[report](/tmp/run/report.json)`, the way Codex cites files) opens the same way.
|
||||
@@ -168,6 +171,11 @@ choice is remembered per device. The picker inserts the path into your prompt
|
||||
**without** pressing Enter, so nothing is submitted by accident. Its sibling **⌫ All**
|
||||
key clears the unsent prompt, and never sends the agent's `/clear` command.
|
||||
|
||||
In **Link Existing**'s picker, **+📁** (New folder) makes a folder inside the folder you
|
||||
are viewing and selects it. Names use letters, numbers, spaces and `_ - . ~` (not starting
|
||||
with a dot or `~`). The cases folder is refused, since every folder there is already a
|
||||
case: use **Add Case → New Case** instead.
|
||||
|
||||
This is a separate file-serving surface from the viewer, with its own rules: it allowlists
|
||||
your home directory, the cases directory, and anything in `CODEMAN_FILE_PICKER_ROOTS`, and
|
||||
blocks sensitive trees. In multi-user mode a non-admin gets only their own user space as a
|
||||
@@ -272,6 +280,60 @@ data comes from `GET /api/sessions/:id/git-status`, `GET /api/sessions/:id/git-d
|
||||
click or the interval you turned on, `POST /api/sessions/:id/git-fetch`
|
||||
(see the [API reference](https://github.com/Ark0N/Codeman/blob/master/docs/api-reference.md)).
|
||||
|
||||
## Edit history
|
||||
|
||||
The Git panel shows what is different now. The edit history shows what the agent did, one edit
|
||||
at a time, including edits that were later undone or committed. Turn on **App Settings → Header &
|
||||
Panels → Header → Edit history** (per device, off by default) and a clock button appears in the
|
||||
header next to Attachments. It is not shown on phones.
|
||||
|
||||
Click it for a draggable window listing the active session's edits, newest first:
|
||||
|
||||
- One row per Edit or Write, with `new` for a file the agent created, `edit` otherwise,
|
||||
and the lines added and removed. **Click a row** to see that edit's diff inline, coloured like the
|
||||
Git panel; a diff over 64 KB is cut short. **Click the path** to open the file in the preview.
|
||||
- Edits made by subagents carry a chip with the subagent's task; hover it for the agent type and
|
||||
its worktree branch. **Main agent only** hides them. **Group by file** puts the edits under
|
||||
their file, with the totals on the file's row.
|
||||
- Images an agent produced with a shell command (a render, a plot, a screenshot) appear as rows with
|
||||
a thumbnail: a `.png`, `.jpg`, `.gif`, `.webp`, `.avif` or `.svg` path named in the command or
|
||||
its output counts when the file's modification time falls within that command's run. Images the
|
||||
agent sent you count as well. Images outside the workspace and SVGs show no thumbnail. Click one
|
||||
to open it in the preview.
|
||||
- **Load older** reads further back in the conversation, in the main agent's transcript and the
|
||||
subagents' alike (up to three transcripts per click; with more, they take turns).
|
||||
- After `/clear` or a resume, the edits of the earlier conversation stay listed, and the window
|
||||
first catches up on the ones it had not read yet. **Load older** then goes back within the new
|
||||
conversation.
|
||||
|
||||
It works for local Claude sessions only. Remote (SSH), Docker and other CLIs' sessions say so instead.
|
||||
|
||||
How it reads:
|
||||
|
||||
- **Only while you look.** The history is read from the session's Claude transcript when you open
|
||||
the window, and again after each tool call that can change files and at the end of each turn,
|
||||
while it stays open on that session. A closed window reads nothing, and Codeman does no work in
|
||||
the background for sessions nobody looks at.
|
||||
- **The transcript is found through the session's hooks.** Each prompt tells Codeman where the
|
||||
session's transcript is. Right after a server restart, before the next prompt, Codeman looks in
|
||||
the session's `CLAUDE_CONFIG_DIR` if you set one for it in Codeman, else in the default config
|
||||
directory. A `CLAUDE_CONFIG_DIR` set outside Codeman (in a shell profile or a wrapper script)
|
||||
is only known after the next prompt; until then the window says "No transcript found for this
|
||||
session yet".
|
||||
- **The history is stored, and it holds secrets.** Every diff an agent wrote is copied to
|
||||
`~/.codeman/edit-history/<session-id>.json`, including API keys or `.env` contents it edited. The file is
|
||||
readable by your user only, capped at 500 edits and 4 MiB of diff text per session (the oldest
|
||||
are dropped), never part of search, blocked from every file route, and deleted when you delete
|
||||
the session (a file left behind, by a crash for instance, goes at the next start). A pinned session you kill keeps its record and its history until you unpin and
|
||||
delete it.
|
||||
- **Images go through the existing file routes.** A thumbnail inside the workspace uses the File
|
||||
Viewer's route. An image outside it opens like any clicked path outside the workspace (no
|
||||
notification, same file-type allowlist and sensitive-file blocklist). No new route serves a file.
|
||||
|
||||
The data comes from `GET /api/sessions/:id/edits`, `GET /api/sessions/:id/edits/:entryId` and
|
||||
`POST /api/sessions/:id/edits/older` (see the
|
||||
[API reference](https://github.com/Ark0N/Codeman/blob/master/docs/api-reference.md)).
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **The viewer follows the active session's workspace.** Switching tabs changes what you are
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
- [Unattended Runs](Keeping-Agents-Running)
|
||||
- [Notifications & Approvals](Notifications-And-Approvals)
|
||||
- [Discord Bridge](Discord-Bridge)
|
||||
- [Cron Jobs](Cron-Jobs)
|
||||
- [Autonomous Loops](Autonomous-Loops)
|
||||
- [Watching Agents Work](Watching-Agents-Work)
|
||||
|
||||
Reference in new issue
Block a user