Install
$ agentstack add skill-tanchuping-codex-task-watchdog-codex-watchdog ✓ 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 No
- ✓ 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
Codex Watchdog
Use scripts/codex_watchdog.py as the only state-changing interface. Resolve it from this skill's directory and invoke it by absolute path; do not rely on the current working directory.
Honor control requests
Treat these requests as executable controls, including in a brand-new conversation:
- On “关闭watchdog” or equivalent, run
python disable, then report the returned state. - On “启用watchdog” or equivalent, run
python enable, then report the returned state. - On a watchdog status request, run
python status, then report the result. - On “卸载/彻底移除 watchdog”, run
disableand thenuninstall. Preserve the skill and incident files unless the user separately asks to delete them.
Do not merely acknowledge these requests. disable persists across conversations; while disabled, do not arm jobs unless the user enables monitoring again.
Monitor long work
For each tool or delegated worker expected to exceed 30 seconds:
- Check
statusonce before an immediately launched batch. If enabled, classify each attempt and have the main conversation choose a rolling no-progress threshold from [references/timeout-policy.md](references/timeout-policy.md). Runarm --kind KIND --turn auto --generation 1 --timeout-seconds CHOSEN-SECONDS --label SHORT-LABELfor every initial attempt. The script usesCODEX_THREAD_IDwhen available and otherwise keeps anunknown-threaddiagnostic label; tag UUIDs still isolate jobs. Retain the exact unique tag returned by the script. - Keep parallel work isolated: assign one tag to one attempt, and pass that exact tag to every later command.
- Observe the real worker or output at least every 30 seconds. The main conversation or a dedicated monitoring subagent may record a heartbeat after judging the attempt healthy from current evidence such as advancing scan counters, new stream/log/tool-call records, changing output files, active process work, worker phase changes, or other task-specific progress. A timer tick or an unchanged “thinking” label alone is not proof of progress.
- Treat expiry of the chosen interval as a mandatory review point, not an automatic stop. Inspect the exact attempt without preempting the main task. If current evidence shows normal progress, run
heartbeat TAG --note EVIDENCEand continue waiting. Absence-only evidence—including no completed command, unchanged files, no child process,post_tool_transition_unobserved,model_preparing_no_request, or a quiet model stream—never authorizes interruption. Stop only on explicit user instruction or positive terminal/failure evidence. A task may run much longer thantimeout_secondswhile it continues producing verified progress. Keep the separate 180-second hard limit for a single image-generation attempt when the active repository or user instructions require it. - Always run
disarm TAG --reason REASONimmediately on completion, failure, cancellation, or a confirmed abnormal stall. Use a new generation and a new tag for any retry.
Never automatically replay a tool that can spend quota, send messages, mutate files, or otherwise cause side effects unless an active user instruction explicitly pre-authorizes that retry. After a reconnect or interruption, inspect status, bounded list, bounded incidents, and actual outputs before deciding whether anything is genuinely missing. Compatibility --all output is still capped and must not be used as a routine context dump.
The external timer cannot penetrate an app-server, client, or network stall and cannot force the model to resume. It can persist evidence and notify the user; it is not proof that the Agent is alive.
Review and recover a stopped task
Run python recover-plan --thread THREAD [--turn TURN] after an alert. This command is bounded and read-only: it does not send a prompt, replay a tool, stop a worker, or create a task.
Then recover in this order:
- Inspect the target task through the Codex task/thread interface, including incomplete model output and current activity. Do not judge only from completed tool-call logs or file timestamps; an agent may be actively composing code before either changes.
- If the task is active, streaming, preparing a model request, editing, or otherwise advancing, leave it untouched. Heartbeat only the exact tag when there is concrete progress evidence.
- If the task is confirmed terminal or idle, remains unfinished, and has no advancing output, send one concise continuation to that same task. Tell it to inspect its existing disk state and continue the exact unfinished step. Do not duplicate the work in the monitoring task and do not start a competing worker.
- After a reconnect, verify actual outputs before any retry. A missing UI notification is not proof that a side effect failed.
- Use a small disk handoff and ask for a clean task only when same-task recovery is impossible or thread health is
critical. Never fork or clone a critical history.
Treat severity: review, evidence_class: absence_only, or safe_to_interrupt: false literally. These are review notices, not stall verdicts. The watchdog must remain lower-cost than the work it monitors; avoid repeated broad log scans or diagnostic prompts that preempt normal work.
Create a visible sidebar task when explicitly requested
Treat “新开”, “新开对话”, “开 side chat”, “开一个左边栏可见的任务”, “换干净任务继续”, and equivalent wording as explicit authorization when the recovery context already identifies the work to hand off. Do not ask the user to repeat the authorization.
A visible user-owned task is not a subagent or Quick Chat:
- Use the Codex app
create_threadtool for a task that must appear in the sidebar. - Never substitute
spawn_agent, a background worker, a subagent thread, or a commentary promise. - Load only the exact
list_projectsandcreate_threadtools if they are deferred; do not enumerate a broad tool catalog.
Execute the handoff immediately:
- Write or verify a small disk handoff first when continuity matters. Include the repository/worktree, branch or commit, dirty files, completed outputs, verification, one next action, safe retries, and forbidden repeats.
- Run
list_projectsand select the project matching the exact workspace. For repo-scoped work, callcreate_threadwith:
{
"prompt": "Read , use the specified repository/worktree, and perform only the recorded next action. Preserve completed work and forbidden repeats.",
"target": {
"type": "project",
"projectId": "",
"environment": { "type": "local" }
}
}
Use a worktree environment only when isolation is requested. Set startingState to working-tree only when the user explicitly wants current uncommitted changes, or to branch only for an existing branch/ref. Omit model and thinking unless the user explicitly requests them. Use projectless only for genuinely non-project work.
- After success, report the returned task ID and emit
::created-thread{threadId="..."}; if creation is queued, emit the returnedclientThreadIdform. This receipt is required proof that a sidebar task was actually created. - If
create_threadis unavailable or fails, say that creation did not occur. Do not claim success. Offer the documented fallbackcodex://threads/new?prompt=...&path=...orCtrl+N; note that a deep link pre-fills the composer but does not send automatically.
Recover oversized tasks
Run python /scripts/check_thread_health.py before substantial work after “continue” or a batch request. Resolve ` from this skill's own location; never hard-code a user profile path. Use --thread ID when diagnosing another task. On critical`, do not continue or fork that task. Preserve repository and output files and write a small project handoff plus manifest. When the user explicitly requests a new visible task, follow the sidebar-task procedure above immediately instead of merely describing it.
Automatic review incidents write metadata-only recovery manifests under $CODEX_HOME/watchdog/recovery_manifests (or ~/.codex/watchdog/recovery_manifests when CODEX_HOME is unset). They may identify a rollout path and byte size but never read, rewrite, compact, or delete rollout contents. A manifest is diagnostic evidence, not authorization to interrupt or retry.
Keep watchdog metadata bounded
The daemon retains all active/stalled jobs, prunes disarmed jobs after 30 days or beyond the newest 500, and rotates incidents.jsonl at 5 MiB with three backups. Run cleanup --dry-run to inspect the exact plan; use cleanup --apply only when cleanup is requested. Both operations are restricted to the watchdog-owned runtime directory and must report codex_data_touched: false.
Read [references/protocol.md](references/protocol.md) before arming parallel jobs, handling a stall, or installing the per-user startup entry. Use [references/manifest.schema.json](references/manifest.schema.json) when reading or writing the job manifest. Use [references/recovery-manifest.schema.json](references/recovery-manifest.schema.json) when consuming an automatic review recovery manifest. Read [references/timeout-policy.md](references/timeout-policy.md) before selecting or changing a manual job's no-progress threshold.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: TanChuping
- Source: TanChuping/codex-task-watchdog
- License: MIT
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.