create-ironclaws 1.0.4 → 1.1.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-ironclaws",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "description": "Create an IronClaws AI agent platform in seconds",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,66 +1,123 @@
1
- # NanoClawArdoq IT Ops Agent Platform
1
+ # IronClawsAI Agent Platform
2
2
 
3
- Internal deployment of NanoClaw. Hosts the Ardoq IT agent fleet over Slack.
3
+ This is an IronClaws deployment. It runs a fleet of AI agents over Slack.
4
4
 
5
5
  ## Architecture
6
6
 
7
- Single Node.js host process. Each registered agent gets its own Docker container (isolated filesystem + memory) spawned on demand. Agents communicate back via IPC files. All agents share one Docker image: `argus-claude:latest`.
7
+ Single Node.js host process. Each agent gets its own Docker container isolated filesystem, memory, and credentials. The host handles Slack routing, scheduling, and security. Agents do the actual work.
8
+
9
+ ```
10
+ Slack
11
+
12
+
13
+ IronClaws host (src/index.ts)
14
+ │ reads .env, agents.yaml, agent-credentials.yaml
15
+
16
+ ├── Message router ──► spawns Docker container per agent
17
+ ├── Task scheduler ──► spawns containers on schedule
18
+ └── IPC watcher ──► reads results from containers
19
+
20
+
21
+ Docker container (argus-claude:latest)
22
+ ├── Claude Code (the AI)
23
+ ├── agent-runner (IPC bridge)
24
+ ├── Python tools (container/tools/)
25
+ └── Skills (container/skills/)
26
+ ```
8
27
 
9
28
  ## Key Files
10
29
 
11
30
  | File | Purpose |
12
31
  |------|---------|
13
32
  | `src/index.ts` | Main loop: message routing, agent invocation, state |
14
- | `src/channels/slack.ts` | Slack channel integration (Socket Mode) |
33
+ | `src/channels/slack.ts` | Slack Socket Mode integration |
15
34
  | `src/container-runner.ts` | Spawns containers with correct mounts and env vars |
16
35
  | `src/ipc.ts` | IPC file watcher — agents write here to send messages / schedule tasks |
17
36
  | `src/task-scheduler.ts` | Cron-based task scheduling |
18
37
  | `src/db.ts` | SQLite: messages, groups, sessions, tasks |
19
- | `src/config.ts` | Trigger patterns, paths, env var loading |
20
- | `src/sender-allowlist.ts` | Per-channel sender filtering |
38
+ | `agents.yaml` | Declarative agent registry single source of truth for the fleet |
39
+ | `agent-credentials.yaml` | Per-agent access control: which env vars, tools, and skills each agent gets |
21
40
  | `groups/{name}/CLAUDE.md` | Per-agent identity and instructions |
22
- | `container/Dockerfile.argus` | Agent container image definition |
41
+ | `container/Dockerfile.argus` | Agent container image |
23
42
  | `container/tools/` | Python tools available inside containers |
24
- | `container/skills/` | Shared skills available to all agents |
43
+ | `container/skills/` | Shared skills (SKILL.md files) available to agents |
25
44
 
26
- ## Agent Fleet
45
+ ## Your Agent Fleet
27
46
 
28
47
  | Agent | Folder | Channel | Purpose |
29
48
  |-------|--------|---------|---------|
30
- | Argus Alert | `argus-alert` | Alert channel | Monitors alerts, investigates incidents, raises fix PRs |
31
- | Argus Deps | `argus-deps` | Deps channel | Manages Dependabot alerts, bumps packages |
32
- | Byte | `byte` | IT standup | Team standup agent, team memory |
33
- | Byte IT Internal | `byte-it-internal` | IT internal | Silent reader, writes to Byte's MEMORY.md |
34
- | Ticket Creator | `ticket-creator` | Ticket channel | Creates Jira tickets from Slack conversation |
35
- | Jira Worker | `jira-worker` | Worker channel | Picks up IAI tickets, implements, raises PRs |
36
- | Global Claw | `global-claw` | DM (Sewnet only) | Meta-agent: manages all other agents |
49
+ | Forge | `forge` | Your channel | Built-in guide helps you add new agents and troubleshoot |
50
+
51
+ Add more agents by creating a `groups/{name}/CLAUDE.md`, adding an entry to `agents.yaml`, and setting the channel ID in `.env`.
52
+
53
+ ## Adding an Agent
54
+
55
+ **1. Create the agent instructions:**
56
+ ```bash
57
+ mkdir -p groups/my-agent
58
+ # Write groups/my-agent/CLAUDE.md — the agent's identity, what it does, how to respond
59
+ ```
60
+
61
+ **2. Register in `agents.yaml`:**
62
+ ```yaml
63
+ - folder: my-agent
64
+ name: "My Agent"
65
+ trigger: "@Argus"
66
+ channel_env: MY_AGENT_CHANNEL_ID
67
+ requires_trigger: false
68
+ onecli_secrets: [litellm]
69
+ onecli_id: <python3 -c "import uuid; print(uuid.uuid4())">
70
+ ```
71
+
72
+ **3. Set the channel ID in `.env`:**
73
+ ```
74
+ MY_AGENT_CHANNEL_ID=C...
75
+ ```
76
+
77
+ **4. Restart IronClaws** — agents auto-register on startup. No script needed.
37
78
 
38
79
  ## Container Image
39
80
 
40
- All agents use `argus-claude:latest`. Built with:
81
+ All agents share one image: `argus-claude:latest`. Build it with:
41
82
  ```bash
42
- cd container && ./build-argus.sh
83
+ cd container && ./build.sh && ./build-argus.sh
43
84
  ```
44
85
 
45
- Set `CONTAINER_IMAGE=argus-claude:latest` in `.env`.
86
+ ## Tools
87
+
88
+ Located in `container/tools/` — baked into the image at build time. There are no default tools. You add the tools your agents need.
46
89
 
47
- ## Tools Available Inside Containers
90
+ Drop a Python script into `container/tools/`, rebuild the image, then grant access in `agent-credentials.yaml`:
91
+ ```yaml
92
+ agents:
93
+ my-agent:
94
+ tools: [my_tool.py]
95
+ config: [MY_SERVICE_URL]
96
+ ```
48
97
 
49
- Located in `container/tools/` baked into the image:
50
- - `elastic_query.py` — Kibana/Elastic log querying
51
- - `jira_tool.py` — Jira CRUD (get, search, create, update, comment, assign)
52
- - `gdrive_tool.py` — Google Drive transcript reading
53
- - `slack_history_tool.py` — Slack channel history fetching
98
+ See `container/tools/README.md` for design principles and auth patterns.
54
99
 
55
100
  ## Skills Available Inside Containers
56
101
 
57
- Located in `container/skills/` — loaded at runtime:
58
- - `agent-browser` — web browsing
59
- - `capabilities` — list available skills
60
- - `slack-formatting` — Slack mrkdwn formatting reference
102
+ Located in `container/skills/` — mounted at runtime, no rebuild needed.
103
+
104
+ - `slack-formatting` — Slack mrkdwn formatting rules (loaded by all agents)
105
+ - `capabilities` — lets agents list available tools
61
106
  - `status` — system health check
62
- - `agent-status` — dashboard of all agents
63
- - `edit-agent` — collaborative CLAUDE.md editing
107
+ - `agent-browser` — web browsing capability
108
+ - `agent-status` — dashboard of all running agents
109
+ - `edit-agent` — collaborative CLAUDE.md editing from Slack
110
+
111
+ ## Credentials and Security
112
+
113
+ The `agent-credentials.yaml` file controls what each agent can access:
114
+ - `config:` — env vars from `.env` forwarded to the container
115
+ - `tools:` — Python scripts mounted at `/workspace/extra/tools/`
116
+ - `skills:` — SKILL.md files made available
117
+
118
+ Dangerous skills (`edit-agent`, `agent-browser`, `agent-status`) are not in the default set — agents must explicitly opt in. See `agent-credentials.yaml`.
119
+
120
+ Service API credentials (Jira, Slack, etc.) are never in containers. The OneCLI proxy intercepts HTTPS traffic and injects `Authorization` headers server-side. See `docs/how-it-works.md` → Secrets Management.
64
121
 
65
122
  ## Runtime Config
66
123
 
@@ -68,37 +125,34 @@ Key env vars (set in `.env`):
68
125
  ```
69
126
  SLACK_BOT_TOKEN Slack bot token (xoxb-...)
70
127
  SLACK_APP_TOKEN Slack app-level token (xapp-...)
71
- GITHUB_TOKEN GitHub PAT for raising PRs
72
- GITHUB_APP_ID GitHub App ID (for token generation)
73
- ELASTIC_BASE_URL Kibana base URL
74
- ELASTIC_API_KEY Kibana API key
75
- JIRA_BASE_URL https://ardoqcom.atlassian.net
76
- JIRA_EMAIL Jira account email
77
- JIRA_API_TOKEN Jira API token
78
- JIRA_PROJECT_KEY IAI
128
+ ANTHROPIC_BASE_URL LiteLLM gateway URL
129
+ ANTHROPIC_AUTH_TOKEN LiteLLM auth token
79
130
  CONTAINER_IMAGE argus-claude:latest
80
131
  ```
81
132
 
133
+ See `.env.example` for the full list with descriptions.
134
+
82
135
  ## Security
83
136
 
84
- - Mount allowlist: `~/.config/nanoclaw/mount-allowlist.json` — controls what host paths containers can access
85
- - Sender allowlist: `~/.config/nanoclaw/sender-allowlist.json` — per-channel sender filtering, outside project root (tamper-proof)
86
- - Global Claw DM is restricted to Sewnet only (U04S2VA1CU8) at allowlist level
87
- - `github-app.pem` is gitignored — never commit
137
+ - Mount allowlist: `~/.config/nanoclaw/mount-allowlist.json` — controls what host paths containers can access. Outside the project directory so containers can't read or modify it.
138
+ - Sender allowlist: `~/.config/nanoclaw/sender-allowlist.json` — per-channel sender filtering. Also outside the project directory.
139
+ - `*.pem` files are gitignored never commit private keys
88
140
 
89
141
  ## Running
90
142
 
91
143
  ```bash
92
- npm run dev # Development (hot reload)
93
- npm run build # Compile TypeScript
94
- npm start # Production
144
+ docker compose up -d # Start OneCLI credential proxy
145
+ npm run dev # Start IronClaws (development, hot reload)
146
+ npm run build && npm start # Production
95
147
  ```
96
148
 
97
149
  ## First-Time Setup
98
150
 
99
151
  1. Copy `.env.example` to `.env` and fill in all values
100
- 2. Run `./setup-agents.sh` to register all agents in the SQLite database
101
- 3. Update `~/.config/nanoclaw/sender-allowlist.json` with channel IDs
102
- 4. Update `~/.config/nanoclaw/mount-allowlist.json` for Global Claw repo access
103
- 5. Build the container: `cd container && ./build-argus.sh`
104
- 6. Start: `npm run dev`
152
+ 2. Start OneCLI: `docker compose up -d`
153
+ 3. Build the container image: `cd container && ./build.sh && ./build-argus.sh`
154
+ 4. Start IronClaws: `npm run dev`
155
+ 5. Agents auto-register on startup no script needed
156
+ 6. Say hello in the configured Slack channel
157
+
158
+ For credential registration (Jira, Elastic, etc.): `bash scripts/setup-onecli-secrets.sh`
@@ -1,6 +1,6 @@
1
- # Argus Claude Agent Container
2
- # Extends the NanoClaw agent image with Python, Poetry, gh CLI, and moon
3
- # so Claude's Bash tool can run poetry lock, gh pr create, moon lint, etc.
1
+ # IronClaws Agent Container
2
+ # Extends the base NanoClaw image with Python and the gh CLI.
3
+ # This is intentionally minimal add your own dependencies as needed.
4
4
  #
5
5
  # Build the base image first: ./container/build.sh
6
6
  # Then build this image: ./container/build-argus.sh
@@ -9,24 +9,26 @@ FROM nanoclaw-agent:latest
9
9
 
10
10
  USER root
11
11
 
12
- # Python 3 + pip (requests needed by elastic_query.py)
12
+ # Python 3 + pip required to run tools from container/tools/
13
+ # requests: foundational HTTP library; most tools will need it
13
14
  RUN apt-get update && apt-get install -y python3 python3-pip && rm -rf /var/lib/apt/lists/*
14
- RUN pip3 install requests tenacity youtube-transcript-api markdownify --break-system-packages
15
+ RUN pip3 install requests --break-system-packages
15
16
 
16
- # Poetry
17
- RUN pip3 install poetry --break-system-packages
18
-
19
- # gh CLI
17
+ # gh CLI — for agents that work with GitHub (PR creation, issue management, etc.)
20
18
  RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
21
19
  | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg 2>/dev/null && \
22
20
  echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] \
23
21
  https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
24
22
  apt-get update && apt-get install -y gh && rm -rf /var/lib/apt/lists/*
25
23
 
26
- # moon task runner
27
- RUN npm install -g @moonrepo/cli
24
+ # ── Add your own dependencies here ────────────────────────────────────────────
25
+ # Examples:
26
+ # RUN pip3 install tenacity pyjwt pyyaml --break-system-packages
27
+ # RUN pip3 install poetry --break-system-packages
28
+ # RUN npm install -g @moonrepo/cli
28
29
 
29
- # Argus tools — baked into the image, no repo mount needed
30
+ # Tools — baked into the image at build time
31
+ # Add Python scripts to container/tools/ and rebuild to make them available
30
32
  COPY tools/ /workspace/extra/tools/
31
33
  RUN chown -R node:node /workspace/extra/tools && chmod -R 755 /workspace/extra/tools
32
34
 
@@ -42,25 +42,25 @@ Tables don't render. Use these patterns instead:
42
42
 
43
43
  **Field list (best for structured data):**
44
44
  ```
45
- *Voucher:* AP-818
46
- *Vendor:* Metosin Oy
47
- *Amount:* 325,994.74 NOK
48
- *Posted:* 2025-08-31
45
+ *Ticket:* PROJ-042
46
+ *Assignee:* eng@yourcompany.com
47
+ *Priority:* High
48
+ *Due:* 2026-06-30
49
49
  ```
50
50
 
51
51
  **Compact inline (best for short summaries):**
52
52
  ```
53
- AP-818Metosin Oy325,994.74 NOK 2025-08-31
53
+ PROJ-042Deploy pipeline fix HighDue 2026-06-30
54
54
  ```
55
55
 
56
56
  **Key-value in code block (best for exact copy-paste, e.g. email drafts):**
57
57
  ````
58
58
  ```
59
- Voucher: AP-818
60
- Vendor: Metosin Oy
61
- Amount: 325,994.74 NOK
62
- Move from: 6784 – Konsulentkostnader Utvikling
63
- Move to: [INSERT ACCOUNT]
59
+ Ticket: PROJ-042
60
+ Summary: Deploy pipeline fix
61
+ Priority: High
62
+ Assignee: eng@yourcompany.com
63
+ Due date: 2026-06-30
64
64
  ```
65
65
  ````
66
66
 
@@ -94,13 +94,12 @@ _Footer — instructions or next steps_
94
94
  ```
95
95
  :red_circle: *1 violation found — action required*
96
96
 
97
- *Voucher:* AP-818
98
- *Vendor:* Metosin Oy (Finland)
99
- *Amount:* 325,994.74 NOK
100
- *Posted:* 2025-08-31
101
- *Issue:* Vendor invoice posted to 6784 — must be reclassified by Amesto
97
+ *Item:* PROJ-042
98
+ *Assigned to:* eng@yourcompany.com
99
+ *Found:* 2026-06-15
100
+ *Issue:* Missing required field — needs manual review before proceeding
102
101
 
103
- > Christianfill in `[INSERT ACCOUNT]` and send the correction email below.
102
+ > Team Lead please review and confirm the correct value.
104
103
  ```
105
104
 
106
105
  ---
@@ -108,11 +107,11 @@ _Footer — instructions or next steps_
108
107
  ## Status summaries
109
108
 
110
109
  ```
111
- :white_check_mark: *Expense check complete — May 2026*
110
+ :white_check_mark: *Check complete — June 2026*
112
111
 
113
- Reports checked: 14 | Expenses: 67
114
- • :red_circle: 2 red violations | :large_yellow_circle: 7 yellow flags
115
- Notifications: 0 (DM sending not yet enabled)
112
+ Items reviewed: 14 | Findings: 3
113
+ • :red_circle: 1 critical | :large_yellow_circle: 2 warnings
114
+ • :large_green_circle: 11 clean
116
115
  ```
117
116
 
118
117
  ---
@@ -122,25 +121,26 @@ _Footer — instructions or next steps_
122
121
  Always use a triple-backtick code block. This makes it copy-paste ready and visually distinct:
123
122
 
124
123
  ````
125
- Here's the correction email for Christian to review and send:
124
+ Here's the draft for your review:
126
125
 
127
126
  ```
128
- To: [Amesto contact]
129
- Cc: finance@ardoq.com, Christian Dotterweich <christian.dotterweich@ardoq.com>
130
- Subject: Correction requestvoucher AP-818 — move from 6784 to [INSERT ACCOUNT]
127
+ To: recipient@theircompany.com
128
+ Cc: team@yourcompany.com
129
+ Subject: Action requiredPROJ-042
131
130
 
132
- Hi [Amesto contact],
131
+ Hi [Name],
133
132
 
134
- Please reclassify the following vendor invoice ...
133
+ Please review the following item and confirm the correction below.
135
134
 
136
- Voucher: AP-818
137
- Vendor: Metosin Oy
138
- Amount: 325,994.74 NOK
139
- Move from: 6784 – Konsulentkostnader Utvikling
140
- Move to: [INSERT ACCOUNT]
135
+ Item: PROJ-042
136
+ Details: [description]
137
+ Action: [what needs to happen]
138
+ Deadline: [date]
139
+
140
+ Please confirm once resolved.
141
141
 
142
142
  Thanks,
143
- Christian Dotterweich
143
+ [Your Name]
144
144
  ```
145
145
  ````
146
146
 
@@ -151,10 +151,10 @@ Christian Dotterweich
151
151
  Use `send_message` for long-running tasks so people know you're working:
152
152
 
153
153
  ```
154
- :hourglass_flowing_sand: Fetching transactions from Xledger...
154
+ :hourglass_flowing_sand: Fetching data from the API...
155
155
  ```
156
156
  ```
157
- :mag: Found 3 entries on account 6784 — running classification...
157
+ :mag: Found 3 items — running checks...
158
158
  ```
159
159
 
160
160
  ---
@@ -162,12 +162,11 @@ Use `send_message` for long-running tasks so people know you're working:
162
162
  ## Escalations and warnings
163
163
 
164
164
  ```
165
- :rotating_light: *Annual true-up required December close*
165
+ :rotating_light: *Review required before proceeding*
166
166
 
167
- The December close report cannot be marked complete until the annual true-up is logged.
167
+ This task cannot complete automatically. Human judgment needed.
168
168
 
169
- Reply with:
170
- `annual true-up done 2025: <summary including adjustment amount>`
169
+ Please reply with your decision or `skip` to defer.
171
170
  ```
172
171
 
173
172
  ---
@@ -175,13 +174,13 @@ Reply with:
175
174
  ## Confirmations and success
176
175
 
177
176
  ```
178
- :white_check_mark: *Done* — session flagged as resolved in state/flagged_6784.json
177
+ :white_check_mark: *Done* — state updated in flagged_items.json
179
178
  ```
180
179
 
181
180
  ```
182
- :white_check_mark: *Reconciliation complete — 67842025-08*
181
+ :white_check_mark: *Check complete — PROJJune 2026*
183
182
 
184
- :red_circle: 1 violation | :large_green_circle: 1 compliant | no volume flag
183
+ :red_circle: 1 violation | :large_green_circle: 3 compliant
185
184
  ```
186
185
 
187
186
  ---
@@ -192,9 +191,9 @@ Use `•` for bullets. Never `1.` numbered lists (they don't render as lists in
192
191
 
193
192
  ```
194
193
  What was checked:
195
- Account 6784 — Konsulentkostnader Utvikling
196
- • Period: 2025-08 (August)
197
- Source: Xledger GraphQL API
194
+ Data source: API
195
+ • Period: 2026-06 (June)
196
+ Items reviewed: 14
198
197
  ```
199
198
 
200
199
  ---
@@ -202,9 +201,9 @@ What was checked:
202
201
  ## Mentions and links
203
202
 
204
203
  ```
205
- <@U04S2VA1CU8> # Mention a specific user
206
- <#C0B36KNFDHV|finance-close-ops> # Link a channel
207
- <https://expensify.com/report?id=123|View report> # Named link
204
+ <@USERID> # Mention a specific user
205
+ <#CHANNELID|channel-name> # Link a channel
206
+ <https://app.yourservice.com/item/123|View> # Named link
208
207
  ```
209
208
 
210
209
  ---
@@ -0,0 +1,33 @@
1
+ # Tools
2
+
3
+ Add Python scripts here that your agents need. Each script becomes available
4
+ inside containers at `/workspace/extra/tools/<script-name>`.
5
+
6
+ ## How to add a tool
7
+
8
+ 1. Drop your Python script here: `container/tools/my_tool.py`
9
+ 2. Rebuild the container image: `cd container && ./build-argus.sh`
10
+ 3. Grant access to specific agents in `agent-credentials.yaml`:
11
+ ```yaml
12
+ agents:
13
+ my-agent:
14
+ tools: [my_tool.py]
15
+ ```
16
+
17
+ ## Design principles
18
+
19
+ - One purpose per tool. A Jira tool does Jira things. A database tool does database things.
20
+ - Output JSON to stdout. Errors to stderr. Exit non-zero on failure.
21
+ - Auth: don't put credentials in tools. Use the OneCLI proxy (`HTTPS_PROXY` is set
22
+ automatically in every container — outbound requests get Authorization headers
23
+ injected by the proxy for any service you've configured in OneCLI).
24
+ - If a service embeds credentials in request bodies (not headers), pass them via
25
+ env vars listed in `agent-credentials.yaml` → `config:`.
26
+
27
+ ## What's available inside containers
28
+
29
+ - Python 3 with `requests` — for HTTP calls
30
+ - `gh` CLI — for GitHub operations (PR creation, issue management)
31
+ - All skills from `container/skills/`
32
+
33
+ Add dependencies to `container/Dockerfile.argus` and rebuild.
@@ -113,7 +113,7 @@ This is the most important system to understand. The design goal: **no long-live
113
113
 
114
114
  ### The Four Credential Categories
115
115
 
116
- #### A. Service API Keys (Elastic, Jira, Confluence, Slack, Intercom, Ardoq)
116
+ #### A. Service API Keys (Jira, Slack, Elastic, Confluence, and any other services you configure)
117
117
  These never enter containers at all. The OneCLI proxy intercepts HTTPS requests and injects the `Authorization` header server-side. The container makes a request to `jira.atlassian.com`, OneCLI intercepts, adds `Authorization: Basic <token>`, forwards it. The container only ever sees the base URL.
118
118
 
119
119
  ```
@@ -136,10 +136,10 @@ Same pattern as GitHub. The host holds the OAuth refresh token. Before spawning,
136
136
 
137
137
  **Where to read:** `src/google-token.ts`, `container-runner.ts:470–478`
138
138
 
139
- #### D. Expensify Credentials (the exception)
140
- Expensify embeds credentials in the **JSON request body** (not in HTTP headers). OneCLI can only inject headers, so it can't handle Expensify. These two env vars (`EXPENSIFY_PARTNER_USER_ID`, `EXPENSIFY_PARTNER_USER_SECRET`) must be passed directly to the container. This is explicitly documented as a known trade-off, and only the `expense-policy-checker` agent gets them.
139
+ #### D. Services that embed credentials in request bodies (the exception)
140
+ Some APIs embed credentials in JSON request bodies rather than HTTP headers (e.g. certain payment or partner APIs). OneCLI can only inject headers it cannot inject body parameters. For these, the credentials must be passed as env vars directly to the container. This is explicitly documented as a known trade-off, and only the agents that specifically need them should receive them (principle of least privilege).
141
141
 
142
- **Where to read:** `agent-credentials.yaml` (comment on expense-policy-checker block)
142
+ **Where to read:** `agent-credentials.yaml` add these under `config:` for the relevant agent
143
143
 
144
144
  ### Per-Agent Selective Credentials
145
145
 
@@ -148,7 +148,7 @@ Each agent only gets the credentials it actually needs. This is configured in tw
148
148
  **`agent-credentials.yaml`** — controls which env vars from the host's `.env` are forwarded:
149
149
  ```yaml
150
150
  agents:
151
- argus-alert:
151
+ my-agent:
152
152
  config:
153
153
  - GITHUB_TOKEN # gets a fresh token injected
154
154
  - ELASTIC_BASE_URL # just a URL, not a secret
@@ -156,7 +156,7 @@ agents:
156
156
 
157
157
  **`agents.yaml`** — controls which OneCLI credential sets are linked (for service auth via proxy):
158
158
  ```yaml
159
- - folder: byte-it-internal
159
+ - folder: my-agent
160
160
  onecli_secrets: [slack, litellm] # can call Slack API + Claude API
161
161
  ```
162
162
 
@@ -187,7 +187,7 @@ When OneCLI intercepts a request:
187
187
  3. If yes: injects the `Authorization: Bearer <secret>` header
188
188
  4. If no credential: proxies the request unchanged (or blocks if configured to do so)
189
189
 
190
- The `access_token` in the proxy URL is the per-agent token stored in OneCLI's PostgreSQL database. It's regenerated each time `setup-agents.sh` is run.
190
+ The `access_token` in the proxy URL is the per-agent token stored in OneCLI's PostgreSQL database. It's generated when the agent is first registered (automatically on startup).
191
191
 
192
192
  ### Git Authentication Fix
193
193
 
@@ -201,7 +201,7 @@ GIT_CONFIG_VALUE_0=Authorization: Basic <base64(x:token)>
201
201
  - `src/container-runner.ts:482–499` — where `applyContainerConfig()` is called
202
202
  - `node_modules/@onecli-sh/sdk/lib/index.js` — what it actually injects
203
203
  - `agents.yaml` — `onecli_id` and `onecli_secrets` per agent
204
- - `setup-agents.sh:101–124` — how agents are registered in OneCLI's DB
204
+ - `src/index.ts` — `autoRegisterAgentsFromYaml()` — how agents are registered on startup
205
205
 
206
206
  ---
207
207
 
@@ -227,12 +227,12 @@ The `REJECT` (not `DROP`) matters: with `DROP`, a blocked connection hangs for m
227
227
  The iptables rules only allow port 10255 (OneCLI proxy). Since `HTTPS_PROXY` is set in the container, ALL HTTPS calls go through port 10255 automatically. So:
228
228
  - Direct `api.anthropic.com:443` connections → REJECTED (but these go through proxy anyway)
229
229
  - Claude API calls → port 10255 → OneCLI → forwarded with credentials → OK
230
- - Expensify calls → port 10255 → OneCLI → forwarded without modification (body unchanged) → OK
230
+ - Calls to any service with no credential → port 10255 → OneCLI → forwarded unchanged service decides auth
231
231
  - Any unauthorized service → port 10255 → OneCLI → no credential → 401 or blocked
232
232
 
233
233
  ### Cleanup
234
234
 
235
- Rules are tagged with the container name (`--comment "nanoclaw-argus-deps-123"`). When the container exits, all its rules are deleted. On NanoClaw startup, stale rules from any previous run are cleaned up automatically.
235
+ Rules are tagged with the container name (`--comment "nanoclaw-my-agent-123"`). When the container exits, all its rules are deleted. On startup, stale rules from any previous run are cleaned up automatically.
236
236
 
237
237
  **Where to read:**
238
238
  - `src/network-policy.ts` — `applyContainerIptables()`, `cleanupContainerIptables()`
@@ -255,7 +255,7 @@ Each group has its own IPC directory at `data/ipc/{agentFolder}/`. Agents can on
255
255
  Each container only gets the skills and tools listed in `agent-credentials.yaml`. See [Section 7](#7-tools-and-skills).
256
256
 
257
257
  ### Worktrees
258
- When an agent needs to modify code (e.g. argus-deps raising a PR), it doesn't work on your live checkout. NanoClaw creates a git worktree — a separate clone of the repo — at `data/worktrees/{agentFolder}/repo/`. This is mounted read-write into the container while the actual repo stays untouched.
258
+ When an agent needs to modify code (e.g. an agent raising a PR), it doesn't work on your live checkout. NanoClaw creates a git worktree — a separate clone of the repo — at `data/worktrees/{agentFolder}/repo/`. This is mounted read-write into the container while the actual repo stays untouched.
259
259
 
260
260
  **Where to read:**
261
261
  - `src/worktree.ts` — worktree creation/management
@@ -279,15 +279,15 @@ common:
279
279
  tools: [] # no tools by default
280
280
 
281
281
  agents:
282
- argus-alert:
282
+ alert-agent:
283
283
  skills: [] # adds nothing extra
284
- tools: [elastic_query.py, jira_tool.py] # but gets these tools
285
- global-claw:
284
+ tools: [my_tool.py] # gets this tool
285
+ meta-agent:
286
286
  skills: [agent-browser, agent-status, edit-agent] # dangerous skills
287
- tools: [elastic_query.py, jira_tool.py, ...] # all tools
287
+ tools: [my_tool.py, other_tool.py] # all tools
288
288
  ```
289
289
 
290
- **Dangerous skills** (`edit-agent`, `agent-browser`, `agent-status`) are NOT in the common layer. Only `global-claw` has them by explicit opt-in.
290
+ **Dangerous skills** (`edit-agent`, `agent-browser`, `agent-status`) are NOT in the common layer. Only agents that explicitly list them in `agent-credentials.yaml` get them typically just your main/meta agent.
291
291
 
292
292
  ### How It's Enforced
293
293
 
@@ -395,12 +395,12 @@ If `wakeAgent: false`, the task ends without calling Claude — useful for tasks
395
395
  ## 10. Agent Registration
396
396
 
397
397
  ### Automatic Registration on Startup
398
- NanoClaw reads `agents.yaml` on every startup and auto-registers any agent whose channel ID env var is set in `.env` but isn't in the DB yet. This means a fresh install only requires filling in `.env` and starting NanoClaw — no manual script needed.
398
+ IronClaws reads `agents.yaml` on every startup and auto-registers any agent whose channel ID env var is set in `.env` but isn't in the DB yet. A fresh install only requires filling in `.env` and starting IronClaws — no manual script needed.
399
399
 
400
400
  The `autoRegisterAgentsFromYaml()` function in `src/index.ts` handles this. It also runs `scripts/setup-onecli-secrets.sh` automatically when credentials change (detected via hash of relevant env vars).
401
401
 
402
402
  ### Dynamic Registration (Main Group)
403
- The `global-claw` agent (the meta-agent) can register new agents at runtime using the `register_group` MCP tool. Only the main group can do this — NanoClaw enforces this at the IPC processing level.
403
+ The main agent (`is_main: true` in `agents.yaml`) can register new agents at runtime using the `register_group` MCP tool. Only the main group can do this — IronClaws enforces this at the IPC processing level.
404
404
 
405
405
  ### What Registration Does
406
406
 
@@ -492,5 +492,5 @@ If you want to go deeper on a specific area:
492
492
  | Network security | `src/network-policy.ts` |
493
493
  | How agents talk back | `src/ipc.ts` + `container/agent-runner/src/ipc-mcp-stdio.ts` |
494
494
  | Scheduling | `src/task-scheduler.ts` |
495
- | What OneCLI does | `setup-agents.sh` + `node_modules/@onecli-sh/sdk/lib/index.js` |
495
+ | What OneCLI does | `docker-compose.yml` + `node_modules/@onecli-sh/sdk/lib/index.js` |
496
496
  | Security model end-to-end | This doc → `src/mount-security.ts` → `src/network-policy.ts` |
@@ -63,7 +63,7 @@ Tone, format, constraints.
63
63
  ```yaml
64
64
  my-agent:
65
65
  skills: []
66
- tools: [jira_tool.py] # tools from container/tools/
66
+ tools: [my_tool.py] # tools from container/tools/
67
67
  config:
68
68
  - SOME_API_URL
69
69
  ```
@@ -72,16 +72,20 @@ Tone, format, constraints.
72
72
 
73
73
  Agents never see raw API keys. OneCLI (the HTTPS proxy) intercepts outbound requests and injects Authorization headers. `onecli_secrets` in `agents.yaml` controls which credentials flow to which agent. Run `bash scripts/setup-onecli-secrets.sh` to register new credentials — this runs automatically on startup when credentials change.
74
74
 
75
- ### Available tools
75
+ ### Tools
76
76
 
77
- | Tool | What it does |
78
- |------|-------------|
79
- | `jira_tool.py` | Jira CRUD — get, search, create, update, comment |
80
- | `elastic_query.py` | Query Kibana/Elasticsearch |
81
- | `slack_history_tool.py` | Read Slack channel history |
82
- | `gdrive_tool.py` | Read Google Drive files |
77
+ There are no default tools tools are specific to each deployment. To add one:
83
78
 
84
- Add tools to an agent via `agent-credentials.yaml` `tools:`.
79
+ 1. Write a Python script and drop it in `container/tools/my_tool.py`
80
+ 2. Rebuild the image: `cd container && ./build-argus.sh`
81
+ 3. Grant it to the agent in `agent-credentials.yaml`:
82
+ ```yaml
83
+ agents:
84
+ my-agent:
85
+ tools: [my_tool.py]
86
+ ```
87
+
88
+ **Tool design:** output JSON to stdout, errors to stderr, exit non-zero on failure. Auth goes through the OneCLI proxy — don't put credentials in tools. See `container/tools/README.md`.
85
89
 
86
90
  ---
87
91