Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/validate-skills.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Validate skills

on:
workflow_dispatch:
pull_request:
paths:
- 'skills/**'
- 'package.json'
- '.github/workflows/validate-skills.yml'
push:
branches:
- main
paths:
- 'skills/**'
- 'package.json'
- '.github/workflows/validate-skills.yml'

concurrency:
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
validate-skills:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out repository
uses: actions/checkout@v6

- name: Set up mise
uses: jdx/mise-action@v3

- name: Validate TanStack Intent skills
run: npx @tanstack/intent@latest validate
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ Development server: **none**. This is a CLI project, so iterative development us
- **Do update coupled limits together.** `src/host/eventLog.ts` and `src/host/replay.ts` both enforce the 50 MB event-log limit. **Do not** change one without the other.
- **Do add tests at the right layer.** Small parser/validation changes usually belong in `test/unit`; CLI wiring and temp-home behavior fit `test/integration`; renderer/artifact flows belong in `test/e2e`.

- **Do keep the public `skills/agent-terminal/` artifact binary-first.** The committed public skill and public-facing skill docs must use `agent-terminal ...`, not repo-local `npx`, `tsx`, or `src/cli/main.ts` invocations. When you execute those examples from this source tree, translate them locally to `npx tsx src/cli/main.ts ...`, but do not commit that substitution back into the public skill or README skill-install guidance.
- **Do teach the terminal workflow the public skill is supposed to reinforce.** Prefer `--home`, `--json`, `run`, `wait`, `snapshot`, `screenshot`, and `record export` when writing or maintaining public skill examples. **Do not** teach `tmux`, blind `sleep`, or out-of-band screenshots as the primary workflow.

## Testing patterns

- Unit tests often mock command dependencies and assert exact envelopes or manifest writes.
Expand Down
92 changes: 83 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,31 @@
`agent-terminal` is a Node/TypeScript CLI for launching, controlling, inspecting, and exporting reviewable terminal sessions.
It is built for agent workflows that need both semantic state and visual artifacts from live or exited TUIs.

## Quick start
## Installation

### Global installation

```bash
mise install
npm ci
npx playwright install chromium
npm run build
npm install -g agent-terminal
agent-terminal version --json
```

### Project installation

```bash
npm install agent-terminal
./node_modules/.bin/agent-terminal version --json
```

## Quick start

SESSION_ID=$(node dist/cli/main.js create --json --name demo | jq -r '.result.sessionId')
node dist/cli/main.js run "$SESSION_ID" 'echo hello from agent-terminal'
node dist/cli/main.js inspect "$SESSION_ID" --json
node dist/cli/main.js destroy "$SESSION_ID"
```bash
AGENT_HOME="$(mktemp -d)"
agent-terminal --home "$AGENT_HOME" doctor --json
SESSION_ID=$(agent-terminal --home "$AGENT_HOME" create --json --name demo -- /bin/bash | jq -r '.result.sessionId')
agent-terminal --home "$AGENT_HOME" run "$SESSION_ID" 'echo hello from agent-terminal' --json
agent-terminal --home "$AGENT_HOME" snapshot "$SESSION_ID" --format text --json
agent-terminal --home "$AGENT_HOME" destroy "$SESSION_ID" --json
```

## Feature highlights
Expand Down Expand Up @@ -53,6 +66,67 @@ Recommended sequence:
3. Use `wait` for render-visible readiness conditions.
4. Capture screenshots for point-in-time review.
5. Export WebM recordings when reviewers need motion proof.
6. Destroy the session when done.

## AI agent skill

The public skill lives under `skills/agent-terminal/` and ships in the npm package.
You can install it directly for Mux-style skill loaders, or let TanStack Intent discover and map it for compatible coding agents.

### TanStack Intent integration

If your agent supports Intent-compatible skill mappings, install `agent-terminal` in the project and let Intent wire the mapping into `AGENTS.md`, `CLAUDE.md`, or another supported agent config file.

```bash
npm install agent-terminal
npx @tanstack/intent@latest list
npx @tanstack/intent@latest install
```

That workflow keeps the skill version aligned with the installed `agent-terminal` package and avoids writing one-off instructions for each individual coding agent.

### Mux skill installation

```bash
npm install -g agent-terminal

mkdir -p ~/.mux/skills/agent-terminal
cp -R "$(npm root -g)/agent-terminal/skills/agent-terminal/." ~/.mux/skills/agent-terminal/
```

### Direct skill copy for other skill loaders

```bash
npm install -g agent-terminal

mkdir -p ~/.claude/skills/agent-terminal
cp -R "$(npm root -g)/agent-terminal/skills/agent-terminal/." ~/.claude/skills/agent-terminal/
```

If your assistant supports repository-backed skills, point it at `coder/agent-terminal` and select the `agent-terminal` skill directory.

### Suggested `AGENTS.md` / `CLAUDE.md` snippet

```markdown
## Terminal Automation

Use `agent-terminal` for terminal and TUI automation instead of `tmux`, ad hoc PTY wrappers, or external screenshot tools.

Preferred workflow:

1. Create an isolated home and session with `agent-terminal --home "$AGENT_HOME" create --json -- /bin/bash`.
2. Use `agent-terminal run` for setup and bootstrap commands.
3. Use `agent-terminal wait` for observable readiness instead of blind sleeps.
4. Use `agent-terminal snapshot` to inspect the current terminal state.
5. Use `agent-terminal screenshot` or `agent-terminal record export` for reviewer-facing artifacts.
6. Destroy the session when the task is done.
```

Maintainers can validate the shipped skill locally with:

```bash
npm run intent:validate
```

## Isolation

Expand Down
Binary file not shown.
12 changes: 12 additions & 0 deletions dogfood/20260327-public-skill/create.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"ok": true,
"command": "create",
"timestamp": "2026-03-27T17:01:28.898Z",
"result": {
"sessionId": "01KMR3WRXSP97ZBVWXN0YQ3VG2",
"createdAt": "2026-03-27T17:01:28.378Z",
"cols": 80,
"rows": 24,
"shell": "/bin/bash"
}
}
9 changes: 9 additions & 0 deletions dogfood/20260327-public-skill/destroy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"ok": true,
"command": "destroy",
"timestamp": "2026-03-27T17:01:34.791Z",
"result": {
"sessionId": "01KMR3WRXSP97ZBVWXN0YQ3VG2",
"destroyed": true
}
}
130 changes: 130 additions & 0 deletions dogfood/20260327-public-skill/doctor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
{
"ok": true,
"command": "doctor",
"timestamp": "2026-03-27T17:01:27.838Z",
"result": {
"ok": true,
"checks": {
"environment": [
{
"name": "node-runtime",
"status": "pass",
"message": "Node 24.14.0 ok",
"durationMs": 0
},
{
"name": "cwd-access",
"status": "pass",
"message": "cwd read/write: /home/coder/.mux/src/agent-terminal/agent-terminal-ejrg",
"durationMs": 0
},
{
"name": "temp-dir",
"status": "pass",
"message": "temp dir ok: /tmp",
"durationMs": 1
},
{
"name": "home_isolation",
"status": "pass",
"message": "Agent-terminal home is isolated from system home: /tmp/tmp.JSj3HFOAzD",
"durationMs": 0
},
{
"name": "home-writable",
"status": "pass",
"message": "home writable: /tmp/tmp.JSj3HFOAzD",
"durationMs": 1
},
{
"name": "pty-spawn",
"status": "pass",
"message": "spawned /home/coder/.npm/_npx/387698761821791d/node_modules/node/bin/node",
"durationMs": 29
},
{
"name": "socket-viable",
"status": "pass",
"message": "socket ok: /tmp/tmp.JSj3HFOAzD/sessions/doctor-785178-mn95esfe-2/host.sock",
"durationMs": 4
},
{
"name": "artifact-atomicity",
"status": "pass",
"message": "atomic rename ok: /tmp/tmp.JSj3HFOAzD/sessions/doctor-785178-mn95esfi-3/artifacts",
"durationMs": 2
},
{
"name": "event-log-writable",
"status": "pass",
"message": "append ok: /tmp/tmp.JSj3HFOAzD/sessions/doctor-785178-mn95esfk-5/events.jsonl",
"durationMs": 1
}
],
"renderer": [
{
"name": "playwright_available",
"status": "pass",
"message": "available",
"durationMs": 0
},
{
"name": "browser_cache_accessible",
"status": "pass",
"message": "browser cache accessible: /home/coder/.cache/ms-playwright",
"durationMs": 1
},
{
"name": "browser_launch",
"status": "pass",
"message": "chromium launches",
"durationMs": 130
},
{
"name": "ghostty_web_available",
"status": "pass",
"message": "WASM available",
"durationMs": 10
},
{
"name": "screenshot_viable",
"status": "pass",
"message": "viable",
"durationMs": 159
}
]
},
"capabilities": [
{
"name": "snapshot",
"status": "available",
"reason": "built-in capability",
"detail": "available without external renderer dependencies"
},
{
"name": "wait",
"status": "available",
"reason": "built-in capability",
"detail": "available without external renderer dependencies"
},
{
"name": "screenshot",
"status": "available",
"reason": "renderer smoke checks passed",
"detail": "playwright_available: available; browser_launch: chromium launches; ghostty_web_available: WASM available; screenshot_viable: viable"
},
{
"name": "record-export-asciicast",
"status": "available",
"reason": "built-in capability",
"detail": "available without external renderer dependencies"
},
{
"name": "record-export-webm",
"status": "available",
"reason": "browser-backed export dependencies available",
"detail": "playwright_available: available; browser_launch: chromium launches; ghostty_web_available: WASM available"
}
]
}
}
Loading
Loading