Install
$ agentstack add skill-keugenek-shark-shark ✓ 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
🦈 The Shark Pattern
> STOP — check ARGUMENTS first. Look at the ARGUMENTS line at the bottom of this file. If the first word matches a sub-command below, execute ONLY that sub-command and stop. Do NOT apply the Shark Pattern. > > | First word | Action | > |------------|--------| > | loop | Run the shell script. Strip "loop" from args to get the task. Run: bash "/shark.sh" "" (where ` is the "Base directory for this skill" shown above). Pass --max-loops N as SHARKMAXLOOPS=N env var, --timeout S as SHARKLOOPTIMEOUT=S. Defaults: 50 loops, 25s timeout. **Do not apply the Shark Pattern manually.** | > | status | Read /shark-exec/state/pending.json, check .shark-done and SHARKLOG.md. Report state or "No active shark jobs." | > | clean | Remove .shark-done, SHARKLOG.md, shark-exec/state/pending.json. Report what was cleaned. | > | autotune | Read /state/timings.jsonl, compute stats, recommend settings. | > | help` | List sub-commands and summarize the Shark Pattern briefly. | > > If ARGUMENTS does not start with a sub-command above, treat the full text as a task and apply the Shark Pattern below.
> A shark that stops swimming dies. An agent that waits for tools wastes compute.
Works with: Claude Code · Codex · Gemini CLI · Cursor · Windsurf · Aider · OpenClaw · any LLM agent
When to Use This Skill
Trigger this skill when the user says:
- "use the shark pattern"
- "non-blocking agent"
- "never wait for tools"
- "spawn background workers"
- "parallel subagents"
- "keep the main agent moving"
- or when you notice you're about to block on a slow tool (web fetch, build, test run, API call)
The Rule
Every LLM turn must complete in under 30 seconds.
If any operation would take longer:
- Spawn a remora (
sessions_spawnwithmode: "run") - Continue reasoning immediately
- Incorporate remora results when they arrive
You are never in I/O wait. You are always reasoning about something.
Lifecycle
┌─────────────┐
│ DECOMPOSE │ Break task into N independent subtasks
└──────┬──────┘
│ spawn N remoras (+ 1 pilot fish when first completes early)
▼
┌─────────────┐
│ SPAWN │ sessions_spawn × N, all parallel, record session IDs
└──────┬──────┘
│ main agent keeps reasoning (never waits)
▼
┌─────────────┐ timeout/crash
│ MONITOR │ ──────────────────► MARK ⏱/❌ (partial still useful)
└──────┬──────┘
│ all done OR deadline hit
▼
┌─────────────┐
│ AGGREGATE │ Collect results, note failures, merge pilot fish draft
└──────┬──────┘
│
▼
┌─────────────┐
│ REPORT │ Single coherent response with failure count noted
└─────────────┘
No nested remoras. If a remora is running, it executes inline — remoras cannot spawn their own remoras. Only the main shark spawns.
The Pattern
Bad (Ralph-style blocking):
think → call slow tool → WAIT 60s → think → call slow tool → WAIT 45s → ...
Good (Shark-style non-blocking):
think → spawn remora(slow tool) → think about something else
→ spawn remora(another tool) → synthesize partial results
→ receive remora result → incorporate → swim on
Implementation
When applying the Shark Pattern, structure your work like this:
1. Identify blocking operations
Before calling any tool, ask: "Will this take more than 20-30 seconds?"
Slow tools (always spawn — these are examples, not things this skill executes):
- Web searches / page fetches
- Remote commands
- Build / test / CI runs
- File system scans over large directories
- API calls with unknown latency
- LLM inference calls (coding agents)
Fast tools (run inline, never spawn):
- Reading local files
- Simple calculations
- String manipulation
- Memory lookups
2. Spawn remoras
sessions_spawn({
task: "Do the slow thing and return the result",
mode: "run",
runtime: "subagent",
streamTo: "parent" // optional: stream output back
})
Spawn multiple remoras in parallel when possible — don't serialize unless there's a data dependency.
3. Keep the main fin moving
After spawning, immediately continue:
- Plan the next step
- Work on a different part of the task
- Summarize what you know so far
- Prepare to incorporate results
4. Incorporate results
When remora results arrive, weave them in and continue. Never re-do work a remora already completed.
If your runtime keeps subagents alive after completion, close them once you've incorporated their result. In Codex that means: wait for the remora, use its output, then close_agent(id) unless you intentionally plan to reuse that same agent.
Timing Budget
| Operation | Budget | Action | |-----------|--------|--------| | File read | 🦈 Shark mode — spawning [N] remoras for [tasks], continuing...
Progress bar (chat-friendly, Unicode only — no images needed)
Use this format after each remora or pilot fish completes. Works in Telegram, Discord, Signal, iMessage — anywhere.
🦈 3 remoras · 1 pilot fish
◉ [A] task name here ████████████ ✅ 9s
◉ [B] task name here ████████████ ✅ 33s
○ [C] task name here ░░░░░░░░░░░░ pending
◈ [P] Pilot fish ██████░░░░░░ ~14s left
↳ continuing...
Symbols:
◉= remora (completed)○= remora (pending)⊙= remora (running)◈= pilot fish (time-bounded)████████████= done bar (12 blocks)██████░░░░░░= partial (filled = elapsed / total budget)░░░░░░░░░░░░= not started
Progress fill: filled = round(elapsed / timeout * 12) blocks of █, remainder ░
Only post an update when something changes (remora completes or pilot fish starts/ends). Don't spam — one update per event.
Final synthesis
After all remoras done: > 🦈 All fins in — synthesising [N] results + pilot draft
Then deliver the report.
The Pilot Fish Sub-Pattern
> Pilot fish swim alongside sharks doing prep work. When you have idle time, use it.
When one remora returns early and others are still running:
- Spawn a pilot fish — a time-bounded analysis sub-agent
- Give it only the partial results so far + a hard timeout equal to the estimated remaining wait
- Let it pre-validate, pre-analyse, find patterns, draft conclusions
- Kill it (or it self-terminates) when the last primary remora completes
- Incorporate whatever the pilot fish produced into the final synthesis
remora A ──────► result (early)
remora B ────────────────────────────► result
remora C ──────────────────────────────────► result
main: spawn A, B, C
A done → spawn pilot-fish(A's result, timeout=est_remaining)
pilot-fish: pre-analyse A, draft partial report, validate data...
B done → pilot-fish still running, feed B's result in (or kill+reuse)
C done → kill pilot-fish, synthesise A+B+C+pilot-fish draft
Pilot Fish Rules
- Always time-bounded — pass
runTimeoutSecondsequal to estimated remaining wait - Never blocks — spawned async, main agent continues
- Opportunistic — if it finishes early, bonus; if killed mid-run, partial output is still useful
- One at a time — don't stack pilot fish on pilot fish
- Task: pre-validate data, find gaps, draft structure, flag anomalies, prepare questions
Example
// remoras A (fast) and B (slow) both spawned
// A finishes in 10s, B will take another 30s
// Spawn pilot fish with 25s budget:
sessions_spawn({
task: "Pre-analyse these results from remora A.
Validate the data, note any gaps, draft the structure
of the final report. Stop after 25 seconds.",
runTimeoutSeconds: 25,
mode: "run"
})
// Main agent continues doing other work
// When B finishes → kill pilot fish → synthesise A + B + pilot draft
Decision Tree — When to Spawn
Before every tool call, ask: "Will this take more than 10 seconds?"
Estimated time 50% remoras failed
- Degrade gracefully — fall back to sequential for remaining work
- Note in report: "⚠️ degraded mode — N/M remoras failed"
### All remoras failed
- Fall back to sequential execution for the most critical task only
- Do not spawn another full fleet — you're likely hitting a systemic issue
### Forgetting to spawn the pilot fish (most common mistake)
- You finished a fast inline task, a remora is still running, and you just... wait
- **Symptom:** main agent idle, no pilot fish, time wasted
- **Fix:** always ask after any remora completes early — "what can I pre-draft right now?"
- Even if you have nothing obvious, draft the output structure, prepare questions, or outline the synthesis
### Pilot fish killed mid-run
- Normal and expected — whatever it produced is still useful
- Incorporate partial pilot fish output into synthesis
- Don't wait for it or re-spawn it
---
## Terminology
- **remora** = a `sessions_spawn` call with `mode: "run"`, `runtime: "subagent"`, and `runTimeoutSeconds` set. A remora is specifically a *timed* sub-agent — untimed subagents are not remoras.
- **Pilot fish** = a remora spawned *after* another remora completes, with a short timeout sized to the estimated remaining wait. Purpose: pre-analysis only, never primary work.
- **Fleet** = the full set of remoras spawned for one task
- **Fin moving** = the main agent is doing useful work (not waiting)
- **No nested remoras** = remoras always execute inline — only the main shark spawns
### `runTimeoutSeconds` — confirmed real
Verified against OpenClaw source: `runTimeoutSeconds: z.number().int().min(0).optional()` — maps to the subagent wait timeout. Use it. Hard-kills the sub-agent process after N seconds, partial output returned.
---
## Pilot Fish Sizing Formula
pilotFishTimeout = min(estimatedRemaining * 0.8, 25)
- `estimatedRemaining` = how long you think the slowest remaining remora will take
- Cap at 25s so pilot fish always finishes before the main synthesis turn
- If you don't know: use 20s as default
Example: slowest remaining remora estimated at 30s → pilot fish timeout = min(24, 25) = 24s
---
## Hard Limits
- **Never** use `yieldMs` > 30000 in exec calls — this holds the main turn hostage
- **Never** `process(action=poll, timeout > 20000)` in the main session — same reason
- **Never** add `sleep` or wait loops in the main thread
- **Always** set `runTimeoutSeconds` on remoras — unbound sub-agents are not sharks
- **Always** clean up completed remoras — if your runtime requires explicit teardown, do it right after incorporating the result
- **Max 8** concurrent remoras — beyond this, context overhead exceeds the gain
- **Never stack pilot fish** — one at a time, no pilot fish spawning pilot fish
- **Spawn tasks ≤ 3 sentences** — longer task descriptions need decomposition first
## Enforcing the 30-Second Timeout
The 30s cap isn't just a guideline — here's how to actually enforce it per runtime.
### OpenClaw subagents
```js
sessions_spawn({
task: "...",
mode: "run",
runtime: "subagent",
runTimeoutSeconds: 30 // hard kill after 30s — agent gets SIGTERM
})
runTimeoutSeconds is enforced by the OpenClaw runtime — the sub-agent process is killed if it exceeds it. Partial output is still returned.
exec calls (shell, scripts)
exec({
command: "some-slow-command",
timeout: 30, // hard kill in seconds
background: true, // don't block the main agent turn
yieldMs: 500 // poll back quickly to check
})
timeout kills the process. background: true means the main agent doesn't wait — it gets a session handle and can check back with process(poll).
Gemini CLI via exec
timeout 30 gemini -p "task here"
# or on Windows:
Start-Process gemini -ArgumentList '-p "task"' -Wait -Timeout 30
Wrap the CLI invocation with OS-level timeout / Start-Process -Timeout.
Pilot fish — always use runTimeoutSeconds
sessions_spawn({
task: "pre-analyse partial results, draft structure, flag gaps",
mode: "run",
runTimeoutSeconds: estimatedRemainingMs / 1000, // die before the last remora
})
Set it to slightly less than your estimated remaining wait — so the pilot fish always finishes before you need to synthesise.
What happens when timeout fires
- Sub-agent/process is killed
- Whatever output was produced so far is returned
- Main agent treats it as a partial result — still useful for synthesis
- Log:
[timeout]in the progress bar instead of✅
⊙ [A] slow task ████████████ ⏱ 30s [timeout — partial result]
The LLM turn itself
You can't hard-kill an LLM mid-turn, but you can:
- Keep prompts tight — don't ask for exhaustive analysis in one turn
- Use
thinking: "none"for fast sub-tasks that don't need deep reasoning - Break large tasks into smaller shark-able chunks upfront
Rule of thumb: if a task description is >3 sentences, it probably needs to be split into remoras.
Compatibility — Claude, Codex, Gemini CLI
The Shark Pattern is runtime-agnostic. remoras can be any agent type.
OpenClaw (Claude / Sonnet / Opus)
sessions_spawn({
task: "...",
mode: "run",
runtime: "subagent",
runTimeoutSeconds: 30 // hard cap for pilot fish
})
Codex
sessions_spawn({
task: "...",
runtime: "acp",
agentId: "codex",
mode: "run",
runTimeoutSeconds: 30
})
Codex-specific lifecycle:
- Spawn with
spawn_agent(...)or the runtime-equivalent remora launcher - Check completion with
wait_agent(...) - If you want to reuse the same remora, send more work with
send_input(...) - Otherwise, once the remora has completed and you've incorporated its result, call
close_agent(id)so the agent does not linger in the session
Gemini CLI
Gemini CLI is a local process — spawn via exec with a timeout:
exec({
command: "gemini -p \"task description here\"",
timeout: 30, // hard cap in seconds
background: true, // don't block main agent
yieldMs: 500 // check back quickly
})
For Gemini sub-tasks, use exec with timeout + background: true rather than sessions_spawn. Treat the process handle the same way — continue working, collect output when it lands.
Mixed fleets
You can mix runtimes in the same shark run:
spawn remora A → Codex (coding task)
spawn remora B → Gemini (web search / analysis)
spawn remora C → Claude subagent (reasoning)
spawn pilot fish → Claude subagent (pre-analysis, time-bounded)
Which to use when
| Task type | Best runtime | |-----------|-------------| | Code generation / editing | Codex | | Web search / summarise | Gemini CLI | | Multi-step reasoning | Claude subagent | | File ops / shell | exec (background) | | Pre-analysis / drafting | Claude subagent (pilot fish) |
shark-exec Sub-Skill
For slow shell commands (>5s), use the shark-exec companion skill:
- Located at
shark-exec/SKILL.mdin this repo - Wraps any
execcall in background + cron poller - Guarantees main turn completes in
The loop detects this file and exits cleanly.
## Commands
When the user invokes these commands, follow the instructions for each.
### `/shark `
Apply the Shark Pattern to the given task. Decompose, spawn remoras for slow ops, keep the main fin moving. Follow all rules in this SKILL.md.
### `/shark-loop [--max-loops N] [--timeout S]`
Run the external shark loop enforcer.
On Linux/Mac:
```sh
SHARK_MAX_LOOPS= SHARK_LOOP_TIMEOUT= bash "/shark.sh" ""
On Windows (PowerShell):
$env:SHARK_MAX_LOOPS = ""
$env:SHARK_LOOP_TIMEOUT = ""
& "\shark.ps1" ""
Defaults: --max-loops 50, --timeout 25.
/shark-status
Check current shark state:
- Read
/shark-exec/state/pending.json— report active background jobs (label, command, elapsed time, whether overdue past maxSeconds) - If
.shark-doneexists, show its contents - If
SHARK_LOG.mdexists, show the last 10 lines - If nothing exists, report "No active shark jobs."
/shark-clean
Remove shark state files: `.shark-
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: keugenek
- Source: keugenek/shark
- License: Apache-2.0
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.