Install
$ agentstack add skill-lifecycle-innovations-limited-claude-ops-ops-pocket ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ● Filesystem access Used
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
OPS ► POCKET
Surfaces the Pocket voice-memo pipeline as a discoverable slash command. The pipeline was previously orphaned — 7 scripts, no entry point. This skill is the entry point.
For the full architecture reference (every state file, every script, every failure mode) see [STATUS.md](./STATUS.md) sibling to this file.
Runtime Context
Before any route runs, resolve:
- State dir:
${POCKET_STATE_DIR:-$HOME/.claude/state/pocket}. Every file mentioned below is relative to this dir. - Plugin root:
${CLAUDE_PLUGIN_ROOT}— used to invoke pipeline scripts underscripts/. - Daemon health snapshot:
${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/daemon-health.json— surface itspocket-*service status if present.
If $POCKET_STATE_DIR does not exist on disk, the pipeline has never been bootstrapped — route to setup automatically (no autoroute on status if the user explicitly asked for status).
Routing table
Parse $ARGUMENTS and route immediately. First token decides the route.
| First arg | Route | | --------------------- | --------------------------------------------------------------------------- | | (empty) / status | Status dashboard — daemon health + queue depths + cursors + counts | | setup | Delegate to skills/setup/channels/pocket.md if present; else inline steps | | tasks | Pending + in-progress + recently-completed task list | | test | End-to-end synthetic completion test (covered below) | | logs [N] | Tail N lines (default 50) of notifier + run + executor logs | | restart | Kickstart launchd notifier + (re)spawn pocket-exec tmux supervisor | | whatsapp on / off | Toggle WhatsApp self-chat sink | | email on / off | Toggle email self-mail sink |
Anything else: print the routing table and exit.
Route — status (default)
The default route. Read state files, render a compact dashboard.
Read these — in parallel where possible:
STATE_DIR="${POCKET_STATE_DIR:-$HOME/.claude/state/pocket}"
# Daemon plist liveness
launchctl list com.claude-ops.pocket-activity-notifier 2>/dev/null \
| awk '/PID/{print "pid="$3} /LastExitStatus/{print "exit="$3}'
# Supervisor tmux session
tmux has-session -t pocket-exec 2>/dev/null && echo "tmux=up" || echo "tmux=down"
tmux list-windows -t pocket-exec 2>/dev/null | wc -l
# Queue depths (line counts)
wc -l /dev/null
wc -l /dev/null
wc -l /dev/null
wc -l /dev/null
# Completed reports
ls "$STATE_DIR/executor-results/"*.done.json 2>/dev/null | wc -l
# Last pull cursor
cat "$STATE_DIR/cursor.txt" 2>/dev/null
# Last 3 notifications (from out-queue-sent.jsonl)
tail -n 3 "$STATE_DIR/out-queue-sent.jsonl" 2>/dev/null
# Per-component health
for h in .activity-notifier-health .out-queue-health .email-bridge-health .health; do
cat "$STATE_DIR/$h" 2>/dev/null
done
Output format (desktop):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
OPS ► POCKET — [timestamp]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
DAEMONS
watcher [running|stalled] last tick [Xs ago]
triage [running|idle]
executor watchdog [running|stalled] tmux pocket-exec=[up|down] (N windows)
activity-notifier [running|stalled] pid [N]
out-queue [running|disabled|error]
email-bridge [running|disabled|error]
QUEUES
pending-triage [N items] (awaiting ACT/SKIP decision)
tasks.jsonl [N items] (canonical task store)
spawn-ledger [N spawns]
out-queue [N pending]
executor-results [N .done.json]
CURSORS
watcher last pull [ISO timestamp from cursor.txt]
last completion [latest .done.json mtime]
CHANNELS
whatsapp [on|off|misconfigured] chat_jid=[masked tail]
email [on|off|misconfigured] to=[masked]
LAST 3 NOTIFICATIONS
[N. kind type | task_id | sent_at]
──────────────────────────────────────────────────────
Mobile mode (Rule 7 — $SSH_CONNECTION/$SSH_CLIENT/$SSH_TTY set OR $OPS_MOBILE=1 OR `$COLUMNS 0, etc.). On a clean board, exit silently.
Route — setup
Delegate to the setup channel doc when it exists:
SETUP_DOC="$CLAUDE_PLUGIN_ROOT/skills/setup/channels/pocket.md"
[[ -f "$SETUP_DOC" ]] && cat "$SETUP_DOC"
If pocket.md does not exist, print the inline onboarding sequence:
- Confirm
pocket-cli(or equivalent Pocket API auth) is on PATH. - Drop a
whatsapp-config.jsonand/oremail-config.jsonunder$STATE_DIR(see STATUS.md for schemas). - Run
bash $CLAUDE_PLUGIN_ROOT/scripts/install-pocket-notifier.shto register the launchd LaunchAgent. - Verify with
/ops:pocket status.
Per Rule 4 (background by default during setup) and Rule 2 (never delegate commands to the user) — run the install script via Bash with run_in_background: true. Per Rule 3, never auto-skip channel selection — if whatsapp-config.json and email-config.json are both missing, ask via AskUserQuestion which to configure first ([WhatsApp] / [Email] / [Both] / [Skip]).
Route — tasks
Render a single combined list. No AskUserQuestion — read-only by default.
STATE_DIR="${POCKET_STATE_DIR:-$HOME/.claude/state/pocket}"
# Pending triage (awaiting ACT/SKIP)
tail -n 50 "$STATE_DIR/pending-triage.jsonl" 2>/dev/null
# Live tasks (canonical store)
tail -n 50 "$STATE_DIR/tasks.jsonl" 2>/dev/null
# In-flight workers (windows in pocket-exec tmux, excluding _idle + supervisor)
tmux list-windows -t pocket-exec -F '#{window_name}' 2>/dev/null \
| grep -vE '^(_idle|supervisor)$'
# Recently completed (.done.json sorted by mtime, last 10)
ls -t "$STATE_DIR/executor-results/"*.done.json 2>/dev/null | head -10
Format:
PENDING TRIAGE (N)
[id] [created] [title]
ACTIVE TASKS (N)
[task_id] [status] [title] [started]
IN-FLIGHT WORKERS (N)
[tmux window name] [up since]
RECENTLY COMPLETED (last 10)
[task_id] [duration] [report file]
Route — test (synthetic end-to-end)
Smoke-tests the full notifier → out-queue → both bridges path without going through the watcher or triage. Same flow as the manual session-level test that was run when the notifier shipped.
Steps:
- Pre-flight: verify
$STATE_DIR/whatsapp-config.jsonORemail-config.jsonhasenabled: true. If neither: printnot configured — run /ops:pocket setupand exit. - Generate a synthetic task_id like
test-$(date +%s). - Append a tasks.jsonl entry for the synthetic task (so the notifier can title-resolve it):
``bash echo "{\"task_id\":\"$TID\",\"title\":\"synthetic pocket test\",\"created_at\":\"$(date -u +%FT%TZ)\",\"verdict\":\"ACT\"}" \ >> "$STATE_DIR/tasks.jsonl" ``
- Drop a synthetic
.done.jsonintoexecutor-results/:
``bash cat > "$STATE_DIR/executor-results/$TID.done.json" "$STATE_DIR/executor-results/$TID.out.md" ``
- Manually invoke the notifier once (don't wait 60s for launchd):
``bash "$CLAUDE_PLUGIN_ROOT/scripts/ops-pocket-activity-notifier.py" --once 2>&1 | tail -20 ` (If --once is not supported, run the script with POCKETNOTIFIERONESHOT=1 env var, or just python3 ops-pocket-activity-notifier.py`.)
- Drain both bridges in parallel:
``bash "$CLAUDE_PLUGIN_ROOT/scripts/ops-pocket-out-queue.py" 2>&1 | tail -10 "$CLAUDE_PLUGIN_ROOT/scripts/ops-pocket-email-bridge.py" 2>&1 | tail -10 ``
- Verify delivery — for each enabled channel:
- WhatsApp: tail
$STATE_DIR/out-queue-sent.jsonlfor an entry with the synthetic task_id. (Do NOT usemcp__whatsapp__list_messages— the bridge's own sent ledger is the source of truth.) - Email: tail
$STATE_DIR/email-bridge.logforSENTon the synthetic task_id.
- Cleanup:
``bash rm -f "$STATE_DIR/executor-results/$TID.done.json" \ "$STATE_DIR/executor-results/$TID.out.md" ` Leave the tasks.jsonl` line (append-only log; harmless).
Report:
POCKET ► TEST
task_id: [tid]
whatsapp: [SENT|SKIPPED-disabled|FAIL: reason]
email: [SENT|SKIPPED-disabled|FAIL: reason]
duration: [Xs]
If any channel fails, surface the last error line from the corresponding *.log and .health file.
Route — logs [N]
N="${ARG_2:-50}"
STATE_DIR="${POCKET_STATE_DIR:-$HOME/.claude/state/pocket}"
for f in activity-notifier.log run.log executor.log out-queue.log email-bridge.log; do
echo "==> $f /dev/null || echo "(missing)"
done
For Rule 7 mobile mode, default N=20 and skip per-file headers.
Route — restart
# 1. Kickstart the launchd activity-notifier
launchctl kickstart -k "gui/$(id -u)/com.claude-ops.pocket-activity-notifier" 2>&1
# 2. (Re)spawn the pocket-exec supervisor via the executor watchdog cron script
"$CLAUDE_PLUGIN_ROOT/scripts/ops-cron-pocket-executor.py" 2>&1 | tail -10
If the launchd label is missing (notifier never installed), prompt via AskUserQuestion: [Install notifier now] / [Skip]. On install: run scripts/install-pocket-notifier.sh (Rule 4: run_in_background: true).
Route — whatsapp on|off and email on|off
Both routes mutate a small JSON config file. Never overwrite the whole file — patch in place.
STATE_DIR="${POCKET_STATE_DIR:-$HOME/.claude/state/pocket}"
CFG="$STATE_DIR/whatsapp-config.json" # or email-config.json
ACTION="${ARG_2}" # on | off
mkdir -p "$STATE_DIR"
if [[ ! -f "$CFG" ]]; then
# Bootstrap empty config with enabled=false so subsequent `on` is meaningful.
echo '{"enabled":false}' > "$CFG"
fi
case "$ACTION" in
on) python3 -c "import json,sys,pathlib; p=pathlib.Path('$CFG'); d=json.loads(p.read_text()); d['enabled']=True; p.write_text(json.dumps(d,indent=2))" ;;
off) python3 -c "import json,sys,pathlib; p=pathlib.Path('$CFG'); d=json.loads(p.read_text()); d['enabled']=False; p.write_text(json.dumps(d,indent=2))" ;;
*) echo "usage: /ops:pocket {whatsapp|email} {on|off}"; exit 2 ;;
esac
# Echo new state
cat "$CFG"
Required keys per channel (validated by status):
whatsapp-config.json—chat_jid(WhatsApp JID of the self-chat, e.g.@s.whatsapp.net).email-config.json—to(self-email address).
If on is requested but the required key is missing, switch state to enabled: false and route the user to setup via AskUserQuestion.
Rule reminders
- Rule 1: Max 4 options per
AskUserQuestion. None of the routes above need more. - Rule 2: Never delegate commands to the user — every command runs through Bash.
- Rule 3: Never auto-skip channels in
setup— always ask explicitly. - Rule 4: Background by default in
setup(run_in_background: true). - Rule 5: This skill performs NO destructive ops — no deletes, no terminates, no force-kills beyond
launchctl kickstart -k(which is a graceful restart, not a wipe). - Rule 6: No outbound comms staged from this skill except the synthetic test message in
test, which goes to the operator's OWN self-chat / self-email (already enabled by the user) — not to third parties. Per-message approval rule is satisfied by the test being a no-args opt-in. - Rule 7: Mobile mode renders plain text only — see
statusexample.
Native tool usage
AskUserQuestion: only when there is a real choice to make (stalled daemon → restart? missing channel config → bootstrap?). Never required on a green status.Skill:setuproute may delegate to the setup channel doc.
See also
- [
STATUS.md](./STATUS.md) — full architecture: 8 scripts, every state file, lifecycle, troubleshooting. scripts/ops-cron-pocket-watcher.py,scripts/ops-pocket-triage.py,scripts/ops-cron-pocket-executor.py,scripts/ops-pocket-activity-notifier.py,scripts/ops-pocket-out-queue.py,scripts/ops-pocket-email-bridge.py,scripts/ops-pocket-whatsapp-bridge.py.scripts/install-pocket-notifier.sh,scripts/com.claude-ops.pocket-activity-notifier.plist.templates/pocket-supervisor-prompt.md— the prompt the long-lived supervisor runs under.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Lifecycle-Innovations-Limited
- Source: Lifecycle-Innovations-Limited/claude-ops
- License: MIT
- Homepage: https://github.com/Lifecycle-Innovations-Limited/claude-ops/wiki
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.