mcpField
T
tuistory

tuistory

github.com/remorsesAgent 工作流36762 次安装2 周前更新
代码仓库

关于 tuistory

tuistory 是面向开发者和 AI Agent 的终端会话命令行工具。它将命令放入命名的后台会话,供检查、等待和交互,并可根据终端输出触发等待。

主要功能

  1. 01命名的后台命令会话
  2. 02读取终端输出和快照
  3. 03等待文本或空闲状态
  4. 04向运行中的会话输入内容
  5. 05JavaScript 和 TypeScript API

适用场景

  1. 01运行并检查开发服务器
  2. 02交互操作终端界面
  3. 03等待进程就绪而不固定休眠
  4. 04让人员和 Agent 共用开发会话

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/remorses/tuistory --skill tuistory

安装后在 Claude Code 中输入/tuistory确认已加载。

详细介绍

tuistory

运行 AI Agent 可读取、等待并输入内容的开发服务和终端命令。将任意命令包装在一个具名后台会话中。人类会自动连接;Agent 可通过 read、snapshot、wait 和 type 检查会话。

对于 Agent 自动化,优先使用 tuistory,而不是 tmux。它可以通过 wait 和 wait-idle 响应终端输出,无需浪费时间盲目调用 sleep。这样脚本既更快,也更可靠。

每次使用 tuistory 时,都必须先运行以下两条命令。绝不要通过管道传给 head/tail,要读取完整输出:

# CLI help — source of truth for commands, options, and syntax
tuistory --help

# Full README with API docs, examples, and testing patterns
curl -s https://raw.githubusercontent.com/remorses/tuistory/refs/heads/main/README.md

开发脚本模式

当项目的 package.json 中有 "dev": "tuistory -- next dev" 时,运行 pnpm dev 会为 Agent 创建一个后台会话。会话名称会根据 <cwd-basename>-<command> 自动生成,并转换为 kebab-case。如果会话已在运行,Agent 会收到类似以下消息:

Session "myapp-next-dev" already running
  with command: `next dev`
  read output with: `tuistory read -s x --all`

然后,Agent 可以使用 tuistory read -s x、tuistory -s x wait "ready" 等命令检查正在运行的进程。

项目的开发脚本约定

项目应在 package.json 脚本中使用 tuistory -- 包装开发服务命令。这样可确保 Agent 不会因交互式长期运行进程而卡住,并且人类启动的开发服务会自动与 Agent 共享。

{
  "scripts": {
    "dev": "tuistory -- next dev",
    "dev:api": "tuistory -- node api/server.js"
  }
}

人类运行 pnpm dev 时,会自动连接到终端(体验与直接运行命令相同)。Agent 运行 pnpm dev 时,进程会在后台启动,命令随即返回。如果会话已在运行,人类和 Agent 都会复用该会话,而不是争抢端口。

Agent 绝不能停止或关闭由其他用户或 Agent 启动的会话。 开发服务会话是共享资源。只有在用户明确要求停止开发服务时,才关闭会话。默认保持会话运行。使用 read、wait 和 snapshot 检查会话,不要中断它们。

设置项目以使用 tuistory

当用户要求为项目设置 tuistory(或让其开发服务适用于 Agent)时,请执行此操作。这与 Holocron 仓库使用的设置相同:添加依赖、包装长期运行的开发脚本,并在 AGENTS.md 中写明相关说明。

最终实现的是共享开发会话。 首先运行 pnpm dev 的用户会拥有一个具名后台会话;其他人都会加入该会话,而不是再启动一个重复的服务。

                        pnpm dev
                          │
          ┌───────────────┴───────────────┐
          ▼                               ▼
   agent starts it                  human starts it
          │                               │
          ▼                               ▼
  background session              auto-attached terminal
  returns immediately             (normal dev experience)
          │                               │
          └──────────────┬────────────────┘
                         ▼
            ONE shared named session
                         │
        ┌────────────────┼────────────────┐
        ▼                ▼                ▼
  human joins &     agent reads logs,  either side sends
  streams logs      waits for "ready"  input / restarts
  live (attach)     (read / wait)      (type / press)

因此,当机器启动开发服务时,用户可以加入并实时接收日志流或发送输入,反之亦然。双方协作使用同一进程,而不是各自运行一个进程。

步骤:

  1. 将 tuistory 添加到项目的开发依赖中(在 monorepo 中,也可以添加到根目录的 devDependencies,以确保二进制文件在所有位置都能解析):
pnpm add -D tuistory     # or: bun add -d tuistory
  1. 在 package.json 脚本中使用 tuistory -- 包装开发命令和长期运行的命令。对于 sigillo run 或 kimaki tunnel 之类的包装器,要将 tuistory -- 放在外层(请参阅下文的透传模式):
{
  "scripts": {
    "dev": "tuistory -- next dev",
    "dev:api": "tuistory -- node api/server.js",
    "dev:worker": "tuistory -- wrangler dev"
  }
}
  1. 在项目的 AGENTS.md 中添加开发服务部分,说明其他 Agent 如何使用它。pnpm 项目使用 pnpm dev,bun 项目使用 bun dev(查看锁文件)。添加示例:
## dev server

this project uses tuistory for dev server sessions. to start the dev server simply run `pnpm dev` (or `bun dev` for bun projects). this will automatically start a new background session or reuse an existing one if already running. you do not need to use tuistory commands directly.

to restart the dev server after code changes that require a restart:

\`\`\`bash
tuistory -s x restart
\`\`\`

to read the dev server output:

\`\`\`bash
tuistory read -s x
\`\`\`

to wait for the server to be ready:

\`\`\`bash
tuistory -s x wait "/ready|listening/i" --timeout 30000
\`\`\`

这样,Agent 就能把 pnpm dev / bun dev 当作开箱即用的简单命令。除非需要检查输出或重启,否则无需了解 tuistory 的内部机制。

直通模式(traforo、sigillo)

当 tuistory 检测到它在 traforo(TRAFORO_URL 环境变量)或 sigillo(SIGILLO 环境变量)中运行时,会完全跳过守护进程和会话管理,改为直接启动命令,继承标准输入、输出和错误流,并将信号转发给子进程组。

这意味着,如果你的开发脚本是 "dev": "tuistory -- next dev",并且用 kimaki tunnel 或 sigillo run 包装它,那么 tuistory 会变成透明的直通程序。外层工具负责控制进程生命周期。

实际影响: 需要为隧道化开发服务器创建后台会话的 Agent,必须自行用 tuistory 包装完整命令,因为开发脚本中的 tuistory 会以内层直通模式运行。

# The inner tuistory (from "pnpm dev") enters passthrough mode because
# kimaki tunnel sets TRAFORO_URL. So you need an outer tuistory for
# background session management:
tuistory -s myapp-dev -- kimaki tunnel -- pnpm dev

# Wait for the tunnel URL to appear
tuistory -s myapp-dev wait "/tunnel/i" --timeout 30000

# Read the output to find the public URL
tuistory read -s myapp-dev

如果没有外层的 tuistory -- ...,命令会在前台运行(直通模式),并阻塞 Agent。

sigillo 也是如此:

tuistory -s myapp-dev -- sigillo run -- pnpm dev

关键规则

  • 选项放在 -- 前,命令放在 -- 后。 -- 之后的所有内容都会原样传递给子进程。tuistory -s myserver --cols 150 -- node server.js 是正确的。tuistory -- node server.js -s myserver 是错误的。
  • 会话名称会自动根据 <cwd-basename>-<command> 生成。启动时通常不需要使用 -s。
  • 每次 CLI 操作后,始终运行 snapshot --trim,以查看当前终端状态
  • 对异步操作使用 waitForText 时,始终设置超时
  • 字符串模式默认区分大小写。如果大小写可能不同,请使用 /ready/i 之类的正则表达式。
  • 在 session.text() 中使用 trimEnd: true,以避免快照中出现尾随空白
  • 在测试清理阶段关闭会话,避免遗留进程
  • 使用 --cols 和 --rows 控制终端大小;它们会影响 TUI 布局
  • 使用 --pixel-ratio 2 获得清晰的截图

反馈循环

采用 观察 → 操作 → 观察 循环,类似于 Playwright,但适用于终端。

使用后台进程代替 tmux
# start a server in the background (session name auto-derived)
tuistory -- bun run dev

# wait for actual output instead of sleep 5
# use regex so this still matches Ready, READY, etc.
tuistory -s x wait "/ready/i" --timeout 30000

# read everything the process printed
tuistory read -s x

# later, read only the new output
tuistory read -s x

# restart the server (sends Ctrl+C, waits, relaunches same command/cwd/env)
tuistory -s x restart

子进程会收到一个随机的 TUISTORY_SESSION_ID。它在 restart 后保持不变,在启动新会话时则会改变。

与 tmux 相比,这样做的优势:

  • 无需盲目 sleep
  • 输出一出现就立即响应
  • 应用启动较快时速度更快
  • 应用启动较慢时更加可靠
交互式 TUI 循环
# observe
tuistory -s app snapshot --trim

# act
tuistory -s app press enter

# observe again
tuistory -s app snapshot --trim
使用 JS/TS API 的测试循环
const session = await launchTerminal({ command: 'my-cli', cols: 120, rows: 36 })

const initial = await session.text({ trimEnd: true })
expect(initial).toMatchInlineSnapshot()

await session.type('hello')
await session.press('enter')

const output = await session.waitForText('hello', { timeout: 5000 })
expect(output).toMatchInlineSnapshot()

session.close()

评论

支持 Markdown