Synced from pluk. This page is pulled from hivecommons/pluk@main during the docs build. Edit the canonical source in the pluk repository.

@hivecommons/pluk

Pluk structured events from AI agent terminal output.

TypeScript port of hivecommons/pluk — classify, subscribe, and react to JSONL event streams from AI coding agents (Claude Code, GitHub Copilot CLI, Gemini CLI, Goose, etc.).

Install

npm install -g @hivecommons/pluk

Quick Start command to create a tmux session, start an AI CLI, attach pluk event capture, and wire up rationguard for real-time excuse detection:

pluk attach my-agent --cli=claude --rationguard --rebuttal=send

This does four things:

  1. Creates a tmux session named my-agent
  2. Starts claude inside it
  3. Attaches pluk via tmux pipe-pane to classify all terminal output
  4. Starts rationguard watch to detect rationalizations and send rebuttals back

To just attach pluk without rationguard:

pluk attach my-agent --cli=claude

To attach to an existing tmux session (e.g., already running goose):

pluk attach my-agent --cli=goose

Note: When attaching to an existing session with --dangerous, the CLI may not have permission-skip enabled (the flag applies when creating a new session). pluk will print a warning with the command to restart the CLI with the right flag.

A new terminal window is always opened for the tmux session (unless --no-open is set), so you can interact with the agent directly.

See What’s Running

pluk sessions
SESSION          CLI       STATE     TMUX  LAST ACTIVITY EVENTS
scanner          claude    working   ●     2s ago        1204
helper           claude    idle      ●     45s ago       892
goose-exp        goose     idle      ○     3m ago        156

Manual Setup

If you prefer to wire things up yourself:

# 1. Start an AI agent in tmux
tmux new-session -d -s my-agent
tmux send-keys -t my-agent "claude" Enter
 
# 2. Attach pluk to capture output
export PLUK_RUN_DIR=/tmp/pluk-run
tmux pipe-pane -t my-agent -o "pluk watch my-agent --cli=claude"
 
# 3. Subscribe to events (another terminal)
pluk subscribe my-agent --filter=state_change,rate_limit,error
 
# 4. Or start rationguard for real-time detection
rationguard watch my-agent --rebuttal=send
 
# 5. View the agent
tmux attach -t my-agent

CLI Commands

CommandWhat it does
pluk attach <session>Create tmux + start CLI + wire pluk (+ rationguard)
pluk sessionsList active pluk-monitored sessions
pluk subscribe <session>Tail a pluk JSONL log (like tail -f)
pluk watch <session>Classify stdin line-by-line
pluk send <session> --text="..." --enterSend text to a tmux session
pluk patterns --cli=claudeShow loaded patterns for a CLI

Attach Flags

FlagWhat it does
--cli=claudeCLI type: claude, copilot, gemini, goose, codex, aider
--rationguardStart rationguard watcher alongside pluk
--rebuttal=sendAuto-send rebuttals when rationguard detects excuses
--dangerousSkip CLI permission prompts (--dangerously-skip-permissions for claude, --full-auto for codex, --non-interactive for goose)
--dir=/pathWorking directory for the agent
--cli-args="..."Extra arguments to pass to the CLI
--no-openDon’t open a terminal window
--verboseShow debug output

Programmatic API

import { Classifier, getPatterns, subscribe, watch, discoverSessions, attach, send } from '@hivecommons/pluk';
 
//-command setup: tmux + CLI + pluk + rationguard
attach({
  session: 'my-agent',
  cli: 'claude',
  rationguard: true,
  rebuttal: 'send',
  dangerouslySkipPermissions: true,
});
 
// Send text to a tmux session
send({ session: 'my-agent', text: 'check the build', enter: true });
 
// Discover running sessions
const sessions = discoverSessions('/tmp/pluk-run');
for (const s of sessions) {
  console.log(`${s.session}: ${s.cli} (${s.state}, ${s.lastActivityAgo})`);
}
 
// Classify individual lines
const patterns = getPatterns('claude');
const classifier = new Classifier({ session: 'my-agent', patterns });
const event = classifier.classify('● Read main.go');
// → { type: 'tool_call_started', data: { tool: 'Read', ... } }
 
// Subscribe to a JSONL log file (tail -f behavior)
const sub = subscribe('my-agent', (event) => {
  console.log(event.type, event.data);
}, { filter: ['rate_limit', 'error'] });
 
// Watch stdin for events
const watcher = watch({
  session: 'my-agent',
  cli: 'claude',(event) {
    if (event.type === 'rate_limit') {
      console.warn('Rate limited!', event.data.message);
    }
  },
});

Event Types

TypeMeaning
raw_outputEvery non-empty terminal line
state_changeAgent went idle or started working
rate_limitUsage limit / quota exhausted
login_requiredAuthentication needed
trust_dialogFolder trust prompt
bypass_permissionsPermission bypass prompt
tool_call_startedAgent invoked a tool
tool_call_completedTool finished
errorError in output
model_changedModel was switched
session_endedCLI session ended
command_receivedCommand sent via pluk-send

Send Command

Inject text into a running tmux session — used by rationguard to send rebuttals, or by you to send commands:

# Send text and press Enter
pluk send my-agent --text="check the build logs" --enter
 
# Send literal text (no key interpretation)
pluk send my-agent --text="hello world" --literal
 
# Also available as a standalone binary
pluk-send --session=my-agent --text="test" --enter

Supported CLIs

Built-in pattern files for: Claude Code, GitHub Copilot CLI, Gemini CLI, Goose CLI, Codex, Aider.

Custom patterns can be loaded from a directory with --patterns-dir or getPatterns(cli, patternsDir).

Works With

License

Apache-2.0