sesh-cli
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesesesh CLI skill
sesh CLI 技能
Use this skill when the user wants to use (manage their
coding-agent sessions), not develop sesh itself.
seshseshsesh-daemonsesh当用户想要使用(管理他们的coding-agent会话)而非开发sesh本身时,使用本技能。
seshseshsesh-daemonseshShort UUIDs
短UUID
Every command that takes a also accepts a short prefix — the
first 8 characters (or any unambiguous prefix). For example, if a session's
UUID is , you can use or even if that prefix is
unique:
<uuid>a808a699-…a808a699a808bash
sesh info a808a699 # same as sesh info a808a699-xxxx-xxxx-xxxx-xxxx
sesh send a808a699 "hello"
sesh pane-capture a808 # only if a808 uniquely identifies one sessionIf a prefix matches multiple sessions, non-archived sessions win. If the
tie is still ambiguous (multiple non-archived, or multiple archived with no
active match), the command errors and lists all matching UUIDs.
Use to explore matches before acting:
sesh find <prefix>bash
sesh find a808 # list every session whose UUID starts with a808所有接受参数的命令也支持短前缀——UUID的前8个字符(或任何无歧义的前缀)。例如,如果某个会话的UUID是,你可以使用,甚至在该前缀唯一的情况下使用:
<uuid>a808a699-…a808a699a808bash
sesh info a808a699 # 等同于 sesh info a808a699-xxxx-xxxx-xxxx-xxxx
sesh send a808a699 "hello"
sesh pane-capture a808 # 仅当a808能唯一标识一个会话时可用如果某个前缀匹配多个会话,未归档会话优先。如果仍存在歧义(多个未归档会话,或多个归档会话且无活跃匹配项),命令会报错并列出所有匹配的UUID。
使用在执行操作前查看匹配项:
sesh find <prefix>bash
sesh find a808 # 列出所有UUID以a808开头的会话Before running commands
执行命令前须知
- Read-only — safe to run anytime: ,
list,find,info,state,pane,pane-resolve,tags,tail,transcript,doctor,daemon status(listing),peer/pick(interactive; they emit a selection, they don't mutate).tui - Mutating / side-effecting — confirm intent first: (spawns an agent),
new,register,rename/tag/untag,retag/archive,unarchive,delete(messages the agent),send,abort,compact,autoname,autoname-toggle(switches/launches tmux),resume,copy/backup/restore,import,daemon start/stop/restart.peer add/remove - Be especially careful with:
- — removes the record (a tombstone propagates across the mesh).
delete <uuid>tombstones a sesh this machine doesn't own (orphan cleanup); only use it when the owning machine is gone. Once deleted, the session is gone everywhere: it is no longer resolvable (by full UUID or short prefix) and all reads/mutations on it report "not found" (exit 1).--force - — actually drives the agent.
send <uuid> <message> - — one-shot migration of v1
import.~/.sesh/sessions.json
- 只读命令——随时可安全执行:、
list、find、info、state、pane、pane-resolve、tags、tail、transcript、doctor、daemon status(列出节点)、peer/pick(交互式;仅输出选择结果,不修改数据)。tui - 修改类/有副作用命令——请先确认意图:(启动Agent)、
new、register、rename/tag/untag、retag/archive、unarchive、delete(给Agent发送消息)、send、abort、compact、autoname、autoname-toggle(切换/启动tmux)、resume、copy/backup/restore、import、daemon start/stop/restart。peer add/remove - 尤其需要注意以下命令:
- ——删除会话记录(墓碑标记会在网格中传播)。
delete <uuid>参数用于标记本机不拥有的会话(清理孤立会话);仅在会话所属机器已下线时使用。一旦删除,会话将在所有机器上消失:无法通过完整UUID或短前缀找到,所有对该会话的读取/修改操作都会返回“未找到”(退出码1)。--force - ——直接驱动Agent执行操作。
send <uuid> <message> - ——一次性迁移v1版本的
import文件。~/.sesh/sessions.json
Core concepts
核心概念
- UUID & short id. Each session has a UUID. The "short id" is the part
up to the first (e.g.
-); the TUI shows it and most users refer to sessions by it. Commands accept the full UUID.a42f8a74 - Machine = origin. Every record carries the machine that owns it
(). The owning machine is the single writer for it. Reads work from anywhere (the mesh synced the record locally). Everything else routes cross-machine through one owner-routing seam — run it from any machine that peers with the owner and it's forwarded to the owner's daemon, which applies it and (for a mutation) propagates the updated record back. This covers record mutations (
$SESH_MACHINE/rename/tag/untag/retag/archive/unarchive/delete), agent actions (autoname-toggle/send/abort), and transcript reads (compact/tail/transcript). You no longer have to ssh to the owner to mutate or read a remote session. (A termux-owned session still can't be reached from a server that termux doesn't dial back — that errors clearly.autonamefor an orphan whose owner is gone stays local, since there's no owner to forward to.)delete --force - Live vs detached. "Live" = the session currently has a tmux pane (the
walker found it); "detached" = no pane. The glyphs: live+idle,
●live+busy,◐detached.○ - Archived is orthogonal to live/busy — an archived session can still be live. Views: active (default), archived, all.
- Agents: ,
claude,pi. Some verbs are agent-specific (codex/abortare pi-only).compact
- UUID与短ID:每个会话都有一个UUID。“短ID”是第一个之前的部分(例如
-);TUI会显示短ID,大多数用户也通过短ID指代会话。命令接受完整UUID作为参数。a42f8a74 - 机器=源节点:每条记录都携带其所属机器的标识()。所属机器是该记录的唯一写入方。读取操作可在任意机器上进行(网格已将记录同步到本地)。所有跨机器操作都通过单一源节点路由层转发——在任何与源节点连通的机器上执行命令,都会转发到源节点的守护进程,由其执行操作并(针对修改类命令)将更新后的记录同步回网格。这涵盖了记录修改操作(
$SESH_MACHINE/rename/tag/untag/retag/archive/unarchive/delete)、Agent操作(autoname-toggle/send/abort)以及转录读取操作(compact/tail/transcript)。你无需通过SSH登录到源节点即可修改或读取远程会话。 (Termux所属的会话仍无法被未反向连接的服务器访问——此类情况会明确报错。针对已下线源节点的孤立会话执行autoname仅在本地生效,因为没有可转发的源节点。)delete --force - 活跃与分离状态:“活跃”指会话当前拥有tmux窗格(遍历器已找到);“分离”指无窗格。状态图标:活跃+空闲、
●活跃+忙碌、◐分离。○ - 归档状态独立于活跃/忙碌状态——已归档的会话仍可处于活跃状态。视图选项:活跃(默认)、归档、全部。
- Agent类型:、
claude、pi。部分命令是Agent专属的(codex/abort仅适用于pi)。compact
The TUI — sesh tui
(the primary interface)
sesh tuiTUI界面——sesh tui
(主界面)
sesh tuiFull-screen manager over every machine's sessions, with live updates.
Columns: id · name · cwd · agent · machine · socket · tags · created
(rows sort by creation time, earliest→latest). The name (blue) and cwd
(green) columns are color-accented so they stand out; archived rows are
dimmed gray and the cursor row is reverse-highlighted.
Keys: /// move · fuzzy-filter · cycle
active/archived/all · toggle the id column · show full UUID popup ·
archive · unarchive · rename · add-tag · remove-tag ·
delete · select · / quit.
↑↓jkCtrl-jCtrl-k/TabiyaurtxdEnterqEscsesh tuiEntersesh tui --enter全屏管理所有机器的会话,并支持实时更新。列项:id · 名称 · 工作目录(cwd) · Agent类型 · 机器 · 套接字 · 标签 · 创建时间(行按创建时间排序,从最早到最新)。名称(蓝色)和工作目录(绿色)列带有颜色高亮,以便区分;归档行显示为灰色,光标所在行显示为反色高亮。
快捷键:/// 移动光标 · 模糊过滤 · 切换活跃/归档/全部视图 · 切换ID列显示 · 显示完整UUID弹窗 · 归档会话 · 取消归档 · 重命名 · 添加标签 · 删除标签 · 删除会话 · 选择会话 · / 退出。
↑↓jkCtrl-jCtrl-k/TabiyaurtxdEnterqEscsesh tuiEntersesh tui --enterEntering / resuming a session
进入/恢复会话
bash
sesh resume <uuid> # live → switch to its pane; detached → resume the agent
sesh resume <uuid> --target socket:sess # create that tmux session (if absent) + open a window
sesh resume # no uuid → interactive picker
sesh pick # pick a session; print the selection (json/nul/kv) on stdout
sesh pick --select <uuid> --enter # non-interactive enter of a specific seshresumepicktuitmux switch-clientattachsesh-tuisesh-enterbash
sesh resume <uuid> # 活跃会话→切换到对应窗格;分离会话→恢复Agent
sesh resume <uuid> --target socket:sess # 创建指定tmux会话(若不存在)并打开窗口
sesh resume # 无uuid参数→交互式选择器
sesh pick # 选择会话;在标准输出打印选择结果(json/nul/kv格式)
sesh pick --select <uuid> --enter # 非交互式进入指定会话resumepicktuitmux switch-clientattachsesh-tuisesh-enterListing & inspecting
列出与查看会话
bash
sesh list # active sessions, all machines
sesh list --machine <name> # one machine
sesh list --archived # include archived (alias: --include-archived)
sesh list --agent claude --tag work # filters
sesh list --columns uuid,name,agent,machine,status,cwd,tags,archived,tmux-socket,tmux-session,tmux-window,tmux-pane,live # TSV for fzf/awk (unknown column name errors)
sesh find <partial-uuid> # list all sessions (including archived) matching a UUID prefix
sesh info <uuid> [--json] # full record
sesh state <uuid> # turnStatus + per-agent extras
sesh tags # all tags in use across the mesh (every machine)
sesh tail <uuid> [-n N] # last N transcript lines (any machine; forwards to the owner)
sesh transcript <uuid> # full transcript (any machine; forwards to the owner)
sesh pane [--pane %ID] [--socket-path P] # which REGISTERED sesh owns a tmux pane (store-backed; status bars)
sesh pane-resolve --pane %ID --socket-path P # uuid of the agent LIVE in a pane, registered or not (walker-backed)
sesh pane-capture <uuid> [-n N] # capture current pane text (local; for inspecting stuck TUI state)
sesh pane-keys <uuid> <key>... # send raw tmux key names to a pane (local; for navigating TUI prompts)panepane-resolvepanepane-resolveuuid=$(sesh pane-resolve …) && sesh register "$uuid" …agents --jsonpane--json{uuid, agent, cwd, machine, tmux}034All output uses camelCase keys. and each element of
/ are the full session record:
. To check a tombstone:
.
--jsoninfo --jsonlist --jsonfind --json{uuid, name, agent, machine, cwd, turnStatus, archived, autoRename, summary, lastAutoNameTurnCount, contextPct, filePath, tmux:{socket, session, window, pane}, createdAt, updatedAt, originSeq, tags, deleted}sesh info <uuid> --json | grep '"deleted": true'pane-capturepane-keysbash
sesh list # 所有机器的活跃会话
sesh list --machine <name> # 指定机器的会话
sesh list --archived # 包含归档会话(别名:--include-archived)
sesh list --agent claude --tag work # 过滤条件
sesh list --columns uuid,name,agent,machine,status,cwd,tags,archived,tmux-socket,tmux-session,tmux-window,tmux-pane,live # 生成TSV格式输出,供fzf/awk使用(未知列名会报错)
sesh find <partial-uuid> # 列出所有UUID前缀匹配的会话(包括归档会话)
sesh info <uuid> [--json] # 完整会话记录
sesh state <uuid> # 会话状态+Agent专属信息
sesh tags # 网格中所有机器使用的标签
sesh tail <uuid> [-n N] # 最后N行转录内容(任意机器;转发到源节点)
sesh transcript <uuid> # 完整转录内容(任意机器;转发到源节点)
sesh pane [--pane %ID] [--socket-path P] # 哪个已注册的sesh会话拥有指定tmux窗格(基于存储;适用于状态栏)
sesh pane-resolve --pane %ID --socket-path P # 窗格中活跃Agent的uuid,无论是否注册(基于遍历器)
sesh pane-capture <uuid> [-n N] # 捕获当前窗格文本(本地;用于查看卡住的TUI状态)
sesh pane-keys <uuid> <key>... # 向窗格发送原始tmux按键名称(本地;用于导航TUI提示)panepane-resolvepanepane-resolveuuid=$(sesh pane-resolve …) && sesh register "$uuid" …agents --jsonpane--json{uuid, agent, cwd, machine, tmux}034所有输出使用**驼峰式(camelCase)**键名。以及/的每个元素都是完整的会话记录:。检查墓碑标记:。
--jsoninfo --jsonlist --jsonfind --json{uuid, name, agent, machine, cwd, turnStatus, archived, autoRename, summary, lastAutoNameTurnCount, contextPct, filePath, tmux:{socket, session, window, pane}, createdAt, updatedAt, originSeq, tags, deleted}sesh info <uuid> --json | grep '"deleted": true'pane-capturepane-keysStartup prompts that can block a freshly-spawned claude session
新启动的claude会话可能遇到的启动提示
When spawning a claude session in a directory whose imports files
outside the cwd (e.g. ), claude may open to an
interactive confirmation:
CLAUDE.md@~/.config/AGENTS.mdAllow external CLAUDE.md file imports?
> 1. Yes, allow external imports
2. No, disable external imports
Enter to confirm · Esc to cancelsesh sendbash
sesh pane-capture <uuid> # confirm the prompt is showing
sesh pane-keys <uuid> Enter # confirm option 1 (already selected)在当前目录的引用了工作目录外文件(例如)的情况下启动claude会话时,claude可能会弹出交互式确认提示:
CLAUDE.md@~/.config/AGENTS.mdAllow external CLAUDE.md file imports?
> 1. Yes, allow external imports
2. No, disable external imports
Enter to confirm · Esc to cancel在此提示可见时,无法工作——Agent尚未初始化。解决方法:
sesh sendbash
sesh pane-capture <uuid> # 确认提示已出现
sesh pane-keys <uuid> Enter # 确认选择选项1(已默认选中)wait a moment, then:
等待片刻后:
sesh send <uuid> "your first message"
If you spawn frequently in the same directory and keep hitting this prompt,
configure the acceptance globally:
- Accept it once interactively in a manually-opened claude session; claude
remembers the answer per-project in `~/.claude/projects/<dir>/settings.json`.
- Or set `allowExternalImports: true` in your `~/.claude/settings.json`.sesh send <uuid> "your first message"
如果你经常在同一目录启动会话并遇到此提示,可全局配置自动确认:
- 在手动打开的claude会话中交互式确认一次;claude会在`~/.claude/projects/<dir>/settings.json`中记住每个项目的设置。
- 或在`~/.claude/settings.json`中设置`allowExternalImports: true`。Lifecycle (run from anywhere — mutations forward to the owner)
会话生命周期(可在任意机器运行——修改操作会转发到源节点)
bash
sesh new --agent claude --name foo --tag work [-- agent-args...] # spawn + register from birth; cwd defaults to $PWD
sesh new --agent claude --model opus # launch with a specific model (see "Model selection")
sesh new --agent claude --target socket:sess --msg "greet me" --name foo # spawn window + send initial message, print reply
sesh new --agent pi --dry-run # print the plan, register nothing (add --json for a JSON plan)
sesh new --agent claude --no-launch # register only
sesh new --agent claude --session-id <uuid> --no-launch # pre-assign the UUID (must be a well-formed UUID)
sesh new --agent claude --cwd ./sub # --cwd is absolutized to a realpath (relative is resolved against $PWD)
sesh new --headless --agent claude --msg "do X" --name child # persistent headless child (no tmux window)
sesh register <session-id> --agent pi --name foo # record an already-running agent; --cwd defaults to $PWD
sesh rename <uuid> <name> # sets autoRename=false (unless --keep-auto)
sesh tag <uuid> <tag>... / sesh untag <uuid> <tag>... / sesh retag <uuid> old=new # empty/whitespace tag names are rejected (e.g. tag '' or retag old=)
sesh archive <uuid> / sesh unarchive <uuid> # orthogonal to live/busy
sesh delete <uuid> [--force] # tombstone (propagates); --force for an orphanNote: can't pre-assign a session id, so interactive is unsupported — start it and . ( and DO work — they recover the id
from codex's own output.)
codexnew --agent codexsesh registernew --headless --agent codexdelegate --agent codexbash
sesh new --agent claude --name foo --tag work [-- agent-args...] # 启动并注册会话;工作目录默认当前目录
sesh new --agent claude --model opus # 使用指定模型启动(参见“模型选择”)
sesh new --agent claude --target socket:sess --msg "greet me" --name foo # 创建窗口并发送初始消息,打印回复
sesh new --agent pi --dry-run # 打印计划,不注册会话(添加--json参数可输出JSON格式计划)
sesh new --agent claude --no-launch # 仅注册会话
sesh new --agent claude --session-id <uuid> --no-launch # 预分配UUID(必须是格式正确的UUID)
sesh new --agent claude --cwd ./sub # --cwd会解析为绝对路径(相对路径基于当前目录解析)
sesh new --headless --agent claude --msg "do X" --name child # 持久化无头子会话(无tmux窗口)
sesh register <session-id> --agent pi --name foo # 记录已在运行的Agent;工作目录默认当前目录
sesh rename <uuid> <name> # 设置autoRename=false(除非使用--keep-auto参数)
sesh tag <uuid> <tag>... / sesh untag <uuid> <tag>... / sesh retag <uuid> old=new # 空标签或空白标签会被拒绝(例如tag ''或retag old=)
sesh archive <uuid> / sesh unarchive <uuid> # 独立于活跃/忙碌状态
sesh delete <uuid> [--force] # 标记墓碑(会在网格中传播);--force用于处理孤立会话注意:无法预分配会话ID,因此不支持交互式——请先启动codex,再执行。(和可以正常工作——它们从codex的输出中恢复ID。)
codexnew --agent codexsesh registernew --headless --agent codexdelegate --agent codexSpawning child agents — new --headless
and delegate
new --headlessdelegate启动子Agent——new --headless
与delegate
new --headlessdelegateTwo ways for one agent to spawn another (e.g. a parent agent farming out
work). Both run the agent non-interactively — no tmux window:
bash
undefined有两种方式让一个Agent启动另一个Agent(例如父Agent分配任务)。两种方式都以非交互式运行Agent——无tmux窗口:
bash
undefinedPERSISTENT child you keep talking to. Runs the first turn (--msg), creates
持久化子会话,可反复对话。执行第一轮交互(--msg),在磁盘上创建会话,注册会话,打印回复。之后可使用sesh send <uuid>
以无头模式恢复会话。仅适用于claude/codex。
sesh send <uuid>the session on disk, registers it, prints the reply. Later `sesh send
—
<uuid>` resumes it headlessly. claude/codex only.
—
sesh new --headless --agent claude --msg "You are my test runner. Reply READY." --name runner
sesh send <uuid> "run the suite and summarise failures" # talk to it over time
sesh new --headless --agent claude --msg "You are my test runner. Reply READY." --name runner
sesh send <uuid> "run the suite and summarise failures" # 后续对话
EPHEMERAL one-shot: spawn a worker, give it ONE task, print the reply, then
临时一次性会话:启动Worker,分配一个任务,打印回复,然后删除会话。⚠️会话返回结果后会消失——后续无法访问(使用--keep参数可保留会话)。适用于pi、claude和codex。
DELETE the session. ⚠️ The session DISAPPEARS once it returns — it is gone
—
afterward (use --keep to retain it). pi, claude, and codex.
—
sesh delegate --agent codex "What is 2+2? Reply with just the number."
sesh delegate --agent claude --keep --name audit "audit auth.go for bugs" # keep the session
- **`new --headless`** is for a child you'll converse with repeatedly;
**`delegate`** is for "do this one thing and tell me the answer." Reach for
delegate unless you need to follow up.
- `--headless` requires `--msg` (the first turn is what creates the on-disk
session). **pi can't run headless** (it needs a live terminal to serve its
rpc socket) — `new --headless --agent pi` errors; use `delegate --agent pi`
(one-shot) or interactive `new --agent pi` instead. pi works fine with
`delegate` because that's a single `pi -p` turn.
- **`--msg` also works for non-headless (tmux) spawns** — requires `--target`
or a running `$TMUX` session. Waits for the agent to appear live in its pane,
then delivers the message and prints the reply. Incompatible with `--no-launch`.
- delegate's worker runs read-only-ish (codex `--sandbox read-only`); it's
meant to answer, not mutate your workspace unattended.sesh delegate --agent codex "What is 2+2? Reply with just the number."
sesh delegate --agent claude --keep --name audit "audit auth.go for bugs" # 保留会话
- **`new --headless`**适用于需要反复对话的子Agent;**`delegate`**适用于“完成这一项任务并返回结果”的场景。除非需要后续跟进,否则优先使用delegate。
- `--headless`需要配合`--msg`参数(第一轮交互会在磁盘上创建会话)。**pi无法以无头模式运行**(需要活跃终端来提供rpc套接字)——`new --headless --agent pi`会报错;请使用`delegate --agent pi`(一次性任务)或交互式`new --agent pi`。pi可以正常使用`delegate`,因为这是单次`pi -p`交互。
- **`--msg`也适用于非无头(tmux)启动**——需要`--target`参数或正在运行的`$TMUX`会话。等待Agent在窗格中变为活跃状态,然后发送消息并打印回复。与`--no-launch`参数不兼容。
- delegate的Worker以只读模式运行(codex使用`--sandbox read-only`);仅用于返回结果,不会无人值守地修改你的工作区。Model selection — --model
(set at launch)
--model模型选择——--model
(启动时设置)
--modelsesh newsesh delegate--modelclaude/codex/pi --model-mbash
sesh new --agent claude --model opus # alias or full id (sonnet, opus, claude-opus-4-8)
sesh new --agent pi --model sonnet:high # pi patterns: provider/id, alias, :<thinking>
sesh delegate --agent codex --model gpt-5.4 "…" # codex model idDefaults via — set a default model per agent (with
an optional global fallback) so you don't pass every time:
~/.sesh/config.toml--modeltoml
[models]
default = "opus" # fallback for any agent when it has no specific default
claude = "opus"
codex = "gpt-5.5"
pi = "anthropic/claude-opus-4-7"Precedence: flag > > > the
agent's own built-in default (no flag passed). (pi) /
/ codex docs enumerate valid names.
--model[models].<agent>[models].default--list-modelsclaude --helpScope notes:
- This sets the model at the start of a session only. There is no command
to change a running/existing session's model; switch it inside the agent
(claude , codex/pi
/modelpicker)./model - is unsupported regardless (no pre-assignable id), but
new --agent codexworks.delegate --agent codex --model …
Agent binary location via — override where sesh looks for each
agent's CLI binary. By default sesh resolves // against the
daemon's PATH augmented with common version-manager shim dirs (mise/asdf,
, , …). If your binary lives somewhere exotic — or
the daemon's PATH lacks the shims dir holding it (the spawn-works /
resume-fails asymmetry) — declare the path explicitly:
[agents]claudecodexpi~/.local/bin~/.cargo/bintoml
[agents]
claude = "/opt/tools/claude"
codex = "/home/me/.local/share/mise/shims/codex"
pi = "/home/me/bin/pi"Precedence: config path (if set and an executable file) >
PATH/shim-dir heuristic > loud not-found error. A configured path that is NOT
an executable file is a loud error naming the path (no silent fallback) — fix
or remove the override.
[agents].<agent>sesh newsesh delegate--modelclaude/codex/pi --model-mbash
sesh new --agent claude --model opus # 别名或完整ID(sonnet、opus、claude-opus-4-8)
sesh new --agent pi --model sonnet:high # pi的模型格式:provider/id、别名、:<thinking>
sesh delegate --agent codex --model gpt-5.4 "…" # codex模型ID通过设置默认模型——可为每个Agent设置默认模型(可选全局 fallback),无需每次都传递参数:
~/.sesh/config.toml--modeltoml
[models]
default = "opus" # 当Agent无特定默认模型时使用的全局 fallback
claude = "opus"
codex = "gpt-5.5"
pi = "anthropic/claude-opus-4-7"优先级:参数 > 配置 > 配置 > Agent自身的内置默认值(未传递参数时)。(pi)//codex文档列出了所有有效模型名称。
--model[models].<agent>[models].default--list-modelsclaude --help范围说明:
- 仅在会话启动时设置模型。没有命令可以修改正在运行/已存在会话的模型;请在Agent内部切换模型(claude使用,codex/pi使用
/model选择器)。/model - 无论如何都不被支持(无法预分配ID),但
new --agent codex可以正常工作。delegate --agent codex --model …
通过配置Agent二进制文件路径——覆盖sesh查找各Agent CLI二进制文件的位置。默认情况下,sesh会在守护进程的PATH中查找//,并补充常见版本管理器的shim目录(mise/asdf、、等)。如果你的二进制文件位于特殊位置——或守护进程的PATH中缺少包含该文件的shim目录(启动正常但恢复失败的不对称问题)——请显式声明路径:
[agents]claudecodexpi~/.local/bin~/.cargo/bintoml
[agents]
claude = "/opt/tools/claude"
codex = "/home/me/.local/share/mise/shims/codex"
pi = "/home/me/bin/pi"优先级:配置的路径(如果已设置且为可执行文件) > PATH/shim目录启发式查找 > 明确的未找到错误。如果配置的路径不是可执行文件,会直接报错并显示该路径(无静默 fallback)——请修复或移除该配置。
[agents].<agent>Driving the agent
驱动Agent
bash
sesh send <uuid> <message> # send a message and return the agent's reply (two-way; see below)
sesh send <uuid> <message> --no-wait # deliver only; don't await or print a replybash
sesh send <uuid> <message> # 发送消息并返回Agent的回复(双向交互;参见下文)
sesh send <uuid> <message> --no-wait # 仅发送消息;不等待或打印回复An empty/whitespace-only <message> is rejected up-front with "message is empty".
空消息或仅包含空白字符的消息会被直接拒绝,提示“message is empty”。
sesh await <uuid> [--timeout D] # block until the turn completes (busy → idle), print the status (D=0 means no limit; a negative D is rejected)
sesh abort <uuid> # abort current operation (pi-only)
sesh compact <uuid> # trigger context compaction (pi-only)
sesh autoname <uuid> # auto-generate a name via
sesh autoname --all # auto-name every nameable session in the mesh; un-nameable ones (no transcript yet) are skipped, the rest still named
sesh autoname-toggle <uuid> [--on|--off]
pi -p
`send`/`abort`/`compact` (and the mutations and transcript reads above) route
to the owning machine through the one owner-routing seam, so they work on a
session anywhere in the mesh (not just local).
**`send` is two-way for all three agents** — by default it blocks until the
agent finishes its turn and prints the reply. How the reply is obtained
depends on the agent and whether the session is live in a tmux pane:
- **pi** — delivered over its socket; returns the streamed reply (works even
when detached/headless).
- **claude / codex, live in a pane (attached)** — the message is typed into
the live pane (so a human watching sees it, and the conversation isn't
forked), then `send` waits for the turn to finish and returns the last
assistant message.
- **claude / codex, detached (no live pane)** — the session is resumed
**headlessly** (`claude -p --resume` / `codex exec resume`) and the reply
is returned. (codex runs read-only with no approval prompts; claude resume
is cwd-scoped, so the session's recorded `cwd` must still exist.)
> Caveat (exp14): never headless-resume a claude/codex session that is also
> live in a pane — it forks the in-memory conversation. `sesh` avoids this
> automatically by typing into the pane whenever one is live; the headless
> path is taken only for detached sessions.
**`--no-wait`** makes `send` fire-and-forget: it delivers the message and
returns immediately without awaiting the turn or printing a reply (it still
errors if *delivery* fails). For a detached claude/codex this launches the
headless turn in the background, so turn-time errors are logged by the
daemon, not surfaced to the caller. Use it when you just want to nudge an
agent and not block.
**`await`** is a pure read on the mesh-synced `turnStatus`, so it works for a
session on any machine with no forwarding; an already-idle session returns
immediately. It's mostly useful for observing a turn you didn't start (a
human-driven session, or one nudged with `send --no-wait`) — a plain `send`
already waits. Caveat: if a human is also driving the session, `await`
returns on whichever turn finishes first. `--timeout 0` (the default) waits
forever; a *negative* `--timeout` is rejected with a clear error rather than
silently behaving like "no limit".
**`autoname --all`** auto-names every nameable non-archived session across the
mesh (renames forward to each owner). A session that can't be named yet — most
commonly a freshly-registered one with no transcript on disk — is *skipped*
(reported on stderr) and the rest are still named; the batch does not abort on
the first such session. Naming a single explicit `<uuid>` still surfaces its
error.sesh await <uuid> [--timeout D] # 阻塞直到会话完成当前轮次(忙碌→空闲),打印状态(D=0表示无时间限制;负数D会被拒绝)
sesh abort <uuid> # 中止当前操作(仅适用于pi)
sesh compact <uuid> # 触发上下文压缩(仅适用于pi)
sesh autoname <uuid> # 通过自动生成会话名称
sesh autoname --all # 为网格中所有可命名的会话自动生成名称;无法命名的会话(尚无转录内容)会被跳过,其余会话仍会被命名
sesh autoname-toggle <uuid> [--on|--off]
pi -p
`send`/`abort`/`compact`(以及上文提到的修改操作和转录读取操作)通过单一源节点路由层转发到所属机器,因此可在网格中的任意机器上操作会话(不仅限于本地)。
**`send`对所有三种Agent都是双向交互**——默认情况下会阻塞直到Agent完成当前轮次并打印回复。获取回复的方式取决于Agent类型以及会话是否在tmux窗格中处于活跃状态:
- **pi**——通过其套接字传递;返回流式回复(即使会话处于分离/无头状态也能工作)。
- **claude / codex,且在窗格中活跃(已连接)**——消息会输入到活跃窗格中(因此人类观察者可以看到,对话不会分叉),然后`send`等待轮次完成并返回最后一条助手消息。
- **claude / codex,且处于分离状态(无活跃窗格)**——会话会以**无头模式**恢复(`claude -p --resume` / `codex exec resume`)并返回回复。(codex以只读模式运行,无确认提示;claude恢复操作基于工作目录,因此会话记录的`cwd`必须仍然存在。)
> 注意(exp14):永远不要以无头模式恢复同时在窗格中活跃的claude/codex会话——这会导致内存中的对话分叉。`sesh`会自动避免这种情况:只要存在活跃窗格,就会直接在窗格中输入消息;仅当会话处于分离状态时才会使用无头模式。
**`--no-wait`参数**让`send`成为“即发即弃”模式:发送消息后立即返回,不等待轮次完成或打印回复(如果**发送**失败仍会报错)。对于分离状态的claude/codex,这会在后台启动无头轮次,因此轮次执行过程中的错误会被守护进程记录到日志中,不会反馈给调用者。当你只想触发Agent操作而不想阻塞时使用该参数。
**`await`**是对网格同步的`turnStatus`的纯读取操作,因此可在任意机器上操作会话,无需转发;如果会话已处于空闲状态,会立即返回。该命令主要用于观察你未启动的轮次(人类驱动的会话,或通过`send --no-wait`触发的会话)——普通的`send`已经包含等待逻辑。注意:如果同时有人类在驱动会话,`await`会在任意一方完成轮次时返回。`--timeout 0`(默认值)表示无限等待;**负数**`--timeout`会被明确拒绝,而非静默视为“无时间限制”。
**`autoname --all`**为网格中所有可命名的未归档会话自动生成名称(重命名操作会转发到各源节点)。暂时无法命名的会话——最常见的是刚注册但磁盘上尚无转录内容的会话——会被**跳过**(在标准错误输出中报告),其余会话仍会被命名;批量操作不会因第一个无法命名的会话而中止。为单个明确的`<uuid>`命名仍会显示其错误。Daemon & peers
守护进程与对等节点
bash
sesh daemon status [--json] # machine, uptime, sessions, peers, schema version
sesh daemon start | stop | restart # restart = the reliable way to pick up a redeployed binary
sesh daemon ensure # idempotent start (supervisor entrypoint)
sesh peer ... # manage peer-daemon connections (~/.sesh/peers.json)
sesh doctor # diagnose agents/tmux/daemon/configThe daemon is normally supervised (supervisord/launchd on servers; a
nohup leaf on termux). If supervised, restart via the supervisor, not
, so they don't race. (and the
half of ) refuses with an error if a daemon is already
running, rather than spawning a duplicate — so a stray manual start can't
clobber the supervised instance (the guard is an exclusive flock on the
pidfile, so even concurrent starts can't both win). If a background start
FAILS, the client surfaces the daemon's real error (e.g. missing
) and captures its stderr to .
sesh daemon restartsesh daemon startstartrestartSESH_MACHINE~/.sesh/daemon.logbash
sesh daemon status [--json] # 机器信息、运行时间、会话数、对等节点数、架构版本
sesh daemon start | stop | restart # 重启是获取重新部署的二进制文件的可靠方式
sesh daemon ensure # 幂等启动(监控进程入口)
sesh peer ... # 管理对等守护进程连接(~/.sesh/peers.json)
sesh doctor # 诊断Agent/tmux/守护进程/配置守护进程通常由监控进程管理(服务器上使用supervisord/launchd;Termux上使用nohup)。如果由监控进程管理,请通过监控进程重启,而非,避免竞争。(以及中的启动步骤)如果检测到守护进程已在运行,会拒绝执行并报错,而非启动重复进程——因此意外的手动启动不会覆盖监控进程管理的实例(通过pid文件的独占锁实现,即使并发启动也不会同时成功)。如果后台启动失败,客户端会显示守护进程的真实错误(例如缺少),并将标准错误输出捕获到。
sesh daemon restartsesh daemon startrestartSESH_MACHINE~/.sesh/daemon.logMaintenance
维护操作
bash
sesh backup # import transcripts into a single SQLite file (idempotent)
sesh restore # reconstruct transcripts from a backup
sesh import # one-shot import of v1 ~/.sesh/sessions.json
sesh copy <uuid> <dest> # copy a session's transcript elsewhere (same-agent)restore- must point at an EXISTING backup; a missing/typo'd path errors
--from <file>(it will not silently create an empty DB).no such backup file - accepts a full UUID or a short prefix (like
restore [uuid]), resolved against the backup's stored transcripts; an unknown or ambiguous prefix is a loud error, not a silent no-op.copy - Default target is (reconstruct at the agent's real path). Only claude has a deterministic native path; pi/codex filenames embed a timestamp, so a native restore skips them and reports them as "unsupported" (restore those with
--to native). A mixed-agent backup still restores its claude entries — it does not abort partway.--to <dir>
copy- Cross-machine restores
copy <uuid> --to <machine>on the peer, so it only works for claude sessions; copying a pi/codex session cross-machine errors loudly up front (use--to nativelocally instead). A failed remote restore now propagates a nonzero exit (it no longer reports a false "copied" success).--to-dir <dir>
sesh importsesh daemon stop--forcebash
sesh backup # 将转录内容导入到单个SQLite文件(幂等操作)
sesh restore # 从备份文件重建转录内容
sesh import # 一次性导入v1版本的~/.sesh/sessions.json
sesh copy <uuid> <dest> # 将会话的转录内容复制到其他位置(同Agent类型)restore- 必须指向已存在的备份文件;路径不存在或输入错误会报错“no such backup file”(不会静默创建空数据库)。
--from <file> - 接受完整UUID或短前缀(与
restore [uuid]相同),基于备份文件中存储的转录内容解析;未知或歧义前缀会明确报错,而非静默无操作。copy - 默认目标是(在Agent的真实路径重建)。只有claude拥有确定的原生路径;pi/codex的文件名包含时间戳,因此原生恢复会跳过这些会话并报告“unsupported”(请使用
--to native恢复)。包含多种Agent的备份文件仍会恢复其中的claude会话——不会中途中止。--to <dir>
copy- 跨机器会在对等节点上执行
copy <uuid> --to <machine>恢复,因此仅适用于claude会话;跨机器复制pi/codex会话会直接报错(请在本地使用--to native)。远程恢复失败现在会返回非零退出码(不再错误报告“copied”成功)。--to-dir <dir>
sesh importsesh daemon stop--forceCommon flags & environment
通用参数与环境变量
- Global flags: (target a machine; default all/local),
--machine <name>(machine-readable),--json(daemon socket, default--socket <path>).~/.sesh/daemon.sock - /
newflags:delegate(launch model; see "Model selection") among the per-command flags above.--model <name> - Config:
~/.sesh/config.tomlsets default launch models and[models]overrides each agent binary's path (both under "Model selection"). The mesh/peers live in[agents], not here.~/.sesh/peers.json - Env: (state dir, default
SESH_HOME),~/.sesh(origin identity — required; the daemon refuses to start without it, no hostname fallback),SESH_MACHINE(override walker socket discovery),SESH_TMUX_SOCKETS(a command to relabel the TUI cwd column).SESH_CWD_FORMATTER - Exit codes for the picker (/
pick):tuiselected,0cancelled,130nothing to select.3
- 全局参数:(目标机器;默认所有/本地)、
--machine <name>(机器可读格式)、--json(守护进程套接字,默认--socket <path>)。~/.sesh/daemon.sock - /
new参数:delegate(启动模型;参见“模型选择”),以及上文提到的各命令专属参数。--model <name> - 配置:中的
~/.sesh/config.toml设置默认启动模型,[models]覆盖各Agent二进制文件的路径(均在“模型选择”部分说明)。网格/对等节点信息存储在[agents]中,不在此配置文件中。~/.sesh/peers.json - 环境变量:(状态目录,默认
SESH_HOME)、~/.sesh(源节点标识——必填;守护进程启动时必须设置,无主机名 fallback)、SESH_MACHINE(覆盖遍历器的套接字发现逻辑)、SESH_TMUX_SOCKETS(用于重新标记TUI工作目录列的命令)。SESH_CWD_FORMATTER - 选择器(/
pick)的退出码:tui已选择、0已取消、130无可选内容。3
Picker emit contract
选择器输出约定
picktui--enter--format jsonnulkvactionuuidmachineagentcwdnametmuxsocketsessionwindowpaneactiongotoresumepicktui--action <verb>send--cursor <uuid>tui<uuid>picktui--enter--format jsonnulkvactionuuidmachineagentcwdnametmuxsocketsessionwindowpaneactiongotoresumepicktui--action <verb>sendtui--cursor <uuid><uuid>