# Claude Code Task

> Launch Claude Code async in background with automatic delivery to Telegram/WhatsApp. Use for coding, refactoring, codebase research, deep research, comprehensive investigations, multi-source reports, file generation, and complex multi-step automations. NOT for quick one-off questions or real-time interactive tasks. Includes strict thread-safe routing + E2E operator validation workflow.

- **Type:** Skill
- **Install:** `agentstack add skill-vsevolodustinov-openclaw-skill-claude-code-openclaw-skill-claude-code`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [VsevolodUstinov](https://agentstack.voostack.com/s/vsevolodustinov)
- **Installs:** 0
- **Category:** [Communication](https://agentstack.voostack.com/c/communication)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [VsevolodUstinov](https://github.com/VsevolodUstinov)
- **Source:** https://github.com/VsevolodUstinov/openclaw-skill-claude-code

## Install

```sh
agentstack add skill-vsevolodustinov-openclaw-skill-claude-code-openclaw-skill-claude-code
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Claude Code Task (Async)

Run Claude Code in background — zero OpenClaw tokens while it works. Results delivered to WhatsApp or Telegram automatically.

## Important: Claude Code = General AI Agent

Claude Code is NOT just a coding tool. It's a full-powered AI agent with web search, file access, and deep reasoning. Use it for ANY complex task:

- **Research** — web search, synthesis, competitive analysis, user experience reports, deep research, evidence gathering, tradeoff studies, sanctions/KYC/AML investigations
- **Coding** — create tools, scripts, APIs, refactor codebases
- **Analysis** — read and analyze files, data, logs, source code
- **Content** — write docs, presentations, reports, summaries
- **Automations** — complex multi-step workflows with file system access

Give it prompts the same way you'd talk to a smart human — natural language, focused on WHAT you need, not HOW to do it.

**NOT for:**
- Quick questions (just answer directly)
- Tasks needing real-time interaction

## Quick Start

## What "run tests" means for this skill (critical)

When user asks things like:
- "прогони все тесты"
- "run tests"
- "проверь что всё работает"

it means **run the full E2E operator validation flow** for `run-task.py` routing + notifications.

It does **NOT** mean `pytest`/`unittest` discovery by default.

Required behavior:
1. Run routing validation first (`--validate-only`).
2. Launch smoke/E2E scenario via `nohup` and file-based prompt.
3. Wait for completion through normal async flow (wake/event), not same-turn blocking.
4. Report PASS/FAIL against E2E criteria (routing, heartbeat, mid-task update, completion delivery).

Use the canonical protocol: **[references/testing-protocol.md](references/testing-protocol.md)** and the section below **Full E2E Test (reference)**.

## Async Boundary Rule (mandatory)

`run-task.py` is asynchronous orchestration.

After a successful `nohup` launch, the correct behavior is:
1. Send a short launch acknowledgment (PID/log/session + a brief human-written summary of what you asked Claude to do), then
2. **Stop this turn immediately**.
3. Continue only when wake/completion event arrives in the same session.

Do **not** keep waiting in the same turn for Claude Code completion.
Do **not** poll and then summarize in the same turn unless user explicitly asked for active live monitoring.

Anti-pattern:
- ❌ Launch `run-task.py` and keep responding as if completion should appear in this turn.

Correct pattern:
- ✅ Launch `run-task.py` → acknowledge launch → stop → wait for wake.

## Launch Confirmation Gate (mandatory)

Never claim "launched" until you have **positive launch proof**.

Required proof checklist (all):
1. `nohup` command returned a PID,
2. process is alive (`ps -p `),
3. run log contains `🔧 Starting Claude Code...` (or equivalent startup marker),
4. routing was validated (`--validate-only`) for Telegram thread runs.

If launch fails with `❌ Invalid routing`:
- resolve via `sessions_list`,
- rerun with explicit `--notify-channel telegram --notify-thread-id  --notify-session-id `,
- re-check proof checklist,
- only then send launch acknowledgment.

Do not send "Claude Code ушёл в работу" before this gate is satisfied.

Important: in your own launch acknowledgment, do **not** restate the full raw prompt.
- Give only a short human summary of the task.
- The run-task launch notification already includes the full prompt/body when needed.
- Avoid duplicating large prompt text in the visible agent reply.

## Pre-launch planning note (mandatory)

Before launching Claude Code, post a short plan in chat:
- how you plan to solve the task,
- what result you expect from this run,
- any clarifying questions/assumptions,
- whether you expect a single-pass result or a staged multi-step approach.

If staged: explicitly say this run is "phase 1" and what signal will decide phase 2.

## Telegram Thread Safety (must-follow)

For Telegram thread runs, `run-task.py` is designed to either route correctly or fail immediately.

### Mandatory step before launch
Resolve the **current runtime session key** first (source of truth), then launch with it.

- Get current key via `sessions_list` (or existing runtime context)
- If key is `agent:main:main:thread:` → use it directly in `--session`
- Never derive `--session` from `chat_id`/sender id heuristics

### Rules
- Use only `--session "agent:main:main:thread:"` for thread tasks
- Never use `agent:main:telegram:user:` for thread tasks
- If routing metadata is inconsistent (thread/session UUID/target mismatch), script exits with `❌ Invalid routing`
- Default mode is `--telegram-routing-mode auto`:
  - allows non-thread Telegram for setups without thread sessions
  - blocks ambiguous user-scope session key (`agent:main:telegram:user:`) unless explicitly forced
  - blocks non-thread launch if a recent thread session exists for same target (likely misroute)
- Force strict thread-only behavior with `--telegram-routing-mode thread-only`
- Force non-thread behavior with `--telegram-routing-mode allow-non-thread` or `--allow-main-telegram`

This is intentional: **abort fast > silent misroute**.

⚠️ For background `claude-code-task` launches, **do not set `exec.timeout`**; use only `run-task.py --timeout`, otherwise OpenClaw may SIGTERM the whole process group early.

⚠️ **NEVER put the task text directly in the shell command** — quotes, special characters, and newlines WILL break argument parsing. Always save the prompt to a file first, then use `$(cat file)`.

### WhatsApp

```bash
# Step 1: Save prompt to a temp file
write /tmp/cc-prompt.txt with your task text

# Step 2: Launch with $(cat ...)
nohup python3 {baseDir}/run-task.py \
  --task "$(cat /tmp/cc-prompt.txt)" \
  --project ~/projects/my-project \
  --session "agent:main:whatsapp:group:" \
  --timeout 900 \
  > /tmp/cc-run.log 2>&1 &
```

The `--session` key (e.g. `agent:main:whatsapp:group:120363425246977860@g.us`) is used to auto-detect the WhatsApp target.

### Telegram (thread-safe default)

```bash
# ALWAYS use the current thread session key from context:
# agent:main:main:thread:
nohup python3 {baseDir}/run-task.py \
  --task "$(cat /tmp/cc-prompt.txt)" \
  --project ~/projects/my-project \
  --session "agent:main:main:thread:" \
  --timeout 900 \
  > /tmp/cc-run.log 2>&1 &
```

> Do **NOT** use `agent:main:telegram:user:` for thread tests/runs.
> That routes to main chat scope and can drift from the source thread.

### Telegram Threaded Mode (1:1 DM with threads)

When Marvin is used in Telegram Threaded Mode, each thread has its own session key like `agent:main:main:thread:369520`.

**Fail-safe routing (NEW):** `run-task.py` now enforces strict thread routing.
- If `--session` contains `:thread:`, the script **refuses to start** unless Telegram target + thread session UUID are resolved.
- It auto-resolves missing values from `sessions_list` when possible.
- If the session is inactive and not returned by API, it falls back to local session files: `~/.openclaw/agents/main/sessions/*-topic-.jsonl`.
- If provided `--notify-session-id` mismatches the session key, it exits with error.
- Result: misrouted launches/heartbeats to main chat are blocked before Claude starts.

Use `--notify-session-id` to wake the exact thread session:

```bash
nohup python3 {baseDir}/run-task.py \
  --task "$(cat /tmp/cc-prompt.txt)" \
  --project ~/projects/my-project \
  --session "agent:main:main:thread:369520" \
  --timeout 900 \
  > /tmp/cc-run.log 2>&1 &
```

All 5 notification types route to the DM thread when `--session` key contains `:thread:` ✅

- `--notify-session-id` — optional override. Usually auto-resolved from session metadata/files.
- `--notify-thread-id` — optional override. Usually auto-extracted from `--session`.
- `--reply-to-message-id` — optional debug field; avoid for DM thread routing.
- `--validate-only` — resolve routing and exit (no Claude run). Use this to verify thread launch args safely.

- `--notify-channel` — optional channel hint (`telegram`/`whatsapp`); target is always auto-resolved from session metadata
- `--timeout` — max runtime in seconds (default: 7200 = 2 hours)
- built-in smart stall observer (shadow mode): sends "would terminate" warnings on likely hangs
- built-in post-result tail-hang detector (short grace after result event)
- `--trace-live` — emit live technical trace markers into the same chat/thread (debug mode)
- Always redirect stdout/stderr to a log file

### Why file-based prompts?
Research/complex prompts contain single quotes, double quotes, markdown, backticks — any of these break shell argument parsing. Saving to a file and reading with `$(cat ...)` avoids all quoting issues.

## Channel Detection

The `detect_channel()` function determines where to send notifications:

1. **Deterministic auto-resolve** — target is resolved from session metadata/session key (no manual target flag)
2. **WhatsApp auto-detect** — if the session key contains `@g.us` (WhatsApp group JID), WhatsApp is used
3. **Fail fast on unresolved Telegram target** — script exits with `❌ Invalid routing` instead of silent misroute

```python
def detect_channel(session_key):
    if NOTIFY_CHANNEL_OVERRIDE and NOTIFY_TARGET_OVERRIDE:
        return NOTIFY_CHANNEL_OVERRIDE, NOTIFY_TARGET_OVERRIDE
    jid = extract_group_jid(session_key)
    if jid:
        return "whatsapp", jid
    return None, None
```

## How It Works

```
┌─────────────┐     nohup      ┌──────────────┐
│    Agent     │ ──────────────▶│  run-task.py  │
│  (OpenClaw)  │                │  (detached)   │
└─────────────┘                └──────┬───────┘
                                      │
                                      ▼
                               ┌──────────────┐
                               │  Claude Code  │  ← runs on Max subscription ($0 API)
                               │  (-p mode)    │
                               └──────┬───────┘
                                      │
                          ┌───────────┼───────────┐
                          ▼           ▼           ▼
                    Every 60s    On complete   On error/timeout
                    ┌────────┐  ┌──────────┐  ┌──────────────┐
                    │ ⏳ ping │  │ ✅ result │  │ ❌/⏰/💥 error│
                    │ silent │  │ channel  │  │   channel    │
                    └────────┘  └──────────┘  └──────────────┘
```

### WhatsApp notification flow:
1. **Heartbeat pings** (every 60s) → WhatsApp direct (informational, no agent wake)
2. **Final result** → WhatsApp direct (human sees immediately) + `sessions_send` (agent wakes up)
3. **Agent receives** completion payload via sessions_send → processes it → sends summary via `message(send)` to WhatsApp group
4. Human sees both: raw result + agent's analysis/next steps

### Wake continuation behavior
Wake payload frames continuation as the **same ongoing assistant conversation** (same agent identity, same session, same history) after Claude Code replies to the previous launch.

Continuation flow:
- react briefly to Claude result
- evaluate goal completion (gap analysis)
- if gaps remain and there is no real blocker requiring user input or external waiting: explain the next fix, then launch the next Claude run in the same turn
- keep repeating this wake → visible decision → relaunch pattern for as many iterations as needed until the original goal is complete or a genuine blocker is hit
- if complete: report final outcome and stop

### Deterministic wake guard (anti-duplicate)
- Each run now carries `run_id` and `wake_id` in wake payload.
- `run-task.py` keeps per-project state in `/tmp/cc-orchestrator-state-.json`.
- Duplicate/stale wake dispatches (same output or same wake_id) are skipped before wake delivery.
- In debug mode (`--trace-live`), skipped wakes are announced as `[TRACE][TECH][TELEGRAM][WAKE][SKIP]`.

### No silent launch policy (always-on)
- Silent launch is forbidden (not only in debug mode).
- On wake, agent must first post a visible decision turn:
  - `[TRACE][AGENT][WAKE_RECEIVED] ...`
  - `[TRACE][AGENT][DECISION] continue|stop ...`
- If the goal is still not complete and there is no real blocker, the next Claude iteration is mandatory.
- Only after that visible decision may the next Claude iteration be launched.
### Telegram notification flow (DM Threaded Mode — full pipeline):
1. 🚀 **Launch notification** → thread ✅ (silent; HTML; `` for prompt; via `send_telegram_direct`; includes `Resume: `)
2. ⏳ **Heartbeat** (every 60s) → thread ✅ (silent; plain text; via `send_telegram_direct`)
3. 📡 **Claude Code mid-task updates** → thread ✅ (on-disk Python script `/tmp/cc-notify-{pid}.py`; CC calls file; prefix `"📡 🟢 CC: "` auto-added)
4. ✅/❌/⏰/💥 **Result notification** → thread ✅ (HTML; `` for result; via `send_telegram_direct`)
5. 🤖 **Agent continuation reply** → delivered to chat via `openclaw agent --deliver` ✅ (same session continuation is visible to user)

**`send_telegram_direct()`** is the core mechanism for all thread-targeted notifications from external scripts. It calls `api.telegram.org` directly with `message_thread_id` — bypasses the OpenClaw message tool entirely (which cannot route to DM threads from outside a session context).

**Fallback** — if agent wake fails (session locked/busy): `already_sent=True` is set after the direct send, so no duplicate is sent.

### Key detail: Telegram vs WhatsApp delivery

**WhatsApp:** Raw result sent directly (human sees it immediately) + `sessions_send` wakes agent for analysis.

**Telegram:** Result sent via `send_telegram_direct` → then agent is woken via `openclaw agent --session-id --deliver` so the continuation turn is visible in chat by default. This is the intended “same agent, same conversation” behavior after Claude completion.

**Why not `sessions_send` for Telegram?** `sessions_send` is blocked in the HTTP `/tools/invoke` deny list by architectural design. The `openclaw agent` CLI bypasses this limitation.

## Reliability Features

### Timeout / stall protection
- `--timeout 7200` → hard max runtime (SIGTERM → wait 10s → SIGKILL)
- built-in smart stall observer (shadow mode): warns when run looks kill-worthy but does not terminate
- built-in post-result tail-hang detector: warns when process stays alive after result event grace
- Timeout/stall notification sent to channel with tool call count and last activity
- Partial output saved to file

### Crash safety
- `try/except` wraps entire main → crash notification always sent
- Both channel notification and agent wake attempted on any failure

### PID tracking
- PID file written to `skills/claude-code-task/pids/`
- Stale PIDs cleaned on startup
- Can check running tasks: `ls skills/claude-code-task/pids/`

### Silent mode (Telegram only)
Telegram supports silent notifications (no sound).

Current policy: **all Claude Code notifications are silent** in Telegram:
- Heartbeat pings → `silent=True`
- Launch notifications → `silent=True`
- Mid-task updates (`📡 🟢 CC`) → `silent=True`
- Final results → `silent=True`
- Wake-summary instruction requests `silent=True`

WhatsApp does NOT support silent mode — the flag is ignored for WhatsApp.

### Telegram DM Threads vs Forum Groups

Telegram has two distinct thread models. The key difference for run-task.py is how to route messages to the thread.

**The core problem with external scripts:**
- The OpenClaw `message` tool's `threadId` parameter is **Discord-specific** — ignored for Telegram
- Target format `"chatId:topic:threadId"` is rejected by the message tool's target resolver
- Session auto-routing (`currentThreadTs`) works ONLY inside active sessions — external scripts have no session context
- **Solution:** `send_telegram_direct()` bypasses the message tool entirely; calls `api.telegram.org` directly with `message_thread_id`

**DM Threaded Mode** (bot-user private chat with threads):
- All notifications use `send_telegram_direct(chat_id, text, thread_id=..., parse_mode=...)` ✅
- `thread_id` auto-extracted

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [VsevolodUstinov](https://github.com/VsevolodUstinov)
- **Source:** [VsevolodUstinov/openclaw-skill-claude-code](https://github.com/VsevolodUstinov/openclaw-skill-claude-code)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-vsevolodustinov-openclaw-skill-claude-code-openclaw-skill-claude-code
- Seller: https://agentstack.voostack.com/s/vsevolodustinov
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
