Skip to content
Back to skills

Ana

ASecurity

Attach ANA (Agent-Native Agent) to an existing web app or service so the user can operate it by watching a dashboard and chatting with a coding agent that runs inside tmux — chat is injected via tmux paste-buffer and the session is mirrored via capture-pane, with zero dependencies (no MCP, no bridge, no hooks, no plugin runtime). Use this whenever the user wants to "add ANA / a chat+watch dashboard to my app", "attach a coding-agent chat to an existing service", "make my dashboard talk to a t...

  • 73 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 5, 2026
ai-agentsrustshellbashnodeapi

Works with

  • cursor
  • terminal
  • cli
  • api
  • mcp

Security analysis

A100/100

Scanned October 4, 2026

npx -y skills add tykimos/agent-native-agent --skill ana --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ana?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ana
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tykimos-ana/badge)](https://www.skillsdirectory.com/skills/tykimos-ana)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ana
description: Attach ANA (Agent-Native Agent) to an existing web app or service so the user can operate it by watching a dashboard and chatting with a coding agent that runs inside tmux — chat is injected via tmux paste-buffer and the session is mirrored via capture-pane, with zero dependencies (no MCP, no bridge, no hooks, no plugin runtime). Use this whenever the user wants to "add ANA / a chat+watch dashboard to my app", "attach a coding-agent chat to an existing service", "make my dashboard talk to a tmux agent", "화면 보면서 대화로 조작", "기존 서비스에 ANA 붙이기", or to scaffold the standalone ANA base app. The single file `channel-core.js` is the whole runtime — drop it in and mount it.
---

# Attach ANA to your service

ANA turns any web app into one you **operate by watching + talking**: a coding agent runs inside a tmux pane; the browser sends chat that ANA injects into that pane, and mirrors the session (agent replies, tool activity, busy state) back to the page — no MCP, no bridge, no hooks. **The entire runtime is one dependency-free file: `channel-core.js`.**

## The whole idea (2 pieces)

```
[your web page] ──POST /api/chat──► server ──paste-buffer + Enter──► [tmux pane: claude / any agent]
      ▲                               │                                     │
      └── SSE /api/stream ◄───────────┘  300ms capture-pane → parse → ledger (auto-mirror)
```

1. **A server** that mounts `channel-core.js` and serves your HTML.
2. **A tmux session** running a coding-agent CLI (`claude`, or any).

## Attach in 3 steps (very simple)

**1. Copy `channel-core.js`** into your project (it is dependency-free, Node ≥ 20 + tmux).

**2. Mount it** — add ~12 lines to (or beside) your server:

```js
const path = require('node:path');
const core = require('./channel-core.js');
const app = core.createChannelServer({
  PORT: 8809, BIND: '127.0.0.1',
  SESSION: core.defaultSession(__dirname, process.env),   // TMUX_SESSION || <ANA name>-claude
  SOCKET: process.env.TMUX_SOCKET || '',          // default tmux socket
  TARGET: core.resolveTarget(__dirname, process.env),
  FEED_FILE: path.join(__dirname, '.ana', 'transcript.jsonl'),
  SERVABLE: new Set(['index.html']),              // your dashboard file(s)
  defaultDoc: 'index.html',
  autoConfigPane: true,                            // sets alternate-screen off on connect
});
app.listen(() => console.log('ANA → http://localhost:8809'));
```

**3. Add the chat widget** to your page — send with `POST /api/chat {text}` and stream with `GET /api/stream` (SSE). Minimal client:

```html
<script>
  const es = new EventSource('/api/stream');
  es.onmessage = (e) => { const d = JSON.parse(e.data); /* d.kind: snapshot|commit|pending|status|screen|draft */ };
  function send(text) { fetch('/api/chat', { method:'POST', headers:{'content-type':'application/json'}, body: JSON.stringify({ text, force: true }) }); }
</script>
```

## Run

```bash
tmux new -s base-ana-claude   # inside it, start your agent:  claude
node server.js                # → http://localhost:8809 , open in a browser
```

Session name = `<ANA name>-claude`. The ANA name is your project folder when it is `<xxx>-ana` (e.g. `~/ana/shop-ana` → `shop-ana-claude`), otherwise `base-ana`. The chat's session list shows only `<ANA name>-<yyy>` sessions (`-codex`, `-review`, …); `ANA_NAME`, `TMUX_SESSION` and `ANA_TMUX_ALL=1` override.

That's it — type in the page, the agent answers in the page.

## What channel-core gives you (the API)

| Endpoint | Purpose |
|---|---|
| `POST /api/chat` `{text, force?}` | inject a message into the tmux agent (use `force:true` from the web — it clears the input line first, avoiding false "draft" blocks) |
| `POST /api/keys` `{key}` | send a control key (`enter`/`esc`/`up`/`down`/`1`..`9`/`ctrl-c` …) — used to answer TUI dialogs |
| `GET /api/stream` (SSE) | snapshot + incremental `commit`/`pending`/`status`/`screen`/`draft`/`dialog`/`target` events for **the caller's session** |
| `GET /api/feed?since=<seq>` | that session's conversation ledger (cursor pagination) — survives restarts |
| `GET /api/health` | `{session, target, you, command, ready, dialog, dialogInfo, busy}` — connection + terminal-dialog state |
| `GET /api/config` / `POST /api/config {target}` | list tmux sessions (message count, who picked it, who is watching) / switch **your** session live — remembered per person |
| `GET /api/dialog` / `POST /api/dialog {action, n?, text?}` | structured terminal dialog (AskUserQuestion, permission menus) / answer it: `pick` n (+`text` for "Type something"), `submit` (multi-select), `next`/`prev` (question tabs), `esc` |
| `GET /api/screen` | raw pane snapshot (for a terminal view / dialog card) |

**Sessions.** Every tmux session (target) gets its own ledger (`.ana/transcripts/<target>.jsonl`; the default session keeps `.ana/transcript.jsonl`), poll loop, SSE subscribers and injection queue. A request's session is: `x-ana-target` header or `?target=` (explicit, e.g. for the agent's own `curl`) → the person's most recent pick (`.ana/targets.json`, keyed by the `userKey(req)` hook — the identity header in the ANA base) → the default `TARGET`. Switching sessions swaps the whole chat history, and each signed-in person lands on the session they used last.

## Rich responses (optional)

Plain replies mirror automatically. For **preview + approve** cards, the agent posts `POST /api/agent {text, diff}`; your server applies the diff on approval and bumps a `version` so every device re-syncs. See `dashboard-api.js` in the ANA base for the todo/schedule/memo/evolve reference implementation.

## Safety notes (already built in)

- Server binds `127.0.0.1` by default — a coding agent has tool-execution power, so never expose it unauthenticated (`BIND=0.0.0.0` is opt-in for trusted networks only).
- `/api/chat`/`/api/keys` require `content-type: application/json` + same-origin (CSRF guard). Only `SERVABLE` files are served.
- Injection is refused when the pane is a shell (agent exited) or a TUI dialog is open — surface `health.dialog` in your UI so the user can respond with `/api/keys`.

> Full reference app (dashboard with ANA mode, context chips, docked chat, evolution tab): the repository root. Run it, then copy the parts you want.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.