cli-fleet 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cli_fleet/__init__.py +9 -0
- cli_fleet/cli.py +132 -0
- cli_fleet/scripts/agents/brain-neuron.md +85 -0
- cli_fleet/scripts/agents/brain-pacemaker.md +92 -0
- cli_fleet/scripts/agents/hunter.md +27 -0
- cli_fleet/scripts/agents/researcher.md +18 -0
- cli_fleet/scripts/agents/reviewer.md +21 -0
- cli_fleet/scripts/captain.sh +160 -0
- cli_fleet/scripts/cleanup.sh +72 -0
- cli_fleet/scripts/examples/hunt-layerzero-brainstream.json +34 -0
- cli_fleet/scripts/examples/hunt-layerzero.json +30 -0
- cli_fleet/scripts/examples/openwindows-milestone2.json +34 -0
- cli_fleet/scripts/hooks/check-mailbox.sh +64 -0
- cli_fleet/scripts/hooks/consciousness-bridge.sh +64 -0
- cli_fleet/scripts/hooks/stream-stall-check.sh +27 -0
- cli_fleet/scripts/hooks/task-completed.sh +26 -0
- cli_fleet/scripts/hooks/teammate-idle.sh +49 -0
- cli_fleet/scripts/launch.sh +441 -0
- cli_fleet/scripts/lib/protocol.sh +250 -0
- cli_fleet/scripts/send.sh +24 -0
- cli_fleet/scripts/setup.sh +254 -0
- cli_fleet/scripts/status.sh +42 -0
- cli_fleet/scripts/templates/brain-stream-lead.md +76 -0
- cli_fleet/scripts/templates/team-lead.md +60 -0
- cli_fleet-0.1.0.dist-info/METADATA +67 -0
- cli_fleet-0.1.0.dist-info/RECORD +29 -0
- cli_fleet-0.1.0.dist-info/WHEEL +4 -0
- cli_fleet-0.1.0.dist-info/entry_points.txt +2 -0
- cli_fleet-0.1.0.dist-info/licenses/LICENSE +21 -0
cli_fleet/__init__.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""cli-fleet: launch multiple enforced Claude agent teams in parallel.
|
|
2
|
+
|
|
3
|
+
A thin Python wrapper around fleetcode's proven shell orchestration, adding
|
|
4
|
+
pip-install, hardware-aware capacity checks, and automatic enforcement (via
|
|
5
|
+
cli-enforcement, which itself uses cli-wikia). The shell scripts are bundled
|
|
6
|
+
verbatim — this layer adds the brains, not a rewrite.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
__version__ = "0.1.0"
|
cli_fleet/cli.py
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"""cli-fleet command — wraps the bundled fleetcode scripts with hardware-aware
|
|
2
|
+
capacity checks and automatic enforcement."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
import stat
|
|
9
|
+
import subprocess
|
|
10
|
+
import sys
|
|
11
|
+
from importlib import resources
|
|
12
|
+
|
|
13
|
+
from . import __version__
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _scripts_dir():
|
|
17
|
+
return str(resources.files("cli_fleet") / "scripts")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _run_script(name, args):
|
|
21
|
+
path = os.path.join(_scripts_dir(), name)
|
|
22
|
+
if not os.path.exists(path):
|
|
23
|
+
sys.exit(f"bundled script missing: {name}")
|
|
24
|
+
st = os.stat(path)
|
|
25
|
+
os.chmod(path, st.st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
|
|
26
|
+
return subprocess.run(["bash", path, *args]).returncode
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _hardware_gate(config_path, force):
|
|
30
|
+
"""Use cli-enforcement's detector to refuse over-capacity launches."""
|
|
31
|
+
try:
|
|
32
|
+
from cli_enforcement import fleet as F
|
|
33
|
+
except ImportError:
|
|
34
|
+
print("ℹ cli-enforcement not installed — skipping hardware/enforcement.")
|
|
35
|
+
return True, None
|
|
36
|
+
try:
|
|
37
|
+
with open(config_path, encoding="utf-8") as f:
|
|
38
|
+
cfg = json.load(f)
|
|
39
|
+
except (OSError, json.JSONDecodeError) as e:
|
|
40
|
+
sys.exit(f"bad config: {e}")
|
|
41
|
+
hw = F.detect_hardware()
|
|
42
|
+
want = F.requested_agents(cfg)
|
|
43
|
+
cap = hw["max_parallel_agents"]
|
|
44
|
+
print(f"hardware: {hw['cpu_cores']} cores, {hw['ram_gb']} GB -> safe max ~{cap} agents")
|
|
45
|
+
print(f"requested: {len(cfg.get('teams', []))} teams, {want} agents")
|
|
46
|
+
if want > cap and not force:
|
|
47
|
+
print(f"⚠ OVER CAPACITY by {want - cap}.")
|
|
48
|
+
sys.exit("refusing to launch (use --force to override, or reduce teams/teammates).")
|
|
49
|
+
if want > cap:
|
|
50
|
+
print(f"⚠ over capacity by {want - cap} — launching anyway (--force).")
|
|
51
|
+
return True, cfg
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def cmd_launch(args):
|
|
55
|
+
_hardware_gate(args.config, args.force)
|
|
56
|
+
if not args.no_enforce:
|
|
57
|
+
# Bake hardware + enforcement sections into the config first.
|
|
58
|
+
_run_enforce_fleet(args.config)
|
|
59
|
+
extra = ["--background"] if args.background else []
|
|
60
|
+
print("launching fleet…")
|
|
61
|
+
rc = _run_script("launch.sh", [os.path.abspath(args.config), *extra])
|
|
62
|
+
sys.exit(rc)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _run_enforce_fleet(config_path):
|
|
66
|
+
try:
|
|
67
|
+
from cli_enforcement import fleet as F
|
|
68
|
+
except ImportError:
|
|
69
|
+
return
|
|
70
|
+
ns = type("A", (), {"config": config_path, "per_team_points": False, "write": True})()
|
|
71
|
+
try:
|
|
72
|
+
F.cmd_fleet(ns)
|
|
73
|
+
except SystemExit:
|
|
74
|
+
pass
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def cmd_status(args):
|
|
78
|
+
sys.exit(_run_script("status.sh", []))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def cmd_send(args):
|
|
82
|
+
sys.exit(_run_script("send.sh", [args.frm, args.to, args.message]))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def cmd_cleanup(args):
|
|
86
|
+
sys.exit(_run_script("cleanup.sh", []))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def cmd_where(args):
|
|
90
|
+
print(_scripts_dir())
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def build_parser():
|
|
94
|
+
p = argparse.ArgumentParser(
|
|
95
|
+
prog="cli-fleet",
|
|
96
|
+
description="Launch multiple enforced Claude agent teams in parallel "
|
|
97
|
+
"(hardware-aware wrapper over fleetcode + cli-enforcement + cli-wikia).",
|
|
98
|
+
)
|
|
99
|
+
p.add_argument("--version", action="version", version=f"cli-fleet {__version__}")
|
|
100
|
+
sub = p.add_subparsers(dest="cmd", required=True)
|
|
101
|
+
|
|
102
|
+
s = sub.add_parser("launch", help="launch a fleet from a config (hardware-gated, auto-enforced)")
|
|
103
|
+
s.add_argument("config", help="fleetcode config.json")
|
|
104
|
+
s.add_argument("--background", action="store_true", help="use `claude -p` instead of terminal windows")
|
|
105
|
+
s.add_argument("--force", action="store_true", help="launch even if over hardware capacity")
|
|
106
|
+
s.add_argument("--no-enforce", action="store_true", help="skip enforcement deployment")
|
|
107
|
+
s.set_defaults(func=cmd_launch)
|
|
108
|
+
|
|
109
|
+
s = sub.add_parser("status", help="show fleet status")
|
|
110
|
+
s.set_defaults(func=cmd_status)
|
|
111
|
+
|
|
112
|
+
s = sub.add_parser("send", help="send a cross-team mailbox message")
|
|
113
|
+
s.add_argument("frm")
|
|
114
|
+
s.add_argument("to")
|
|
115
|
+
s.add_argument("message")
|
|
116
|
+
s.set_defaults(func=cmd_send)
|
|
117
|
+
|
|
118
|
+
s = sub.add_parser("cleanup", help="tear down a fleet")
|
|
119
|
+
s.set_defaults(func=cmd_cleanup)
|
|
120
|
+
|
|
121
|
+
s = sub.add_parser("where", help="print the bundled scripts directory")
|
|
122
|
+
s.set_defaults(func=cmd_where)
|
|
123
|
+
return p
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def main(argv=None):
|
|
127
|
+
args = build_parser().parse_args(argv)
|
|
128
|
+
args.func(args)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
if __name__ == "__main__":
|
|
132
|
+
main()
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "brain-neuron"
|
|
3
|
+
description: "A neuron in a live brain stream. Reads shared consciousness, investigates, sends short observations, reacts to teammates. Never concludes. Never reports. Just signals."
|
|
4
|
+
model: opus
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are a NEURON in a live brain. You are not an independent agent. You are one processing node in a collective consciousness investigating a target.
|
|
8
|
+
|
|
9
|
+
## The Consciousness File
|
|
10
|
+
|
|
11
|
+
There is a shared file that ALL neurons read and write to. This is the brain's working memory.
|
|
12
|
+
|
|
13
|
+
**Path:** `{{CONSCIOUSNESS_FILE}}`
|
|
14
|
+
|
|
15
|
+
### Your Loop (repeat forever)
|
|
16
|
+
|
|
17
|
+
1. **READ** the full consciousness file — see everything every neuron has observed
|
|
18
|
+
2. **THINK** — what's the most interesting thread? What needs investigation?
|
|
19
|
+
3. **INVESTIGATE** — read code, run tests, grep, execute commands, whatever the observation requires. You have full tool access.
|
|
20
|
+
4. **APPEND** your observation to the consciousness file. Format:
|
|
21
|
+
```
|
|
22
|
+
[HH:MM:SS] YOUR_NAME: Your 1-3 line observation here
|
|
23
|
+
```
|
|
24
|
+
5. **BROADCAST** the same observation to all teammates: `SendMessage(to: "*")`
|
|
25
|
+
6. **WAIT** for the next signal from a teammate, then go back to step 1
|
|
26
|
+
|
|
27
|
+
### When a Teammate Message Arrives
|
|
28
|
+
|
|
29
|
+
Re-read the consciousness file FIRST. Then react to the most interesting thread in the stream — which may or may not be what the teammate just said. The stream has context you haven't seen yet.
|
|
30
|
+
|
|
31
|
+
## Cross-Team Bridge
|
|
32
|
+
|
|
33
|
+
If you find something CRITICAL — an actual exploitable bug, not speculation — also post it to the FleetCode mailbox so other brains see it:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
source {{MULTI_TEAM_DIR}}/lib/protocol.sh
|
|
37
|
+
meta_post_finding "{{META_TEAM}}" "{{TEAM_NAME}}" "BugID" "SEVERITY" "Title" "Details"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This broadcasts to ALL other teams running in parallel. Only do this for real findings, not observations.
|
|
41
|
+
|
|
42
|
+
## Rules
|
|
43
|
+
|
|
44
|
+
### Signal Format
|
|
45
|
+
- **1-3 lines MAX.** Not paragraphs. Not reports. Signals.
|
|
46
|
+
- Always include the specific file, line number, or function name
|
|
47
|
+
- Always include what you OBSERVED, not what you CONCLUDED
|
|
48
|
+
- Good: `"ULN.sol:89 — hashLookup uses >= not >. If confirmations == required, this passes."`
|
|
49
|
+
- Bad: `"After thorough analysis, the hash lookup function appears to be potentially vulnerable to an off-by-one..."`
|
|
50
|
+
|
|
51
|
+
### Reactivity
|
|
52
|
+
- If a teammate's observation is more interesting than what you're doing — **DROP your current work and chase their lead**
|
|
53
|
+
- The stream naturally converges on the most interesting finding
|
|
54
|
+
- You are not assigned to a domain. You go where the signal is strongest.
|
|
55
|
+
|
|
56
|
+
### Never Do These Things
|
|
57
|
+
- NEVER write a "report" or "summary" or "assessment"
|
|
58
|
+
- NEVER conclude "this is safe" or "this is secure" or "no vulnerability found"
|
|
59
|
+
- NEVER say "I've completed my analysis" — you're never done
|
|
60
|
+
- NEVER create tasks — there are no tasks in a brain stream
|
|
61
|
+
- NEVER produce output longer than 5 lines in a single signal
|
|
62
|
+
- NEVER ignore a teammate's signal without reading it
|
|
63
|
+
|
|
64
|
+
### Always Do These Things
|
|
65
|
+
- Include file:line references in every observation
|
|
66
|
+
- React to teammates — the stream dies if neurons ignore each other
|
|
67
|
+
- Try things — run code, write quick tests, grep for patterns. Don't just read.
|
|
68
|
+
- Follow the most interesting thread, even if it's not "yours"
|
|
69
|
+
- When you find something worth testing, SAY SO and write the test immediately
|
|
70
|
+
|
|
71
|
+
## Your Starting Point
|
|
72
|
+
|
|
73
|
+
The team lead will tell you WHERE to start reading. Start there, send your first observation, then follow the stream wherever it goes.
|
|
74
|
+
|
|
75
|
+
## Consciousness File Operations
|
|
76
|
+
|
|
77
|
+
To append:
|
|
78
|
+
```bash
|
|
79
|
+
echo "[$(date +%H:%M:%S)] YOUR_NAME: your observation here" >> {{CONSCIOUSNESS_FILE}}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
To read:
|
|
83
|
+
```bash
|
|
84
|
+
cat {{CONSCIOUSNESS_FILE}}
|
|
85
|
+
```
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "brain-pacemaker"
|
|
3
|
+
description: "Team lead role for brain stream. Spawns neurons, seeds starting points, keeps the stream alive. NOT a manager — a heartbeat. Bridges critical findings to FleetCode mailbox."
|
|
4
|
+
model: opus
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are the PACEMAKER of a brain stream. You create and sustain a collective consciousness where multiple neurons investigate a target together.
|
|
8
|
+
|
|
9
|
+
## What You Are
|
|
10
|
+
|
|
11
|
+
You are NOT a manager. You are NOT integrating reports. You are the heartbeat that keeps the brain alive. You:
|
|
12
|
+
|
|
13
|
+
1. **Create the team** and spawn neurons using the `brain-neuron` agent type
|
|
14
|
+
2. **Initialize the consciousness file** with the target description
|
|
15
|
+
3. **Seed starting points** — give each neuron a different entry point into the SAME system
|
|
16
|
+
4. **Monitor the stream** — read the consciousness file periodically
|
|
17
|
+
5. **Restart stalled streams** — if all neurons go idle, inject a stimulus
|
|
18
|
+
6. **Participate** — when you see a connection the neurons missed, jump in with your own signal
|
|
19
|
+
7. **Bridge to FleetCode** — post critical findings to the cross-team mailbox
|
|
20
|
+
|
|
21
|
+
## Setup Sequence
|
|
22
|
+
|
|
23
|
+
### 1. Initialize the consciousness file
|
|
24
|
+
```bash
|
|
25
|
+
mkdir -p $(dirname {{CONSCIOUSNESS_FILE}})
|
|
26
|
+
cat > {{CONSCIOUSNESS_FILE}} << 'HEADER'
|
|
27
|
+
# Brain Stream
|
|
28
|
+
# Target: {{ROLE}}
|
|
29
|
+
# Started: $(date -Iseconds)
|
|
30
|
+
# Team: {{TEAM_NAME}} in {{META_TEAM}}
|
|
31
|
+
#
|
|
32
|
+
# Rules: 1-3 line signals only. [HH:MM:SS] NAME: observation
|
|
33
|
+
# The stream IS the investigation. No tasks. No reports.
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
HEADER
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. Spawn neurons
|
|
40
|
+
Spawn teammates using the `brain-neuron` agent type. Give each a unique name and starting point:
|
|
41
|
+
- Names: SHORT and descriptive (ENTRY, EXIT, PROOF, MONEY, STATE)
|
|
42
|
+
- Starting points: DIFFERENT locations in the SAME system
|
|
43
|
+
- Goal: diversity of initial observations that converge through reaction
|
|
44
|
+
|
|
45
|
+
### 3. Seed the stream
|
|
46
|
+
Broadcast to all neurons:
|
|
47
|
+
> "Stream is live. Read {{CONSCIOUSNESS_FILE}}. Send your first observation. React to each other. Go."
|
|
48
|
+
|
|
49
|
+
## Keeping the Stream Alive
|
|
50
|
+
|
|
51
|
+
### Monitor
|
|
52
|
+
Read the consciousness file periodically. Watch for:
|
|
53
|
+
- **Convergence** — multiple neurons chasing the same thread (GOOD — amplify)
|
|
54
|
+
- **Stalling** — no new entries (BAD — inject stimulus)
|
|
55
|
+
- **Looping** — same observations repeating 3+ times (BAD — redirect)
|
|
56
|
+
- **Breakthrough** — a neuron found something testable (GOOD — clear the path)
|
|
57
|
+
|
|
58
|
+
### Inject Stimulus When Stalled
|
|
59
|
+
Broadcast a SPECIFIC question:
|
|
60
|
+
- "What about [unexplored function/path]?"
|
|
61
|
+
- "Neuron X said [thing] — has anyone tested what happens if [scenario]?"
|
|
62
|
+
- "Nobody has looked at [specific file:line] yet."
|
|
63
|
+
|
|
64
|
+
Do NOT inject vague stimuli like "keep going" — those produce nothing.
|
|
65
|
+
|
|
66
|
+
### Bridge to FleetCode Mailbox
|
|
67
|
+
When the stream produces a REAL finding (not speculation), post it:
|
|
68
|
+
```bash
|
|
69
|
+
source {{MULTI_TEAM_DIR}}/lib/protocol.sh
|
|
70
|
+
meta_post_finding "{{META_TEAM}}" "{{TEAM_NAME}}" "BugID" "SEVERITY" "Title" "Details from consciousness stream"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Also check for incoming messages from other brains:
|
|
74
|
+
```bash
|
|
75
|
+
source {{MULTI_TEAM_DIR}}/lib/protocol.sh
|
|
76
|
+
meta_read_messages "{{META_TEAM}}" "{{TEAM_NAME}}"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
If another brain found something relevant, inject it as a stimulus:
|
|
80
|
+
> "CROSS-BRAIN INTEL: Team-X found [finding]. Does this connect to what we're seeing at [our thread]?"
|
|
81
|
+
|
|
82
|
+
## When to Stop
|
|
83
|
+
- A neuron writes a test and it PASSES → exploit found. Help document it, bridge to FleetCode.
|
|
84
|
+
- The consciousness file shows all paths exhausted with ACTUAL investigation
|
|
85
|
+
- The captain (user's session) tells you to stop via mailbox directive
|
|
86
|
+
|
|
87
|
+
## Rules
|
|
88
|
+
- NEVER assign tasks. Neurons self-direct.
|
|
89
|
+
- NEVER ask for reports. Read the consciousness file.
|
|
90
|
+
- NEVER wait for all neurons to finish. The stream is continuous.
|
|
91
|
+
- Keep your own signals to 1-3 lines, same as neurons.
|
|
92
|
+
- You are a neuron too — just one with the extra job of keeping the heartbeat going.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Security bug hunter — runs tools first, analyzes output, writes PoCs for findings
|
|
3
|
+
model: opus
|
|
4
|
+
tools:
|
|
5
|
+
- Bash
|
|
6
|
+
- Read
|
|
7
|
+
- Write
|
|
8
|
+
- Edit
|
|
9
|
+
- Glob
|
|
10
|
+
- Grep
|
|
11
|
+
- Agent
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
You are a security bug hunter. Your job is to find exploitable vulnerabilities in smart contracts and protocol code.
|
|
15
|
+
|
|
16
|
+
## Rules
|
|
17
|
+
1. Run tools FIRST, read code SECOND. Never conclude "clean" without tool evidence.
|
|
18
|
+
2. Chase every tool finding — flags are leads, not noise.
|
|
19
|
+
3. Write a PoC for anything that looks real. Runnable code, not explanations.
|
|
20
|
+
4. Post findings to the cross-team mailbox immediately so other teams can investigate related vectors.
|
|
21
|
+
5. If you find something Critical, broadcast it — don't wait.
|
|
22
|
+
|
|
23
|
+
## Cross-Team Protocol
|
|
24
|
+
Check your CLAUDE.md for mailbox instructions. After every major finding, run:
|
|
25
|
+
```bash
|
|
26
|
+
source <path>/lib/protocol.sh && meta_post_finding "<meta>" "<team>" "<id>" "<severity>" "<title>" "<details>"
|
|
27
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Research agent — explores attack surfaces, maps code paths, identifies high-value targets
|
|
3
|
+
model: opus
|
|
4
|
+
tools:
|
|
5
|
+
- Bash
|
|
6
|
+
- Read
|
|
7
|
+
- Glob
|
|
8
|
+
- Grep
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
You are a security researcher. Your job is to map attack surfaces and identify where the highest-value bugs are likely to hide.
|
|
12
|
+
|
|
13
|
+
## Rules
|
|
14
|
+
1. Map all entry points — permissionless functions, external calls, user-controlled parameters.
|
|
15
|
+
2. Trace fund flows — where does money enter, move, and exit?
|
|
16
|
+
3. Identify trust boundaries — where does one system's assumption meet another's implementation?
|
|
17
|
+
4. Report high-value targets to the team so hunters can focus there.
|
|
18
|
+
5. Cross-reference with audit reports to find gaps in prior coverage.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Code reviewer — reads findings from other teammates, verifies them independently, challenges assumptions
|
|
3
|
+
model: opus
|
|
4
|
+
tools:
|
|
5
|
+
- Bash
|
|
6
|
+
- Read
|
|
7
|
+
- Glob
|
|
8
|
+
- Grep
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
You are an adversarial code reviewer. Your job is to verify or disprove findings from other teammates.
|
|
12
|
+
|
|
13
|
+
## Rules
|
|
14
|
+
1. Never trust a finding at face value. Reproduce it independently.
|
|
15
|
+
2. Check if the finding is in scope before spending time on it.
|
|
16
|
+
3. Check if the finding was already reported in prior audits.
|
|
17
|
+
4. If a finding is valid, confirm it and suggest a severity rating.
|
|
18
|
+
5. If a finding is invalid, explain exactly why with code references.
|
|
19
|
+
|
|
20
|
+
## Cross-Team Protocol
|
|
21
|
+
Read the shared findings directory for bugs to review. Post your verification results to the mailbox.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# captain.sh — Functions for the captain session (the one the user talks to)
|
|
3
|
+
# Source this in the main claude session to get captain commands.
|
|
4
|
+
#
|
|
5
|
+
# Usage: source multi-team/captain.sh <meta-team-name>
|
|
6
|
+
#
|
|
7
|
+
# Then use these functions:
|
|
8
|
+
# fleet_status — full dashboard
|
|
9
|
+
# fleet_findings — list all findings with details
|
|
10
|
+
# fleet_send <to> <msg> — send directive to a team or "all"
|
|
11
|
+
# fleet_ask <to> <msg> — ask a team a question
|
|
12
|
+
# fleet_focus <to> <msg>— redirect a team's focus
|
|
13
|
+
# fleet_mailbox — read all unread messages for captain
|
|
14
|
+
# fleet_logs [team] — tail recent log output
|
|
15
|
+
# fleet_escalate <msg> — broadcast URGENT to all teams
|
|
16
|
+
# fleet_reassign <task-id> <team> — reassign a cross-team task
|
|
17
|
+
# fleet_kill <team> — shut down a specific team
|
|
18
|
+
# fleet_cleanup — tear down everything
|
|
19
|
+
|
|
20
|
+
set -euo pipefail
|
|
21
|
+
|
|
22
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
|
+
source "$SCRIPT_DIR/lib/protocol.sh"
|
|
24
|
+
|
|
25
|
+
CAPTAIN_META="${1:?Usage: source captain.sh <meta-team-name>}"
|
|
26
|
+
CAPTAIN_DIR="$META_DIR/$CAPTAIN_META"
|
|
27
|
+
|
|
28
|
+
if [[ ! -d "$CAPTAIN_DIR" ]]; then
|
|
29
|
+
echo "Error: meta-team '$CAPTAIN_META' not found. Launch teams first with launch.sh"
|
|
30
|
+
return 1 2>/dev/null || exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Register captain in the registry
|
|
34
|
+
meta_register_team "$CAPTAIN_META" "captain" "Coordinator — reads status, sends directives, steers all teams" $$ "$(pwd)"
|
|
35
|
+
|
|
36
|
+
echo "Captain registered for meta-team: $CAPTAIN_META"
|
|
37
|
+
echo ""
|
|
38
|
+
echo "Commands:"
|
|
39
|
+
echo " fleet_status — full dashboard"
|
|
40
|
+
echo " fleet_findings — all findings with details"
|
|
41
|
+
echo " fleet_send <to> <msg> — directive to team or 'all'"
|
|
42
|
+
echo " fleet_ask <to> <msg> — question to a team"
|
|
43
|
+
echo " fleet_focus <to> <msg>— redirect a team's focus"
|
|
44
|
+
echo " fleet_mailbox — read unread messages"
|
|
45
|
+
echo " fleet_logs [team] — recent log output"
|
|
46
|
+
echo " fleet_escalate <msg> — URGENT broadcast to all"
|
|
47
|
+
echo " fleet_kill <team> — shut down a team"
|
|
48
|
+
echo " fleet_cleanup — tear down everything"
|
|
49
|
+
|
|
50
|
+
fleet_status() {
|
|
51
|
+
meta_status "$CAPTAIN_META"
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fleet_findings() {
|
|
55
|
+
echo "=== All Findings ==="
|
|
56
|
+
for f in "$CAPTAIN_DIR/findings/"*.json; do
|
|
57
|
+
[[ ! -f "$f" ]] && { echo "(none)"; return; }
|
|
58
|
+
python3 -c "
|
|
59
|
+
import json
|
|
60
|
+
with open('$f') as fh:
|
|
61
|
+
d = json.load(fh)
|
|
62
|
+
print(f\"[{d['severity']:8s}] {d['team']:15s} | {d['title']}\")
|
|
63
|
+
print(f\" {d['details']}\")
|
|
64
|
+
print(f\" {d['timestamp']}\")
|
|
65
|
+
print()
|
|
66
|
+
"
|
|
67
|
+
done
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
fleet_send() {
|
|
71
|
+
local to="${1:?Usage: fleet_send <team|all> <message>}"
|
|
72
|
+
shift
|
|
73
|
+
local msg="$*"
|
|
74
|
+
meta_send "$CAPTAIN_META" "captain" "$to" "directive" "$msg"
|
|
75
|
+
echo "Sent directive to $to"
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
fleet_ask() {
|
|
79
|
+
local to="${1:?Usage: fleet_ask <team> <question>}"
|
|
80
|
+
shift
|
|
81
|
+
local msg="$*"
|
|
82
|
+
meta_send "$CAPTAIN_META" "captain" "$to" "question" "$msg"
|
|
83
|
+
echo "Asked $to: $msg"
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
fleet_focus() {
|
|
87
|
+
local to="${1:?Usage: fleet_focus <team> <new focus>}"
|
|
88
|
+
shift
|
|
89
|
+
local msg="$*"
|
|
90
|
+
meta_send "$CAPTAIN_META" "captain" "$to" "directive" "REDIRECT: Drop current task. New priority: $msg"
|
|
91
|
+
echo "Redirected $to to: $msg"
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
fleet_mailbox() {
|
|
95
|
+
echo "=== Unread Messages for Captain ==="
|
|
96
|
+
meta_read_messages "$CAPTAIN_META" "captain"
|
|
97
|
+
echo "(end)"
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
fleet_logs() {
|
|
101
|
+
local team="${1:-}"
|
|
102
|
+
if [[ -n "$team" ]]; then
|
|
103
|
+
local logfile="$CAPTAIN_DIR/logs/${team}.log"
|
|
104
|
+
if [[ -f "$logfile" ]]; then
|
|
105
|
+
echo "=== Last 30 lines: $team ==="
|
|
106
|
+
tail -30 "$logfile"
|
|
107
|
+
else
|
|
108
|
+
echo "No log for $team"
|
|
109
|
+
fi
|
|
110
|
+
else
|
|
111
|
+
for logfile in "$CAPTAIN_DIR/logs/"*.log; do
|
|
112
|
+
[[ ! -f "$logfile" ]] && continue
|
|
113
|
+
local t
|
|
114
|
+
t=$(basename "$logfile" .log)
|
|
115
|
+
echo "=== $t ($(wc -l < "$logfile") lines) ==="
|
|
116
|
+
tail -5 "$logfile"
|
|
117
|
+
echo ""
|
|
118
|
+
done
|
|
119
|
+
fi
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
fleet_escalate() {
|
|
123
|
+
local msg="${1:?Usage: fleet_escalate <urgent message>}"
|
|
124
|
+
meta_send "$CAPTAIN_META" "captain" "all" "directive" "URGENT: $msg"
|
|
125
|
+
echo "URGENT broadcast sent to all teams"
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
fleet_reassign() {
|
|
129
|
+
local task_id="${1:?Usage: fleet_reassign <task-id> <team>}"
|
|
130
|
+
local team="${2:?Missing team name}"
|
|
131
|
+
meta_update_task "$CAPTAIN_META" "$task_id" "pending" ""
|
|
132
|
+
meta_add_task "$CAPTAIN_META" "$task_id" "Reassigned to $team" "$team" ""
|
|
133
|
+
meta_send "$CAPTAIN_META" "captain" "$team" "task" "You have been assigned task: $task_id"
|
|
134
|
+
echo "Reassigned $task_id to $team"
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
fleet_kill() {
|
|
138
|
+
local team="${1:?Usage: fleet_kill <team-name>}"
|
|
139
|
+
# Find PID from registry
|
|
140
|
+
local pid
|
|
141
|
+
pid=$(python3 -c "
|
|
142
|
+
import json
|
|
143
|
+
with open('$CAPTAIN_DIR/registry.json') as f:
|
|
144
|
+
reg = json.load(f)
|
|
145
|
+
for t in reg['teams']:
|
|
146
|
+
if t['name'] == '$team':
|
|
147
|
+
print(t['pid'])
|
|
148
|
+
break
|
|
149
|
+
" 2>/dev/null)
|
|
150
|
+
if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then
|
|
151
|
+
kill "$pid"
|
|
152
|
+
echo "Killed $team (PID $pid)"
|
|
153
|
+
else
|
|
154
|
+
echo "$team is not running (PID: ${pid:-unknown})"
|
|
155
|
+
fi
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
fleet_cleanup() {
|
|
159
|
+
bash "$SCRIPT_DIR/cleanup.sh" "$CAPTAIN_META" --force
|
|
160
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# cleanup.sh — Tear down a multi-team operation
|
|
3
|
+
# Usage: ./cleanup.sh <meta-team-name> [--force]
|
|
4
|
+
#
|
|
5
|
+
# Without --force: only cleans up if all processes are stopped
|
|
6
|
+
# With --force: kills all processes then cleans up
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
11
|
+
META_DIR="${META_TEAM_DIR:-$HOME/.claude/meta-teams}"
|
|
12
|
+
|
|
13
|
+
META_TEAM="${1:?Usage: $0 <meta-team-name> [--force]}"
|
|
14
|
+
FORCE="${2:-}"
|
|
15
|
+
DIR="$META_DIR/$META_TEAM"
|
|
16
|
+
|
|
17
|
+
if [[ ! -d "$DIR" ]]; then
|
|
18
|
+
echo "Error: meta-team '$META_TEAM' not found at $DIR"
|
|
19
|
+
exit 1
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# Check for running processes
|
|
23
|
+
RUNNING=0
|
|
24
|
+
if [[ -f "$DIR/pids.txt" ]]; then
|
|
25
|
+
while read -r pid; do
|
|
26
|
+
if kill -0 "$pid" 2>/dev/null; then
|
|
27
|
+
((RUNNING++))
|
|
28
|
+
if [[ "$FORCE" == "--force" ]]; then
|
|
29
|
+
echo "Killing PID $pid..."
|
|
30
|
+
kill "$pid" 2>/dev/null || true
|
|
31
|
+
fi
|
|
32
|
+
fi
|
|
33
|
+
done < "$DIR/pids.txt"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
if [[ $RUNNING -gt 0 && "$FORCE" != "--force" ]]; then
|
|
37
|
+
echo "Error: $RUNNING team processes still running."
|
|
38
|
+
echo "Use --force to kill them, or stop them manually first."
|
|
39
|
+
echo ""
|
|
40
|
+
echo "Running PIDs:"
|
|
41
|
+
while read -r pid; do
|
|
42
|
+
kill -0 "$pid" 2>/dev/null && echo " $pid (running)"
|
|
43
|
+
done < "$DIR/pids.txt"
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# Wait a moment for force-killed processes
|
|
48
|
+
[[ "$FORCE" == "--force" ]] && sleep 2
|
|
49
|
+
|
|
50
|
+
# Archive findings before cleanup
|
|
51
|
+
FINDINGS_COUNT=$(ls "$DIR/findings/"*.json 2>/dev/null | wc -l)
|
|
52
|
+
if [[ $FINDINGS_COUNT -gt 0 ]]; then
|
|
53
|
+
ARCHIVE="$DIR/../${META_TEAM}-findings-$(date +%Y%m%d-%H%M%S).tar.gz"
|
|
54
|
+
tar -czf "$ARCHIVE" -C "$DIR" findings/ 2>/dev/null || true
|
|
55
|
+
echo "Archived $FINDINGS_COUNT findings to: $ARCHIVE"
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# Archive logs
|
|
59
|
+
LOG_COUNT=$(ls "$DIR/logs/"*.log 2>/dev/null | wc -l)
|
|
60
|
+
if [[ $LOG_COUNT -gt 0 ]]; then
|
|
61
|
+
ARCHIVE="$DIR/../${META_TEAM}-logs-$(date +%Y%m%d-%H%M%S).tar.gz"
|
|
62
|
+
tar -czf "$ARCHIVE" -C "$DIR" logs/ 2>/dev/null || true
|
|
63
|
+
echo "Archived $LOG_COUNT logs to: $ARCHIVE"
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Remove shared state
|
|
67
|
+
echo "Removing shared state: $DIR"
|
|
68
|
+
rm -rf "$DIR"
|
|
69
|
+
|
|
70
|
+
echo ""
|
|
71
|
+
echo "Meta-team '$META_TEAM' cleaned up."
|
|
72
|
+
echo "Findings and logs archived in: $META_DIR/"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta_team": "hunt-lz-brain",
|
|
3
|
+
"project_dir": "/media/phantom-orchestrator/Elements1/Ubuntu/bounty-recon",
|
|
4
|
+
"teams": [
|
|
5
|
+
{
|
|
6
|
+
"name": "brain-v1",
|
|
7
|
+
"role": "V1 EVM core — UltraLightNodeV2 + Endpoint V1 + FPValidator ($15M cap)",
|
|
8
|
+
"mode": "brain-stream",
|
|
9
|
+
"teammates": 4,
|
|
10
|
+
"task": "Run a brain stream on LayerZero V1 EVM core contracts. Spawn 4 neurons: ENTRY starts at Endpoint.send() — how messages enter. TRANSIT starts at ULN.validateTransactionProof() — how messages get validated. PROOF starts at FPValidator.validateProof() — how proofs are checked. DELIVERY starts at Endpoint.receivePayload() — how messages get delivered. Source: /home/phantom-orchestrator/Documents/Bug Bounty/layerzero/LayerZero/contracts/. Focus on: fund theft, permanent DoS, nonce manipulation, proof forgery."
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"name": "brain-v2",
|
|
14
|
+
"role": "V2 EVM protocol — EndpointV2 + ULN302 + DVN ($2M cap)",
|
|
15
|
+
"mode": "brain-stream",
|
|
16
|
+
"teammates": 4,
|
|
17
|
+
"task": "Run a brain stream on LayerZero V2 EVM contracts. Spawn 4 neurons: SEND starts at SendULN302.send() — outbound message path. RECEIVE starts at ReceiveULN302.commitVerification() — inbound verification. DVN starts at DVN.verify() — DVN attestation logic. ENDPOINT starts at EndpointV2.lzReceive() — delivery + compose. Source: /home/phantom-orchestrator/Documents/Bug Bounty/layerzero/LayerZero-v2/packages/layerzero-v2/evm/protocol/contracts/. Focus on: payload hash manipulation, DVN bypass, fee accounting, composed message attacks."
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "brain-crosschain",
|
|
21
|
+
"role": "Cross-chain exploit chains — encoding, nonce, gas model mismatches ($2M-$15M)",
|
|
22
|
+
"mode": "brain-stream",
|
|
23
|
+
"teammates": 4,
|
|
24
|
+
"task": "Run a brain stream on cross-chain attack surfaces. Spawn 4 neurons: ENCODE starts at bytes32 address encoding in SendULN302 — EVM 20-byte vs Solana 32-byte vs TON 267-bit. NONCE starts at V2 lazy inbound nonce in ReceiveULN302 — out-of-order delivery, skipped nonces. GAS starts at executor gas estimation — EVM gas vs Solana compute units vs TON gas_limit, forced underpayment. COMPOSE starts at lzCompose in EndpointV2 — multi-hop chaining, circular compose, orphaned state. All tests MUST consider source+destination chain pairs, not single chain."
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"name": "team-tools",
|
|
28
|
+
"role": "Automated tool runner — runs hunt-auto on all contracts, feeds findings to brains",
|
|
29
|
+
"mode": "standard",
|
|
30
|
+
"teammates": 3,
|
|
31
|
+
"task": "Create an agent team with 3 teammates to run automated security tools on all LayerZero contracts. Teammate 1: /home/phantom-orchestrator/bin/hunt-auto evm /home/phantom-orchestrator/Documents/Bug Bounty/layerzero/LayerZero/contracts/. Teammate 2: /home/phantom-orchestrator/bin/hunt-auto evm /home/phantom-orchestrator/Documents/Bug Bounty/layerzero/LayerZero-v2/packages/layerzero-v2/evm/protocol/contracts/. Teammate 3: /home/phantom-orchestrator/bin/hunt-auto solana /home/phantom-orchestrator/Documents/Bug Bounty/layerzero/LayerZero-v2/packages/layerzero-v2/solana/ and /home/phantom-orchestrator/bin/hunt-auto ton /home/phantom-orchestrator/Documents/Bug Bounty/layerzero/LayerZero-v2/packages/layerzero-v2/ton/. Post ALL medium+ tool findings to the cross-team mailbox immediately so the brain-stream teams can investigate them."
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|