From 3996eaa41f3743af617cb85e9abdc2b8d8b15ab6 Mon Sep 17 00:00:00 2001 From: omartelo Date: Fri, 21 Aug 2026 19:33:19 -0300 Subject: [PATCH] feat: rename a session from the command line and from an agent's tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Renaming a card was the one session operation only the window could do. spawn.Rename is the same rename from outside it: it resolves a session by either of the names it answers to (the resolver close already had), writes through store.RenameSession — so the row's label_auto is cleared and the provider's auto-title never overwrites the name again — and emits the event the auto-title already emits, which is the whole reason the card relabels live with no new frontend handler. `lich rename "the login bug"` renames the session the command runs in; `lich rename auth-fix "the login bug"` renames another one. The one-argument form is what an agent has: `sessions` shows it every session but its own, so it knows what it is doing long before it knows what its card is called. The `rename_session` tool is the same call. A name another session in that project already holds is refused rather than written: two sessions under one label is the one thing `lich send` cannot resolve, and the guard is what makes a forgotten second argument an error instead of a silent self-rename. The window keeps no such rule — the user is pointing at the card they mean. findSession is now a plain resolver: whether the caller's own session is a legal answer belongs to the caller, so the refusal to close it moved into Close, which is also where it finally got a test. --- CHANGELOG.md | 12 ++ docs/ceilings.md | 7 ++ docs/cli.md | 28 ++++- frontend/src/lib/session/session-events.ts | 7 +- frontend/src/providers/projects.tsx | 4 +- internal/cli/cli.go | 41 +++++++ internal/cli/cli_test.go | 5 + internal/cli/help.go | 7 ++ internal/cli/mcp.go | 25 ++++ internal/cli/mcp_test.go | 47 ++++++++ internal/cli/wire_test.go | 44 +++++++ internal/spawn/close.go | 18 +-- internal/spawn/close_test.go | 13 ++ internal/spawn/rename.go | 105 +++++++++++++++++ internal/spawn/rename_test.go | 131 +++++++++++++++++++++ internal/spawn/spawn.go | 12 +- internal/spawn/spawn_test.go | 15 +++ 17 files changed, 504 insertions(+), 17 deletions(-) create mode 100644 internal/spawn/rename.go create mode 100644 internal/spawn/rename_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 84bbb56a..68ab276d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- **Sessions can be renamed from the command line and from an agent's own + tools.** Renaming a card was a thing only the window could do; `lich rename + "the login bug"` now renames the session the command runs in, `lich rename + auth-fix "the login bug"` renames another one, and the `rename_session` tool is + the same for an agent — which is what lets a worker's card say what the work in + it is rather than the number it was born with. The name becomes the user's + either way: the provider's auto-title never overwrites it again. A name another + session in that project already holds is refused, because two sessions under + one label is the one thing `lich send` cannot resolve. + ### Changed - **Building lich from source now needs Go 1.27.0.** The pin stays exact so that diff --git a/docs/ceilings.md b/docs/ceilings.md index c77ae3c6..172dda20 100644 --- a/docs/ceilings.md +++ b/docs/ceilings.md @@ -103,6 +103,13 @@ work when nobody knows it and that the call site never shows. The mechanism and which is why the install asks its version first. Crush's block and omp's `mcp.json` register lich's MCP server by the absolute path of the binary that installed it, and omp's is a JSON document lich rewrites rather than appends to: every key survives, the user's formatting does not. +- **A new MCP tool reaches opencode a release later than everyone else** (`internal/cli/mcp.go`, `mcpTools`; the + registration table in `docs/cli.md`): every other harness is handed lich's own server, so a tool added here is in + that session's list on the next spawn. opencode cannot register an MCP server from a plugin, so its plugin + defines each tool itself in the companion repo (`omartelo/lich-plugin`, `opencode/lich.js`) — which means a tool + arrives there only once that repo cuts a release and the user reinstalls the plugin, and until they do it is + missing from that session's list while it is in every other. `lich rename` works there like anywhere else; it is + discovery that lags, which is the whole reason the tools exist. - **Only two of the four harnesses that report a tool spell an MCP one splittably** (`frontend/src/lib/session/tool-label.ts`, table in `docs/hooks/session-state.md`): Claude Code and Codex send `mcp____`, which the card draws as ` · `. omp's `mcp___` has one underscore doing two jobs — `mcp__lich_list_sessions` diff --git a/docs/cli.md b/docs/cli.md index e14fa8b5..f48a81c2 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -351,6 +351,29 @@ conversation back up. - Unlike `sessions`, this reaches a card whose terminal was never opened: it is still a session, and closing it is the one thing you can do with it. +### `lich rename [--project ] [--json] []