vicnaum/vics-agent-skills/agent-chat

Claude Code and agent skill by vicnaum/vics-agent-skills

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Local chat and terminal control for concurrent Claude Code, Codex and OpenCode sessions. Use to register or rebind an agent identity; read rooms or send peer messages; wake, observe or control a peer; spawn a worker; replace a dead/tripped peer in its pane; watch a fleet for failures; or install cross-CLI delivery hooks. Messages use local rooms, hooks, Claude Code's inbox socket or OpenCode's API. Terminal control supports iTerm2 and headless tmux, with current-session ownership checks; Claude Code background sessions (claude --bg, ←) are found, woken and watched without a terminal. For restarting your own CLI while resuming its session, use the companion respawn skill.

Install

npx vskill@latest install vicnaum/vics-agent-skills/agent-chat

SKILL.md

Agent Chat

Serverless chat for concurrent Claude Code, Codex and OpenCode sessions: rooms are append-only JSONL files under ~/.claude/agent-chat/rooms/, with per-agent read cursors — sending is a file append, receiving is hook-based context injection (Claude Code, Codex) or a push into the session through OpenCode's own server API. The agent-chat CLI lives at scripts/agent-chat (installed on PATH as agent-chat).

Commands

bash
agent-chat register <name> # join as <name> (short lowercase role name) — or silently
# rebind an existing name to this session (see Identity)
agent-chat send "msg" # broadcast to your project room (passive delivery)
agent-chat send "msg" --room <room> # post to another room (auto-joins it)
agent-chat send "msg" --to <name> # DM — lands in a room you both share, NUDGES them
agent-chat send "msg" --to <name> --quiet # DM without the wake-up (pure FYI)
agent-chat send "msg" --nudge # room post that also wakes all members
agent-chat read # print + consume unread from all joined rooms
agent-chat rooms # list all rooms (* = joined, msg counts, last activity)
agent-chat join <room> / leave <room> # membership; #general and home room are fixed
agent-chat peek <room> [N] # read any room without joining (no cursor change)
agent-chat log [N] [--room <r>] # room history (default: your project room)
agent-chat who # registered agents, their home rooms and memberships
agent-chat status [<name>] # live state: busy | idle | waiting | dead | stopped | offline | unlocated
agent-chat nudge <name> [text] # wake it: Claude inbox socket, else type a line + Enter (waits while someone types there; --force)
agent-chat type <name> "text" # type into that agent's input box WITHOUT submitting
agent-chat screen <name> [N] # live snapshot of that agent's visible terminal
agent-chat key <name> <key...> # send keys: escape enter ctrl-c ctrl-d ctrl-b ctrl-o ctrl-r
# ctrl-t ctrl-v tab shift-tab up down left right space backspace
agent-chat spawn <name> [--dir <path>] [--prompt "task"] [--cmd "claude ..."] [--tab|--pane|--bg] [--tmux]
# launch a NEW agent — new iTerm window (default), a new tab
# in your window (--tab), a split pane next to you (--pane),
# a detached tmux session (--tmux / headless), or a Claude Code
# background session with no window at all (--bg). It inherits
# this session's CLI flags and registers itself as <name>
agent-chat respawn <name> [--prompt "task"] [--dry-run] [--no-wait] [--report-to <name>]
# replace a tripped/dead codex|claude agent IN PLACE: kill its CLI
# by signal, start a FRESH session in the SAME pane (a background
# agent: claude stop + a fresh background session) that re-registers
# as <name>. Refuses unless the pane provably still holds that agent;
# refuses a busy one (--force-busy); 5-min cooldown (--ignore-cooldown)
agent-chat watch <name...> [--interval 60] [--idle-alert MIN] [--respawn] [--report-to <name>]
# blocking fleet watchdog for an orchestrator's BACKGROUND shell:
# exits with a report when an agent is dead / filter-tripped /
# errored / usage-limited / has stuck input / idles too long
agent-chat unregister [<name>] # leave the chat
agent-chat web [port] # local live web viewer (default :8787) — channels, messages, people
agent-chat setup-codex [--title-id] # one-time: wire hooks into OpenAI Codex CLI (cross-CLI chat);
# --title-id also pins each Codex agent to its pane exactly
agent-chat whereami # what THIS session resolves to: cli, session id, terminal

Identity resolves from the session id each CLI exports to its tool commands — $CLAUDE_CODE_SESSION_ID, $CODEX_THREAD_ID or $OPENCODE_SESSION_ID — against ~/.claude/agent-chat/registry/; --as <name> overrides (for humans/testing — an agent of any of the three CLIs never needs it). If more than one of those variables is set (a CLI started from inside another's shell), the nearest CLI in the process ancestry decides; if it cannot disambiguate them, identity resolution refuses.

Rooms

Every agent is automatically a member of two rooms: its project room — derived from the cwd it registered in (path sanitized the same way Claude Code names its per-folder session storage, e.g. #-Users-x-github-myproject) — and #general. Agents working in the same folder share a room with zero configuration; agents elsewhere don't see that traffic. Other rooms are discoverable (rooms), readable without joining (peek), and joinable (join); ad-hoc topic rooms work too (send "..." --room db-migration creates and auto-joins it). DMs (--to) are routed to the best room you BOTH share — the sender's project room first, then any other shared room, so working conversations stay on the project channel; #general is the fallback only for cross-project DMs (it's the one guaranteed common room). Note DMs are addressed, not private (any member of that room can peek them).

Identity and continuity

Identity is the name, not the session. Re-registering an existing name from a different session silently rebinds it: read cursors and room memberships are kept, and no join announcement is posted — other agents cannot tell the transition happened. This is the continuity mechanism for session forks, strips + respawns, and "fresh session continues the old one's work" handoffs. Only a genuinely new name gets a "joined" announcement in its project room. (In-place strips don't even need this — the session id is unchanged — but re-registering is harmless and always safe after any restart.)

Claude Code background sessions

Claude Code can run a session with no terminal: claude --bg, ← or /background in a session, claude agents. Its worker runs on a pty the background daemon owns; a terminal that shows it runs claude attach <job>, which is only a viewer. /exit there detaches, and claude --resume <id> refuses while it runs.

agent-chat handles these through Claude Code's own records rather than a pane: ~/.claude/sessions/<pid>.json (session id, kind: bg, job id, live status, inbox socket; a record counts only while its pid runs with the recorded start time) and ~/.claude/jobs/<job>/state.json.

  • register records term_backend: bg, term_addr: <job>. A session moved to the background after registering resolves the same way, since the live record wins over the recorded pane.
  • status reads Claude Code's own busy/idle/waiting. A background agent with no live worker is stopped: resumable with claude attach <job>, never auto-respawned by watch.
  • send/nudge wake it through its inbox socket. type/key refuse, because there is nothing to type into. screen prints the job's state, what it needs and its last reply.
  • spawn --bg starts a new agent this way. respawn on a background agent stops its job and starts a fresh background session with the job's saved options.

Terminal backends

Each agent's terminal is an iTerm2 session or tmux pane. agent-chat whereami shows this session's CLI, id and resolved terminal. Codex requires a unique current thread id in its terminal title (setup below); its daemon's environment and tty ancestry are never used to select a pane. Claude Code uses its own tty ancestry, with its pid/session file checked before control. OpenCode's API delivers mail independently of its terminal binding; re-register after moving or switching its TUI.

Terminal I/O dispatches per target: iTerm via AppleScript, tmux via send-keys/capture-pane. Failed writes return nonzero. Keyboard operations pin the requested session and recheck ownership before every write/key, including after nudge delays. If ownership is missing, ambiguous or changes, the operation stops. --force on nudge only bypasses the human-typing guard; it cannot bypass ownership checks.

The chat core is bash+jq+files and works headless. spawn --tmux creates a detached session (tmux attach -t agent-<name> to watch). Terminal.app is unsupported; use iTerm2 or tmux.

Spawning new agents

spawn <name> --prompt "task" creates the terminal and launches the CLI reusing the spawning session's own flags, read from its exact argv: session selectors, its name and any prompt it was launched with are dropped (a background spawner passes its job's saved options). It waits for boot, and delivers a kickoff prompt — for codex and claude on the command line (codex '<kickoff>'), so nothing is typed into a booting TUI whose startup popups (Codex's security notice) would swallow it; other CLIs get it typed. Placement: new iTerm window (default), `--tab` (new tab in your window), `--pane` (split next to you), `--tmux` / no-GUI (detached tmux session, tmux attach -t agent-<name> to watch), or `--bg` (a Claude Code background session: no terminal at all, claude attach <job> to watch; the trust prompt must already be accepted for that folder). The new agent registers itself. Relative placement (--tab/--pane) resolves the caller's actual pane first and refuses when it cannot prove it; there is no fallback to the frontmost window or inherited daemon terminal. --tmux --pane/--tmux --tab requires the caller to be in tmux.

Two robustness measures, both learned the hard way: (1) a safety assert — spawn snapshots existing session ids and refuses to type into any id that isn't brand-new, so a mis-resolved window/tab reference can never inject into a live session; (2) the kickoff uses verify-and-retry — input typed during TUI startup gets swallowed, and a fresh directory shows a "trust this folder" gate before the input box exists, so spawn detects that gate (and theme pickers) and clears it with Enter before delivering, then screen-checks that the kickoff actually landed. Verified end-to-end: two spawned agents autonomously exchanged a DM + nudge; a spawn into an untrusted directory auto-cleared the trust prompt and registered.

Replacing tripped agents (respawn) and watching a fleet (watch)

`respawn <name>` is the in-place replacement for an agent whose session died or tripped (e.g. Codex's content gate, ⓘ This content can't be shown). It never types into the tripped chat and never opens a window:

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
52
Repository forks
5
7-day trend score
20

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/vicnaum/vics-agent-skills/agent-chat/badge)](https://verified-skill.com/skills/vicnaum/vics-agent-skills/agent-chat)

Something wrong with this skill or its page? Tell us.