| name | bash-manual |
| description | **Read this before running long-lived agent/coding CLIs (`claude -p`, `codex exec`, `opencode run`, Cursor agent CLI), or before setting up cron, launchd, systemd timers, crontab jobs, or scheduled reminders.** Router for Bash-related operational depth beyond the bash tool schema: async + poll discipline for long-running child agents, host-scheduler setup, LingTai wake-by-mailbox-drop, script hygiene, one-shot `.notification/cron.json` reminders, debugging silent jobs, and safe cleanup. Start here for any long-running agent CLI, time-driven recurring work ("every hour", "weekdays at 9", "remind me later"), or when a scheduled job misbehaves.
|
| version | 1.4.0 |
Bash Manual — Router
The bash tool schema covers one-off command execution. This manual routes to
operational depth that is too long for the schema: host scheduling, mailbox-drop
wakeups, reminder files, debugging, and cleanup.
For ordinary short, deterministic one-off shell commands, use the tool schema
synchronously. For anything involving time, recurring work, external schedulers,
a silent scheduled job, or a long-running agent/coding CLI (see the resident
rule below), start here.
Nested reference catalog
bash-manual owns these nested references. They are parent-owned drill-down
files, not standalone top-level skills.
- name: bash-scheduled-work
location: reference/scheduled-work/SKILL.md
description: |
Cron-driven scheduled work: when to use host schedulers, the LingTai
wake-by-mailbox-drop contract, prompt boundaries, script hygiene, macOS
launchd, Linux systemd timers, crontab fallback, and the launchd
process-tree reaping gotcha.
- name: bash-notification-reminders
location: reference/notification-reminders/SKILL.md
description: |
One-shot wakeup reminders via `.notification/cron.json`: payload shape,
atomic writer, shell example, and the rest checklist for agents leaving work
pending.
- name: bash-debugging-cleanup
location: reference/debugging-cleanup/SKILL.md
description: |
Debugging and cleanup for scheduled jobs: scheduler fired, script ran, work
landed, agent saw mail, worked launchd diagnosis, retiring cron jobs, and
bash work footprint hygiene.
Router table
| Need / keywords | Read |
|---|
Running a long-running agent/coding CLI as a sub-process: claude -p, codex exec, opencode run, Cursor agent CLI; "run an agent in the background"; avoid blocking the turn | "Core rules to keep resident" below (use bash(async=true) + poll) |
| Human asks for time-driven recurring work: "every hour", "daily", "weekdays at 9", "write/check/send on a schedule"; choose cron vs event watcher; create launchd/systemd/crontab wiring; understand wake-by-mailbox-drop; write scheduler prompt/script hygiene | reference/scheduled-work/SKILL.md |
Need a one-shot reminder or wakeup nudge while work is pending; .notification/cron.json; atomic reminder writer; rest checklist | reference/notification-reminders/SKILL.md |
| Scheduled job is silent, fires twice, exits immediately, gets killed by launchd, fails to deliver mail, or must be retired/cleaned up | reference/debugging-cleanup/SKILL.md |
Quick decision tree
- Short deterministic host work (finishes in seconds:
ls, git status,
grep, a quick build)? Use bash synchronously; this manual is not needed
unless the command is risky, scheduled, or failing mysteriously.
- Long-running agent/coding CLI (
claude -p, codex exec, opencode run,
Cursor agent CLI, or any sub-agent that may think/run tools for minutes)?
Never run it synchronously. Use bash(async=true) and poll — see the
resident rule below.
- Time itself is the trigger? Read
reference/scheduled-work/SKILL.md.
- You only need a single future nudge? Read
reference/notification-reminders/SKILL.md.
- A scheduled job already exists and is misbehaving? Read
reference/debugging-cleanup/SKILL.md before editing blindly.
Core rules to keep resident
-
Synchronous bash is only for short, deterministic commands. A long-running
agent/coding CLI session — claude -p, codex exec, opencode run, the Cursor
agent CLI, or any sub-agent that may think and run tools for minutes — must
never be a synchronous bash call. Run it with bash(async=true) and poll
the returned job_id. A synchronous call blocks the whole turn until the child
exits: you stay ACTIVE and stop seeing channel notifications (mail, refresh,
interrupts) for the entire duration. Async + poll keeps you responsive and
prevents ACTIVE blockage while the child CLI works.
# Start the child agent in the background — returns immediately with a job_id:
bash(async=true, command="claude -p 'refactor the auth module' --output-format json")
# → {"status": "ok", "job_id": "ab12…", "pid": 4321}
# Later turns: poll until done (handle mail/other work between polls):
bash(action="poll", job_id="ab12…")
# → {"status": "running", …} then eventually
# → {"status": "done", "exit_code": 0, "stdout": "…", "stderr": "…"}
# Abandon it if needed:
bash(action="cancel", job_id="ab12…")
-
If repeated-call _advisory appears on bash(action="poll"), stop
tight polling. The poll already executed; the advisory is not a block. If
the job is still running and nothing meaningful changed, handle any human
messages, do other work, or set one future reminder (bash notification
reminder or internal delayed self-email) and yield/idle. Poll again only when
a completion notification arrives, the reminder fires, or you have a concrete
reason to expect new state.
-
Idle care: never hand a launched async job entirely to its completion
notification. Once you start a long-running agent/coding CLI with
bash(async=true) (or any child sub-process), do not go fully IDLE relying
only on the completion/IDLE signal. Before resting, arm at least one
self-wake (a .notification/cron.json reminder or an internal delayed
self-email). Pick the delay from the task's expected duration — not a fixed
number; a 30 s scan and a 40 min build warrant different windows. When the
wake fires, health-check rather than assume progress: confirm the log is
growing, the PID/child is alive, the output file/worktree shows
progress, and the job is not stuck on an interactive prompt or a
provider/model error. If there is no progress, do not keep waiting — cancel,
downgrade, or switch path, and report to the human. A job that exits
immediately or sits silent past its expected window is the failure mode this
rule exists to catch.
-
LingTai has no built-in recurring scheduler. Host schedulers wake agents by
producing channel input, usually a mailbox-drop or notification file.
-
Prefer event watchers/webhooks when an external event is the real trigger;
prefer cron/launchd/systemd only when time is the trigger or polling is truly
the right tradeoff.
-
Scheduler scripts must be idempotent, audited, logged, absolute-path based,
and explicit about how they wake the agent.
-
On macOS, remember launchd process-tree reaping; use the documented
double-fork pattern when a child process must outlive the launchd job.
-
Do not leave silent janitors or hidden recurring jobs behind. Document and
clean them up when the human no longer needs them.
Maintenance
Keep this top-level router short. Add detailed examples, platform recipes, and
troubleshooting trees to nested references so agents can load only the section
needed for the current task.