npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nova-terminal

v0.1.5

Published

AI-native terminal server

Readme

nova-terminal

AI-native terminal server — gives AI agents structured access to terminal sessions, processes, and system state via REST API and MCP protocol.

概述

nova-terminal 是一个为 AI agent 设计的终端服务器。它弥补了 bash 工具无法处理的场景:长期运行的进程、交互式 PTY、跨轮次的进程状态,以及对系统的结构化查询。

| 能力 | bash 工具 | nova-terminal | |---|---|---| | 一次性命令 | ✅ | ✅ (Exec) | | 长期运行进程 | ❌ | ✅ (PTY Sessions) | | 交互式 PTY (stdin/TUI) | ❌ | ✅ | | 等待输出模式匹配 | ❌ | ✅ (Wait) | | 跨轮次进程状态 | ❌ | ✅ | | Attach 已有进程 | ❌ | ✅ | | 结构化断言 | ❌ | ✅ (Verify) |

快速开始

npx / 全局安装

npx nova-terminal
# 或
npm install -g nova-terminal
nova-terminal --port 3444

Docker

docker run -p 3444:3444 ghcr.io/chovrio/nova-terminal:latest

从源码启动

pnpm install
pnpm dev        # tsx watch,热重载
# 或
pnpm build && pnpm start

默认端口:3444

CLI 选项

Usage: nova-terminal [options]

Options:
  --port <number>       监听端口 (默认: 3444)
  --log-level <level>   日志级别: trace|debug|info|warn|error (默认: info)
  --help                显示帮助

MCP 配置

将以下配置加入 Claude Desktop 或其他支持 MCP 的客户端:

{
  "mcpServers": {
    "nova-terminal": {
      "type": "http",
      "url": "http://localhost:3444/mcp"
    }
  }
}

MCP 端点实现了所有 18 个工具,与 REST API 完全对应。

Claude Code Skill

项目内置了一个 Claude Code skill 文件(skills/nova-terminal.md),让 Claude 知道何时以及如何使用 nova-terminal。

安装方式: 在你的 CLAUDE.md 里引用它:

@/path/to/nova-terminal/skills/nova-terminal.md

或者把文件复制到 Claude Code 的全局 skills 目录:

cp skills/nova-terminal.md ~/.claude/skills/nova-terminal.md

Skill 涵盖:

  • 何时用 nova-terminal 而不是 bash 工具
  • 常用工作流(启动服务器、运行测试、交互式 CLI)
  • 完整工具参考
  • Docker 环境下的项目分析与启动流程(自动检测 runtime、端口、volume 挂载)

REST API

Sessions(PTY 会话)

POST   /sessions
  body: { name, command, args?, cwd?, env?, cols?, rows? }
  201: SessionRecord
  409: 名称已存在

POST   /sessions/attach
  body: { name, pid }
  201: SessionRecord (type: "attached")
  404: 进程不存在

GET    /sessions              → SessionRecord[]
GET    /sessions/:id          → SessionRecord
DELETE /sessions/:id          → 204

POST   /sessions/:id/signal
  body: { signal: "SIGTERM"|"SIGKILL"|"SIGHUP"|"SIGINT"|"SIGUSR1"|"SIGUSR2" }
  204

SessionRecord 结构:

{
  "id": "uuid",
  "name": "frontend",
  "command": "pnpm",
  "args": ["dev"],
  "cwd": "/app",
  "type": "pty",
  "pid": 12345,
  "status": "running",
  "exitCode": null,
  "createdAt": 1700000000000,
  "lastActiveAt": 1700000000000
}

Exec(一次性命令)

POST   /exec
  body: { command, args?, cwd?, env?, timeout_ms? (max 300000, 默认 30000) }
  200: { stdout, stderr, exit_code, duration_ms }

与 Sessions 不同,Exec 结果不持久化,适合简单的单次调用。


Output(读取输出缓冲区)

GET    /sessions/:id/output
  query:
    tail?   — 最后 N 行
    since?  — 某时间戳之后的行(毫秒)
    search? — 正则过滤
    stream? — "stdout"|"stderr"|"all" (默认 "all")
    limit?  — 最多返回条数 (默认 100, max 500)
    clear?  — "true" 读取后清空缓冲区
  200: { count, dropped, entries: [{ stream, line, timestamp_ms }] }

Input(写入 PTY)

POST   /sessions/:id/input
  body: { data: string }   — 原始字符串写入 stdin
  204

POST   /sessions/:id/key
  body: { key: "ctrl_c"|"ctrl_d"|"enter"|"tab"|"escape"|"up"|"down"|... }
  204

支持的具名按键:ctrl_c, ctrl_d, ctrl_z, ctrl_l, tab, enter, escape, up, down, left, right, backspace, delete, home, end, page_up, page_down


Wait(等待事件)

POST   /sessions/:id/wait
  body: { pattern?: string (正则), event?: "exit", timeout_ms?: number }
  200: { matched: true, line?: string, elapsed_ms: number }
     | { matched: false, reason: "timeout", elapsed_ms: number }

先检查已有缓冲区,再订阅新行事件。event: "exit" 等待进程退出。


Verify(结构化断言)

POST   /sessions/:id/verify
  body: { rules: VerifyRule[] }
  200: { pass: boolean, results: [{ rule, pass, detail? }] }

VerifyRule 类型:

{ "type": "output_contains",     "pattern": "server ready" }
{ "type": "output_not_contains", "pattern": "ERROR" }
{ "type": "exit_code",           "code": 0 }
{ "type": "process_alive" }
{ "type": "process_exited" }

Inspect(进程元数据)

GET    /sessions/:id/inspect
  200: { pid, ppid, cwd, args, env, children: pid[],
         open_ports: number[], cpu_percent, memory_bytes }

无法读取的字段返回 null,不报错。


Files(文件监听 & 读取)

POST   /files/watch
  body: { path, recursive?: boolean }
  201: { id, path }

GET    /files                      → { entries: [{ id, path, recursive, created_at }] }
GET    /files/tail?path=...&lines= → { lines: string[], total_lines: number }
GET    /files/:id/events?limit=    → { count, entries: [{ type, path, timestamp_ms }] }
DELETE /files/:id                  → 204

System(系统信息)

GET    /system/ports?port=3000          → 单个端口占用情况
GET    /system/ports?range=3000-3010    → 端口范围扫描
GET    /system/processes?name=node      → 进程列表(可按名称过滤)
GET    /system/resources                → CPU / 内存 / 磁盘
GET    /health                          → { status: "ok", version: "0.1.0" }

MCP 工具列表

| 工具 | 对应 REST | |---|---| | session_create | POST /sessions | | session_list | GET /sessions | | session_get | GET /sessions/:id | | session_delete | DELETE /sessions/:id | | session_attach | POST /sessions/attach | | session_signal | POST /sessions/:id/signal | | exec | POST /exec | | output_read | GET /sessions/:id/output | | input_write | POST /sessions/:id/input | | input_key | POST /sessions/:id/key | | wait | POST /sessions/:id/wait | | verify | POST /sessions/:id/verify | | inspect | GET /sessions/:id/inspect | | files_tail | GET /files/tail | | files_list | GET /files | | system_ports | GET /system/ports | | system_processes | GET /system/processes | | system_resources | GET /system/resources |


典型使用流程

启动开发服务器并等待就绪

# 1. 创建 PTY 会话
curl -X POST http://localhost:3444/sessions \
  -H 'Content-Type: application/json' \
  -d '{"name": "frontend", "command": "pnpm", "args": ["dev"], "cwd": "/app"}'

# 2. 等待 "ready" 输出
curl -X POST http://localhost:3444/sessions/<id>/wait \
  -H 'Content-Type: application/json' \
  -d '{"pattern": "ready on port", "timeout_ms": 10000}'

# 3. 读取输出缓冲区
curl http://localhost:3444/sessions/<id>/output?tail=20

运行测试并验证结果

# 创建会话运行测试
curl -X POST http://localhost:3444/sessions \
  -d '{"name": "tests", "command": "pnpm", "args": ["test"]}'

# 等待测试完成
curl -X POST http://localhost:3444/sessions/<id>/wait \
  -d '{"event": "exit", "timeout_ms": 60000}'

# 验证无错误
curl -X POST http://localhost:3444/sessions/<id>/verify \
  -d '{"rules": [{"type": "exit_code", "code": 0}, {"type": "output_not_contains", "pattern": "FAIL"}]}'

交互式操作(输入密码等)

curl -X POST http://localhost:3444/sessions/<id>/input \
  -d '{"data": "mypassword\n"}'

# 或发送 Ctrl+C
curl -X POST http://localhost:3444/sessions/<id>/key \
  -d '{"key": "ctrl_c"}'

架构

REST/MCP clients
      ↓
API routes (src/api/)
      ↓
Core engines (src/core/)
  ├── SessionManager  — 会话注册表,TTL 清理
  ├── OutputBuffer    — 每会话循环缓冲区,EventEmitter
  ├── WaitEngine      — 订阅 OutputBuffer 事件,模式匹配
  ├── VerifyEngine    — 结构化断言
  ├── ProcessInspector — 进程元数据
  ├── SystemInspector  — 系统查询
  └── FileWatcher     — fs.watch 封装
      ↓
Process layer (src/process/)
  ├── PTYManager   — node-pty 封装
  └── ExecRunner   — child_process.spawn 封装
      ↓
node-pty / child_process / fs / os

设计原则: 路由层不直接调用进程层;引擎层不互相依赖(SessionManager 除外,它是共享状态)。


开发

# 安装依赖
pnpm install

# 开发模式(热重载)
pnpm dev

# 类型检查
pnpm typecheck

# 单元测试
pnpm test:unit

# 集成测试(会启动真实进程)
pnpm test:integration

# 构建
pnpm build

技术栈

  • Runtime: Node.js 22, TypeScript ESM
  • HTTP: Fastify 5
  • PTY: node-pty
  • MCP: @modelcontextprotocol/sdk (StreamableHTTP,无状态 per-request)
  • Schema: Zod 4
  • Test: Vitest(unit + integration 双项目)
  • Package manager: pnpm

错误格式

{ "error": "Human-readable message" }

Zod 校验失败(400):

{ "error": "Validation error", "details": [{ "path": ["field"], "message": "Required" }] }

| 状态码 | 含义 | |---|---| | 400 | 请求体或查询参数无效 | | 404 | 会话或监听器不存在 | | 409 | 会话名称已被使用 | | 500 | 服务内部错误 |


注意事项

  • Attach 会话为只读: 从 attach 时刻起捕获输出,历史输出不可恢复;不支持写入 stdin
  • 会话 TTL: 退出的会话在闲置 30 分钟后自动清理
  • Exec vs Session: 一次性命令用 /exec(无 ANSI 码,输出干净);需要交互或长期运行用 Sessions
  • 速率限制: 200 请求/分钟

License

MIT