brainiac 0.4.2 → 0.4.4
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.
- checksums.yaml +4 -4
- data/README.md +124 -40
- data/bin/brainiac +111 -27
- data/docs/waybar-config.md +13 -0
- data/lib/brainiac/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 16f7d64457f92c95cf53466c9d91b14e5011ee8bebe111f0c10eeaba39d26813
|
|
4
|
+
data.tar.gz: 5372f10fed375a774eb62eda8b8c22c80df416b9358b13fc2e1348af966b5bf6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7f32967505e0de3e6feb98f3b53707fb64272ce2a02deebe0eb60b74fade6896aa1522359db145dc10b94a08ed5d5e79689ebd70f9f26f8b9853b4a57e97e792
|
|
7
|
+
data.tar.gz: 7dc2927f465ed0998f1fc264946375d1f85ce250c4e3bb05fd048452c3002f9a7b48b25f1033e761de81595b8ab71d3b05b8f7dde6aa32d01e7e04a24a8d4c09
|
data/README.md
CHANGED
|
@@ -90,7 +90,7 @@ Any agent can be tagged on any card. If Merlin is working card #42 and someone c
|
|
|
90
90
|
|
|
91
91
|
#### Display Name Accuracy
|
|
92
92
|
|
|
93
|
-
Agents need to spell @mentions exactly
|
|
93
|
+
Agents need to spell @mentions exactly (e.g. `@Robin` not `@robin`). The agent registry's `display_name` field handles this — every prompt includes an agent roster with the correct spelling:
|
|
94
94
|
|
|
95
95
|
```
|
|
96
96
|
## Agent Roster
|
|
@@ -100,7 +100,7 @@ When @mentioning other agents in Fizzy comments, use the EXACT spelling below.
|
|
|
100
100
|
- @Merlin
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
Detection is case-insensitive (inbound `@robin` still matches Robin), but outbound mentions use the exact `
|
|
103
|
+
Detection is case-insensitive (inbound `@robin` still matches Robin), but outbound mentions use the exact `display_name` from the registry.
|
|
104
104
|
|
|
105
105
|
#### Agent-to-Agent Loop Prevention
|
|
106
106
|
|
|
@@ -162,25 +162,73 @@ This installs the `brainiac` binary to your gem bin path (just like `rails`, `rs
|
|
|
162
162
|
|
|
163
163
|
### Quick Start (New Machine)
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
From zero to an agent you can @mention in Discord:
|
|
166
166
|
|
|
167
167
|
```bash
|
|
168
|
-
brainiac
|
|
168
|
+
gem install brainiac
|
|
169
|
+
brainiac setup # ~/.brainiac/ dirs, example configs, CLI providers
|
|
170
|
+
brainiac install discord # plus any of: fizzy, github, zoho, basecamp
|
|
171
|
+
cd ~/Code/my-app && brainiac register
|
|
172
|
+
brainiac server --daemon
|
|
173
|
+
|
|
174
|
+
brainiac agent create Quill --local --avatar ~/quill.png --icon 🪶
|
|
169
175
|
```
|
|
170
176
|
|
|
171
|
-
|
|
177
|
+
`agent create` walks you through the rest: it opens `$EDITOR` for the agent's persona, asks for a role, then lets each installed plugin set up its part (for Discord that's one pasted bot token). The bot comes online without a restart. See [Adding an Agent](#adding-an-agent) for what each step does. (If you gave `brainiac setup` a first agent name, finish that agent with `brainiac agent setup <key>` instead.)
|
|
178
|
+
|
|
179
|
+
Make sure the [prerequisites](#prerequisites) are installed first, at least Ruby, an agent CLI, and qmd.
|
|
180
|
+
|
|
181
|
+
Each plugin also has its own setup/config commands (e.g. `brainiac discord default <project>`, `brainiac github setup`) and README.
|
|
182
|
+
|
|
183
|
+
### Adding an Agent
|
|
172
184
|
|
|
173
|
-
|
|
185
|
+
One command creates everything an agent needs:
|
|
174
186
|
|
|
175
187
|
```bash
|
|
176
|
-
brainiac
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
188
|
+
brainiac agent create "Judge Dredd" --local \
|
|
189
|
+
--avatar ~/dredd.png --icon ⚖️ \
|
|
190
|
+
--description-file ~/dredd-style.md \
|
|
191
|
+
--role-file ~/law-specialist.md
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Names.** Type the name the way people should see it, quoted if it has spaces. `Judge Dredd` is the display name (Discord username, Fizzy/Basecamp name, @mentions). `judge-dredd` is the key (agents.json, `persona/judge-dredd/`, `memory/judge-dredd/`, `brainiac agent setup judge-dredd`).
|
|
195
|
+
|
|
196
|
+
**What core writes**
|
|
197
|
+
|
|
198
|
+
| Input | Flag | Ends up in | If you leave it out |
|
|
199
|
+
|-------|------|------------|---------------------|
|
|
200
|
+
| Persona (how they talk) | `--description-file f`, `--description "text"`, `--description @f`, `--description -` | `brain/persona/<key>/style.md` | `$EDITOR` opens |
|
|
201
|
+
| Role (what they do) | `--role-file f.md` or `--role <existing>` (repeatable) | `roles/<name>.md`, `role` in agents.json | Pick existing roles by number, `n` for a new one in `$EDITOR`, blank to skip |
|
|
202
|
+
| Avatar | `--avatar pic.png` | `brain/persona/<key>/avatar.png` | Plugins skip the picture |
|
|
203
|
+
| Status bar icon | `--icon 🪶` | `waybar.json` (Omarchy bar, waybar, xbar) | Asked for an emoji |
|
|
204
|
+
| Email | `--email a@b.com` | agents.json `email` | `agent_email_template` in `brainiac.json`, e.g. `"agent+{key}@example.com"` |
|
|
205
|
+
| Local dispatch | `--local` | agents.json `local: true` | Agent is known but won't pick up work on this machine |
|
|
206
|
+
|
|
207
|
+
A `--role-file` keeps its file name: `law-specialist.md` becomes the `law-specialist` role, so the same file can be passed for several agents. Pass `--role <new-name>` to name it something else. If your persona or role file already has YAML frontmatter it's kept as-is.
|
|
208
|
+
|
|
209
|
+
**What the plugins do** (each installed plugin implements `on_agent_created`)
|
|
210
|
+
|
|
211
|
+
| Plugin | Automated | You do |
|
|
212
|
+
|--------|-----------|--------|
|
|
213
|
+
| discord | Bot username, avatar, app icon and description, Message Content intent, token saved to agents.json, `user_mappings`, invite link opened | Create the application in the developer portal (opened for you) and paste the bot token |
|
|
214
|
+
| fizzy | Name, avatar, `authorized_users`, `FIZZY_TOKEN` | Open the printed join link in a **private window**, sign up as the agent's email, create an access token and paste it |
|
|
215
|
+
| basecamp | Finds the person by name, or invites them by email after a confirm prompt; adds them to every mapped project, `bot_accounts` entry | Nothing |
|
|
216
|
+
|
|
217
|
+
Before each plugin runs you're asked `Set up basecamp for Judge Dredd? [Y/n]`. Answer up front with `--skip basecamp` or `--only discord,fizzy`; skips are saved on the agent. `--no-browser` (or `BRAINIAC_NO_BROWSER=1`) prints links instead of opening them.
|
|
218
|
+
|
|
219
|
+
**Finishing or changing an agent later**
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
brainiac agent setup judge-dredd # re-run every plugin; finished steps are skipped
|
|
223
|
+
brainiac agent setup judge-dredd --only fizzy # just one plugin (also un-skips it)
|
|
224
|
+
brainiac agent setup judge-dredd --icon ⚖️ --only none # change the icon, no plugin steps
|
|
225
|
+
brainiac agent setup judge-dredd --role-file ~/r.md # add a role
|
|
226
|
+
brainiac agent remove judge-dredd # remove from the registry and bars
|
|
181
227
|
```
|
|
182
228
|
|
|
183
|
-
|
|
229
|
+
`agent setup` also asks for a role or icon if the agent doesn't have one yet. With the server running, a new or changed token is picked up without a restart.
|
|
230
|
+
|
|
231
|
+
Writing a plugin that should take part in this? See "Agent Onboarding (`on_agent_created`)" in [skills/brainiac-plugins/SKILL.md](skills/brainiac-plugins/SKILL.md). `brainiac plugin new` scaffolds the hook for you.
|
|
184
232
|
|
|
185
233
|
### Prerequisites
|
|
186
234
|
|
|
@@ -203,13 +251,16 @@ After setup, `~/.brainiac/` looks like:
|
|
|
203
251
|
```
|
|
204
252
|
~/.brainiac/
|
|
205
253
|
├── brainiac.json # Core config (default_agent, default_cli_provider)
|
|
206
|
-
├── agents.json # Agent registry (
|
|
254
|
+
├── agents.json # Agent registry (display names, tokens, role, local flag)
|
|
207
255
|
├── projects.json # Registered projects
|
|
208
256
|
├── users.json # Cross-platform user identity registry
|
|
209
257
|
├── plugins.json # Installed plugins
|
|
258
|
+
├── waybar.json # Status bar icons/colors per agent (Omarchy bar, waybar, xbar)
|
|
259
|
+
├── roles/ # Role definitions (<name>.md), assigned via agents.json "role"
|
|
260
|
+
├── cli-providers/ # One JSON per agent CLI (kiro, claude, codex, ...)
|
|
210
261
|
├── brain/
|
|
211
262
|
│ ├── knowledge/ # Shared technical knowledge (all agents)
|
|
212
|
-
│ ├── persona/ # Per-agent personality files
|
|
263
|
+
│ ├── persona/ # Per-agent personality files (style.md, avatar)
|
|
213
264
|
│ └── memory/ # Per-agent session memory
|
|
214
265
|
├── handlers/ # Legacy custom webhook handlers
|
|
215
266
|
├── plans/ # Planning mode output
|
|
@@ -222,12 +273,12 @@ Plugins add their own config files when installed (e.g. `discord.json`, `fizzy.j
|
|
|
222
273
|
|
|
223
274
|
#### 1. Agent Registry (`~/.brainiac/agents.json`)
|
|
224
275
|
|
|
225
|
-
Maps agents to their identity and environment. Every agent that should dispatch on this machine needs an entry here with `"local": true
|
|
276
|
+
Maps agents to their identity and environment. Every agent that should dispatch on this machine needs an entry here with `"local": true`. `brainiac agent create` writes these entries for you (see [Adding an Agent](#adding-an-agent)); this is what one looks like:
|
|
226
277
|
|
|
227
278
|
```json
|
|
228
279
|
{
|
|
229
280
|
"sherlock": {
|
|
230
|
-
"
|
|
281
|
+
"display_name": "Sherlock",
|
|
231
282
|
"local": true,
|
|
232
283
|
"env": {
|
|
233
284
|
"FIZZY_TOKEN": "fizzy_abc...",
|
|
@@ -389,6 +440,8 @@ Both machines receive the same webhooks. The agent registry (`~/.brainiac/agents
|
|
|
389
440
|
|
|
390
441
|
### Step 1: Agent Registry
|
|
391
442
|
|
|
443
|
+
`brainiac agent create` writes the entry, persona, role and plugin tokens for you (see [Adding an Agent](#adding-an-agent)). The rest of this section explains what it produces, in case you want to edit it by hand.
|
|
444
|
+
|
|
392
445
|
The agent registry at `~/.brainiac/agents.json` is the authority for agent identity. This serves four purposes:
|
|
393
446
|
|
|
394
447
|
1. **Per-agent environment variables** — any env var can be set per-agent via the `env` hash (e.g. `FIZZY_TOKEN`, `DISCORD_BOT_TOKEN`, custom vars)
|
|
@@ -399,7 +452,7 @@ The agent registry at `~/.brainiac/agents.json` is the authority for agent ident
|
|
|
399
452
|
```json
|
|
400
453
|
{
|
|
401
454
|
"sherlock": {
|
|
402
|
-
"
|
|
455
|
+
"display_name": "Sherlock",
|
|
403
456
|
"local": true,
|
|
404
457
|
"env": {
|
|
405
458
|
"FIZZY_TOKEN": "fizzy_abc...",
|
|
@@ -407,19 +460,19 @@ The agent registry at `~/.brainiac/agents.json` is the authority for agent ident
|
|
|
407
460
|
}
|
|
408
461
|
},
|
|
409
462
|
"robin": {
|
|
410
|
-
"
|
|
463
|
+
"display_name": "Robin",
|
|
411
464
|
"env": {
|
|
412
465
|
"FIZZY_TOKEN": "fizzy_xyz...",
|
|
413
466
|
"DISCORD_BOT_TOKEN": "Bot_xyz..."
|
|
414
467
|
}
|
|
415
468
|
},
|
|
416
469
|
"merlin": {
|
|
417
|
-
"
|
|
470
|
+
"display_name": "Merlin"
|
|
418
471
|
}
|
|
419
472
|
}
|
|
420
473
|
```
|
|
421
474
|
|
|
422
|
-
Keys are lowercase lookup keys (normalized: non-alphanumeric chars become hyphens). `
|
|
475
|
+
Keys are lowercase lookup keys (normalized: non-alphanumeric chars become hyphens). `display_name` is the exact name used for @mentions and on every platform (Discord, Fizzy, Basecamp). The `env` hash is injected into the spawned agent process — every key/value pair becomes an environment variable.
|
|
423
476
|
|
|
424
477
|
The `local` flag controls which agents pick up card assignments on this machine. Agents without `"local": true` are still known for mention detection, display names, tokens, and cross-agent interactions — they just won't pick up card assignments. The default agent (from `AI_AGENT_NAME` or `brainiac.json`) is always considered local.
|
|
425
478
|
|
|
@@ -427,13 +480,13 @@ Agents without an `env` block (like Merlin above on a Linux box) still appear in
|
|
|
427
480
|
|
|
428
481
|
The registry reloads on every webhook and via `POST /api/reload`.
|
|
429
482
|
|
|
430
|
-
### Step
|
|
483
|
+
### Step 2: Seed Agent Persona and Knowledge
|
|
431
484
|
|
|
432
485
|
Agents get their personality from persona files and their technical context from knowledge files. These live in the brain directory and are indexed by qmd for semantic search.
|
|
433
486
|
|
|
434
487
|
#### Persona
|
|
435
488
|
|
|
436
|
-
Each agent needs at least one persona file.
|
|
489
|
+
Each agent needs at least one persona file. `brainiac agent create` writes `style.md` from `--description-file` or `$EDITOR`. To create one by hand:
|
|
437
490
|
|
|
438
491
|
```bash
|
|
439
492
|
# Create persona file for your agent
|
|
@@ -471,7 +524,7 @@ qmd update
|
|
|
471
524
|
|
|
472
525
|
Agents also update knowledge themselves during sessions (when they learn something significant), but seeding it with your project's conventions and tool docs gives them a head start.
|
|
473
526
|
|
|
474
|
-
### Step
|
|
527
|
+
### Step 3: Initialize Each Agent's Brain
|
|
475
528
|
|
|
476
529
|
```bash
|
|
477
530
|
brainiac brain init # Default agent (from brainiac.json or AI_AGENT_NAME)
|
|
@@ -479,7 +532,7 @@ brainiac brain init SecurityBot # Additional agent
|
|
|
479
532
|
brainiac brain list # Verify all agents
|
|
480
533
|
```
|
|
481
534
|
|
|
482
|
-
This creates the directory structure, sets up qmd collections, and indexes everything. Run this after you've placed your persona and knowledge files.
|
|
535
|
+
This creates the directory structure, sets up qmd collections, and indexes everything. Run this after you've placed your persona and knowledge files (`agent create --local` already does it for the new agent).
|
|
483
536
|
|
|
484
537
|
### How Dispatch Works
|
|
485
538
|
|
|
@@ -559,6 +612,8 @@ React with ❌ to any message that triggered an agent to immediately terminate t
|
|
|
559
612
|
|
|
560
613
|
### Setup
|
|
561
614
|
|
|
615
|
+
**For a new agent, use `brainiac agent create` (or `brainiac agent setup <key> --only discord` for an existing one).** It covers steps 1-3 below: it opens the developer portal, takes the pasted token, sets the bot's name, avatar and Message Content intent, and opens the invite link. The manual steps are here for reference.
|
|
616
|
+
|
|
562
617
|
#### Step 1: Create Discord Applications
|
|
563
618
|
|
|
564
619
|
Create one Discord application per agent at https://discord.com/developers/applications:
|
|
@@ -588,7 +643,7 @@ brainiac discord token robin "BOT_TOKEN_FOR_ROBIN"
|
|
|
588
643
|
This adds `DISCORD_BOT_TOKEN` to the agent's `env` hash in `~/.brainiac/agents.json`. You can verify with:
|
|
589
644
|
|
|
590
645
|
```bash
|
|
591
|
-
brainiac
|
|
646
|
+
brainiac agent <name> show
|
|
592
647
|
```
|
|
593
648
|
|
|
594
649
|
#### Step 3: Invite Bots to Your Server
|
|
@@ -597,18 +652,22 @@ Go to the "OAuth2" tab for each application:
|
|
|
597
652
|
|
|
598
653
|
1. Under "OAuth2 URL Generator", check the **bot** scope
|
|
599
654
|
2. Under "Bot Permissions", select:
|
|
655
|
+
- View Channels
|
|
600
656
|
- Send Messages
|
|
657
|
+
- Embed Links
|
|
658
|
+
- Attach Files
|
|
659
|
+
- Read Message History
|
|
660
|
+
- Add Reactions
|
|
601
661
|
- Create Public Threads
|
|
602
662
|
- Send Messages in Threads
|
|
603
|
-
-
|
|
604
|
-
- Read Message History
|
|
663
|
+
- Manage Threads
|
|
605
664
|
3. Copy the generated URL and open it in your browser
|
|
606
665
|
4. Select your server and authorize
|
|
607
666
|
|
|
608
|
-
The permission integer for these permissions is `
|
|
667
|
+
The permission integer for these permissions is `326417632320`. You can also construct the invite URL manually:
|
|
609
668
|
|
|
610
669
|
```
|
|
611
|
-
https://discord.com/oauth2/authorize?client_id=YOUR_APP_ID&scope=bot&permissions=
|
|
670
|
+
https://discord.com/oauth2/authorize?client_id=YOUR_APP_ID&scope=bot&permissions=326417632320
|
|
612
671
|
```
|
|
613
672
|
|
|
614
673
|
Replace `YOUR_APP_ID` with the Application ID from the "General Information" tab. Repeat for each agent bot.
|
|
@@ -709,7 +768,7 @@ Leave `authorized_role_ids` and `authorized_user_ids` empty to allow everyone in
|
|
|
709
768
|
|
|
710
769
|
```bash
|
|
711
770
|
brainiac discord token <agent> <token> # Set Discord bot token for an agent
|
|
712
|
-
brainiac discord
|
|
771
|
+
brainiac discord owner <user-id> # Set the owner's Discord user ID
|
|
713
772
|
brainiac discord default <project> # Set default project for all channels
|
|
714
773
|
brainiac discord map <channel-id> <project> # Override for a specific channel
|
|
715
774
|
brainiac discord config # Show current Discord config
|
|
@@ -932,6 +991,9 @@ Configure how agents appear in the status bar via `~/.brainiac/waybar.json`:
|
|
|
932
991
|
}
|
|
933
992
|
```
|
|
934
993
|
|
|
994
|
+
`brainiac agent create` asks for each new agent's icon (or pass `--icon ⚖️`).
|
|
995
|
+
Change one later with `brainiac agent setup <name> --icon <emoji>`.
|
|
996
|
+
|
|
935
997
|
### macOS (xbar)
|
|
936
998
|
|
|
937
999
|
Requires [xbar](https://xbarapp.com) (free, formerly BitBar).
|
|
@@ -1121,8 +1183,8 @@ Brainiac supports a plugin system that lets you extend functionality via Ruby ge
|
|
|
1121
1183
|
### Installing Plugins
|
|
1122
1184
|
|
|
1123
1185
|
```bash
|
|
1124
|
-
brainiac install
|
|
1125
|
-
brainiac install
|
|
1186
|
+
brainiac install discord # Installs brainiac-discord gem + registers it
|
|
1187
|
+
brainiac install fizzy # Installs brainiac-fizzy gem + registers it
|
|
1126
1188
|
brainiac restart # Restart server to load new plugins
|
|
1127
1189
|
```
|
|
1128
1190
|
|
|
@@ -1131,7 +1193,7 @@ This runs `gem install brainiac-<name>`, adds the plugin to `~/.brainiac/plugins
|
|
|
1131
1193
|
You can also install a specific version:
|
|
1132
1194
|
|
|
1133
1195
|
```bash
|
|
1134
|
-
brainiac install
|
|
1196
|
+
brainiac install discord --version 0.0.25
|
|
1135
1197
|
```
|
|
1136
1198
|
|
|
1137
1199
|
### Managing Plugins
|
|
@@ -1144,8 +1206,8 @@ brainiac uninstall <name> # Remove plugin from config (gem stays installed)
|
|
|
1144
1206
|
To fully remove the gem after uninstalling:
|
|
1145
1207
|
|
|
1146
1208
|
```bash
|
|
1147
|
-
brainiac uninstall
|
|
1148
|
-
gem uninstall brainiac-
|
|
1209
|
+
brainiac uninstall discord
|
|
1210
|
+
gem uninstall brainiac-discord
|
|
1149
1211
|
```
|
|
1150
1212
|
|
|
1151
1213
|
### Configuration
|
|
@@ -1155,7 +1217,7 @@ Installed plugins are tracked in `~/.brainiac/plugins.json`:
|
|
|
1155
1217
|
```json
|
|
1156
1218
|
{
|
|
1157
1219
|
"plugins": [
|
|
1158
|
-
{ "name": "
|
|
1220
|
+
{ "name": "discord", "gem": "brainiac-discord", "installed_at": "2026-06-30T14:00:00-04:00" }
|
|
1159
1221
|
]
|
|
1160
1222
|
}
|
|
1161
1223
|
```
|
|
@@ -1164,7 +1226,7 @@ At server startup, `load_plugins!` iterates this list, requires each gem, and ca
|
|
|
1164
1226
|
|
|
1165
1227
|
### Creating a Plugin
|
|
1166
1228
|
|
|
1167
|
-
Any Ruby gem named `brainiac-<name>` can be a Brainiac plugin. The gem must:
|
|
1229
|
+
Any Ruby gem named `brainiac-<name>` can be a Brainiac plugin. `brainiac plugin new <name>` generates a working skeleton (gemspec, module, CLI with an `on_agent_created` stub, tests, and a skill doc); the full contract is in [skills/brainiac-plugins/SKILL.md](skills/brainiac-plugins/SKILL.md). The gem must:
|
|
1168
1230
|
|
|
1169
1231
|
1. **Define a module** at `Brainiac::Plugins::<Name>`
|
|
1170
1232
|
2. **Implement `.register(app)`** — receives the Sinatra app instance for defining routes and starting threads
|
|
@@ -1219,7 +1281,8 @@ The `Brainiac::Plugins` namespace is defined in `lib/brainiac.rb`. Plugin module
|
|
|
1219
1281
|
| fizzy | `brainiac-fizzy` | Fizzy card management — assignment, comments, @mentions, cross-agent reviews, duplicate detection, planning mode |
|
|
1220
1282
|
| github | `brainiac-github` | GitHub webhooks — PR reviews, PR comments, PR merges, CI workflow notifications, deploy tracking |
|
|
1221
1283
|
| zoho | `brainiac-zoho` | Zoho Mail webhooks — rule-based email notifications, AI triage, OAuth for content fetching |
|
|
1222
|
-
|
|
|
1284
|
+
| basecamp | `brainiac-basecamp` | Basecamp epic orchestration — card tables, review gates, epic branches |
|
|
1285
|
+
| featureparity | `brainiac-featureparity` | FeatureParity integration for Brainiac agents |
|
|
1223
1286
|
|
|
1224
1287
|
### Backward Compatibility
|
|
1225
1288
|
|
|
@@ -1272,10 +1335,31 @@ brainiac brain search --persona <query> # Search agent persona
|
|
|
1272
1335
|
brainiac brain list # List everything
|
|
1273
1336
|
```
|
|
1274
1337
|
|
|
1338
|
+
### Agents
|
|
1339
|
+
|
|
1340
|
+
```bash
|
|
1341
|
+
brainiac agent create <name> [flags] # New agent + persona + role + plugin setup (see Adding an Agent)
|
|
1342
|
+
brainiac agent setup <name> [flags] # Finish/re-run plugin setup; change icon, avatar, email, role
|
|
1343
|
+
brainiac agent remove <name> # Remove from the registry
|
|
1344
|
+
brainiac agent list # List agents
|
|
1345
|
+
brainiac agent <name> show # Show config (tokens redacted)
|
|
1346
|
+
brainiac agent <name> env <KEY> <VALUE> # Set an env var
|
|
1347
|
+
```
|
|
1348
|
+
|
|
1349
|
+
### Roles
|
|
1350
|
+
|
|
1351
|
+
```bash
|
|
1352
|
+
brainiac role list # Roles and who has them
|
|
1353
|
+
brainiac role show <name> # Print a role
|
|
1354
|
+
brainiac role create <name> [--from f] [--assign agent] # New role ($EDITOR on a template)
|
|
1355
|
+
brainiac role assign <agent> <role> # Add a role to an agent
|
|
1356
|
+
brainiac role unassign <agent> <role> # Remove it
|
|
1357
|
+
```
|
|
1358
|
+
|
|
1275
1359
|
### Plugins
|
|
1276
1360
|
|
|
1277
1361
|
```bash
|
|
1278
|
-
brainiac install <name> # Install a plugin gem (e.g.,
|
|
1362
|
+
brainiac install <name> # Install a plugin gem (e.g., discord)
|
|
1279
1363
|
brainiac install <name> --version 0.2.0 # Install specific version
|
|
1280
1364
|
brainiac uninstall <name> # Remove plugin from config
|
|
1281
1365
|
brainiac plugins # List installed plugins
|
|
@@ -1436,7 +1520,7 @@ ls brainiac receiver.rb lib/brainiac/*.rb lib/brainiac/handlers/*.rb | entr -r b
|
|
|
1436
1520
|
|
|
1437
1521
|
**Agent commenting as wrong user:** Check `~/.brainiac/agents.json` has the correct `FIZZY_TOKEN` in the agent's `env` hash. The env is injected into the spawned agent process — verify with `curl http://localhost:4567/api/agents` to see the roster.
|
|
1438
1522
|
|
|
1439
|
-
**Agent @mention not linking in Fizzy:** The `
|
|
1523
|
+
**Agent @mention not linking in Fizzy:** The `display_name` in `agents.json` must match the exact Fizzy account name (case-sensitive). Check `curl http://localhost:4567/api/agents` to see what the roster looks like.
|
|
1440
1524
|
|
|
1441
1525
|
**Agent-to-agent loop:** Shouldn't happen — dispatch depth is capped at 10 hops by default. Check `curl http://localhost:4567/api/dispatch-depth` to see current state. Adjust `AGENT_DISPATCH_MAX_DEPTH` in `lib/brainiac/sessions.rb` if needed.
|
|
1442
1526
|
|
data/bin/brainiac
CHANGED
|
@@ -374,6 +374,25 @@ def write_role_file(role_name, text, agent_name = nil)
|
|
|
374
374
|
file
|
|
375
375
|
end
|
|
376
376
|
|
|
377
|
+
# Role for --role-file: named after the first --role that doesn't exist yet,
|
|
378
|
+
# else the file's name (blog-writer.md → blog-writer), so one file can be
|
|
379
|
+
# reused across agents. Reusing an existing role is fine when the file is
|
|
380
|
+
# that role or has the same content; a different role by that name is an error.
|
|
381
|
+
# Returns [role_name, needs_write].
|
|
382
|
+
def role_from_file(role_file, requested_roles)
|
|
383
|
+
name = requested_roles.find { |r| !available_roles.include?(r) } || role_name_arg(File.basename(role_file, ".*"))
|
|
384
|
+
existing = File.join(BRAINIAC_DIR, "roles", "#{name}.md")
|
|
385
|
+
return [name, true] unless File.exist?(existing)
|
|
386
|
+
|
|
387
|
+
same = File.expand_path(existing) == role_file || File.read(existing).strip == File.read(role_file).strip ||
|
|
388
|
+
File.read(existing).include?(File.read(role_file).strip)
|
|
389
|
+
return [name, false] if same
|
|
390
|
+
|
|
391
|
+
puts "❌ A different role named '#{name}' already exists (#{existing})."
|
|
392
|
+
puts " Use --role #{name} to assign it as-is, or --role <new-name> to name the role from #{role_file}."
|
|
393
|
+
exit 1
|
|
394
|
+
end
|
|
395
|
+
|
|
377
396
|
# Add roles to a registry entry, keeping the string-or-array shape.
|
|
378
397
|
def assign_roles(entry, new_roles)
|
|
379
398
|
roles = (Array(entry["role"]) + new_roles).uniq
|
|
@@ -418,6 +437,48 @@ def prompt_for_agent_role(agent_key, display_name)
|
|
|
418
437
|
picked & existing
|
|
419
438
|
end
|
|
420
439
|
|
|
440
|
+
# Status bar icons (Omarchy bar, waybar, xbar) live in ~/.brainiac/waybar.json,
|
|
441
|
+
# keyed by display name (matched case-insensitively). Unlisted agents show ❓.
|
|
442
|
+
def bar_config_file
|
|
443
|
+
File.join(BRAINIAC_DIR, "waybar.json")
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
def read_bar_config
|
|
447
|
+
File.exist?(bar_config_file) ? JSON.parse(File.read(bar_config_file, encoding: "utf-8")) : {}
|
|
448
|
+
rescue JSON::ParserError
|
|
449
|
+
{}
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
def bar_icon(display_name)
|
|
453
|
+
(read_bar_config["agents"] || []).find { |a| a["name"].to_s.casecmp?(display_name) }&.dig("emoji")
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
# Add or update the agent's bar icon, keeping its color and the other agents.
|
|
457
|
+
# A nil icon removes the agent from the file.
|
|
458
|
+
def write_bar_icon(display_name, icon)
|
|
459
|
+
config = read_bar_config
|
|
460
|
+
agents = config["agents"] || []
|
|
461
|
+
existing = agents.find { |a| a["name"].to_s.casecmp?(display_name) }
|
|
462
|
+
if icon.nil?
|
|
463
|
+
agents.delete(existing)
|
|
464
|
+
elsif existing
|
|
465
|
+
existing["emoji"] = icon
|
|
466
|
+
else
|
|
467
|
+
agents << { "name" => display_name, "emoji" => icon }
|
|
468
|
+
end
|
|
469
|
+
config["agents"] = agents
|
|
470
|
+
config["default_emoji"] ||= "❓"
|
|
471
|
+
config["schema_version"] ||= "1.0"
|
|
472
|
+
config["last_updated"] = Time.now.iso8601
|
|
473
|
+
File.write(bar_config_file, "#{JSON.pretty_generate(config)}\n")
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
def prompt_for_bar_icon(display_name)
|
|
477
|
+
print "Status bar icon for #{display_name} (an emoji, blank to skip): "
|
|
478
|
+
icon = $stdin.gets.to_s.strip
|
|
479
|
+
icon.empty? ? nil : icon
|
|
480
|
+
end
|
|
481
|
+
|
|
421
482
|
# Payload handed to plugins' on_agent_created: the registry entry plus the
|
|
422
483
|
# setup inputs plugins need to provision accounts (avatar, description, email).
|
|
423
484
|
# "open_browser" tells plugins whether they may launch a browser for their
|
|
@@ -1495,10 +1556,14 @@ when "setup"
|
|
|
1495
1556
|
|
|
1496
1557
|
puts ""
|
|
1497
1558
|
puts "Next steps:"
|
|
1498
|
-
puts " 1.
|
|
1499
|
-
puts " 2.
|
|
1500
|
-
puts " 3.
|
|
1501
|
-
|
|
1559
|
+
puts " 1. Install plugins: brainiac install discord / fizzy / github / zoho / basecamp"
|
|
1560
|
+
puts " 2. Register projects: cd ~/Code/myproject && brainiac register"
|
|
1561
|
+
puts " 3. Start server: brainiac server --daemon"
|
|
1562
|
+
if agent_name
|
|
1563
|
+
puts " 4. Finish #{agent_name} (persona, role, icon, plugin accounts): brainiac agent setup #{existing_agents.first}"
|
|
1564
|
+
else
|
|
1565
|
+
puts " 4. Add an agent (persona, role, icon, plugin accounts): brainiac agent create <Name> --local"
|
|
1566
|
+
end
|
|
1502
1567
|
|
|
1503
1568
|
# Shell completion setup
|
|
1504
1569
|
puts ""
|
|
@@ -2543,13 +2608,15 @@ when "agent"
|
|
|
2543
2608
|
puts ""
|
|
2544
2609
|
puts "Options:"
|
|
2545
2610
|
puts " --avatar <path> Profile picture (png/jpg/gif/webp), used by plugins (Discord, Fizzy)"
|
|
2611
|
+
puts " --icon <emoji> Status bar icon (Omarchy bar, waybar, xbar), e.g. --icon ⚖️"
|
|
2546
2612
|
puts " --description <text> Persona description (\"-\" reads stdin, \"@file\" reads a file)"
|
|
2547
2613
|
puts " --description-file <path> Read the persona description from a file"
|
|
2548
2614
|
puts " --email <address> Email for the agent's accounts (default: agent_email_template)"
|
|
2549
2615
|
puts " --local Mark agent as local (dispatches on this machine)"
|
|
2550
2616
|
puts " --role <role> Assign a role (repeatable)"
|
|
2551
2617
|
puts " --role-file <path> Create a role from a markdown file and assign it"
|
|
2552
|
-
puts " (named after the
|
|
2618
|
+
puts " (named after the file, e.g. blog-writer.md → blog-writer,"
|
|
2619
|
+
puts " or after a new --role name; an identical role is reused)"
|
|
2553
2620
|
puts " --cli <provider> Set CLI provider (default: kiro)"
|
|
2554
2621
|
puts " --skip <plugins> Don't set up these plugins for this agent, e.g. --skip basecamp"
|
|
2555
2622
|
puts " --only <plugins> Set up just these plugins, e.g. --only discord,fizzy"
|
|
@@ -2557,7 +2624,8 @@ when "agent"
|
|
|
2557
2624
|
puts ""
|
|
2558
2625
|
puts "With no flags and a terminal, interactive mode is used. If no description is"
|
|
2559
2626
|
puts "given on a terminal, $EDITOR opens so you can write a full persona. Without"
|
|
2560
|
-
puts "--role/--role-file you're asked to pick an existing role or write a new one
|
|
2627
|
+
puts "--role/--role-file you're asked to pick an existing role or write a new one,"
|
|
2628
|
+
puts "and without --icon you're asked for a status bar emoji."
|
|
2561
2629
|
puts "After the brainiac files are written, each installed plugin sets up its part"
|
|
2562
2630
|
puts "(Discord bot, Fizzy user, Basecamp person), asking first unless --skip/--only"
|
|
2563
2631
|
puts "is given. Re-run with: brainiac agent setup <name>"
|
|
@@ -2567,8 +2635,8 @@ when "agent"
|
|
|
2567
2635
|
puts " brainiac agent create Quill --local --avatar quill.png --description @quill.md"
|
|
2568
2636
|
puts " brainiac agent create MyAgent # interactive"
|
|
2569
2637
|
puts " brainiac agent create SecurityBot --local --role code-reviewer"
|
|
2570
|
-
puts " brainiac agent create \"Judge Dredd\" --local --avatar dredd.png \\"
|
|
2571
|
-
puts " --description-file dredd-style.md --role-file
|
|
2638
|
+
puts " brainiac agent create \"Judge Dredd\" --local --avatar dredd.png --icon ⚖️ \\"
|
|
2639
|
+
puts " --description-file dredd-style.md --role-file law-specialist.md"
|
|
2572
2640
|
exit 1
|
|
2573
2641
|
end
|
|
2574
2642
|
|
|
@@ -2587,6 +2655,7 @@ when "agent"
|
|
|
2587
2655
|
cli_provider = nil
|
|
2588
2656
|
persona_text = nil
|
|
2589
2657
|
avatar = nil
|
|
2658
|
+
icon = nil
|
|
2590
2659
|
email = nil
|
|
2591
2660
|
skip_plugins = []
|
|
2592
2661
|
only_plugins = nil
|
|
@@ -2617,6 +2686,9 @@ when "agent"
|
|
|
2617
2686
|
when "--avatar"
|
|
2618
2687
|
ARGV.shift
|
|
2619
2688
|
avatar = ARGV.shift
|
|
2689
|
+
when "--icon"
|
|
2690
|
+
ARGV.shift
|
|
2691
|
+
icon = ARGV.shift.to_s.strip
|
|
2620
2692
|
when "--email"
|
|
2621
2693
|
ARGV.shift
|
|
2622
2694
|
email = ARGV.shift
|
|
@@ -2672,16 +2744,13 @@ when "agent"
|
|
|
2672
2744
|
exit 1
|
|
2673
2745
|
end
|
|
2674
2746
|
if role_file
|
|
2675
|
-
|
|
2676
|
-
new_role =
|
|
2677
|
-
|
|
2678
|
-
puts "❌ Role '#{new_role}' already exists. Pass --role <new-name> to name the role from #{role_file}."
|
|
2679
|
-
exit 1
|
|
2680
|
-
end
|
|
2681
|
-
roles |= [new_role]
|
|
2747
|
+
role_name, write_role = role_from_file(role_file, roles)
|
|
2748
|
+
new_role = role_name if write_role
|
|
2749
|
+
roles |= [role_name]
|
|
2682
2750
|
elsif roles.empty? && $stdin.tty?
|
|
2683
2751
|
roles = prompt_for_agent_role(agent_key, name)
|
|
2684
2752
|
end
|
|
2753
|
+
icon = prompt_for_bar_icon(name) if icon.nil? && $stdin.tty?
|
|
2685
2754
|
|
|
2686
2755
|
missing_roles = roles - available_roles - [new_role]
|
|
2687
2756
|
if missing_roles.any?
|
|
@@ -2708,7 +2777,7 @@ when "agent"
|
|
|
2708
2777
|
end
|
|
2709
2778
|
end
|
|
2710
2779
|
|
|
2711
|
-
puts "✓ Created role #{write_role_file(new_role, File.read(role_file)
|
|
2780
|
+
puts "✓ Created role #{write_role_file(new_role, File.read(role_file))}" if new_role
|
|
2712
2781
|
|
|
2713
2782
|
registry[agent_key] = entry
|
|
2714
2783
|
File.write(agent_registry_file, JSON.pretty_generate(registry))
|
|
@@ -2718,6 +2787,10 @@ when "agent"
|
|
|
2718
2787
|
puts " CLI: #{cli_provider}" if cli_provider
|
|
2719
2788
|
puts " Email: #{email}" if email
|
|
2720
2789
|
puts " Avatar: #{entry["avatar"]}" if entry["avatar"]
|
|
2790
|
+
if icon && !icon.empty?
|
|
2791
|
+
write_bar_icon(name, icon)
|
|
2792
|
+
puts " Bar icon: #{icon}"
|
|
2793
|
+
end
|
|
2721
2794
|
|
|
2722
2795
|
# Create persona directory and style file if requested
|
|
2723
2796
|
if persona_text
|
|
@@ -2772,16 +2845,18 @@ when "agent"
|
|
|
2772
2845
|
when "setup"
|
|
2773
2846
|
name = ARGV.shift
|
|
2774
2847
|
unless name
|
|
2775
|
-
puts "Usage: brainiac agent setup <name> [--avatar <path>] [--
|
|
2776
|
-
puts " [--skip <plugins>] [--only <plugins>] [--no-browser]"
|
|
2848
|
+
puts "Usage: brainiac agent setup <name> [--avatar <path>] [--icon <emoji>] [--email <address>] [--role <role>]"
|
|
2849
|
+
puts " [--role-file <path>] [--skip <plugins>] [--only <plugins>] [--no-browser]"
|
|
2777
2850
|
puts ""
|
|
2778
2851
|
puts "Re-runs every plugin's agent setup (Discord bot, Fizzy user, Basecamp person)."
|
|
2779
2852
|
puts "Steps that are already done are skipped, so it's safe to run after an"
|
|
2780
2853
|
puts "interrupted 'agent create' or to set up a newly installed plugin."
|
|
2781
|
-
puts "An agent without a role is asked to pick or write one
|
|
2854
|
+
puts "An agent without a role is asked to pick or write one, and one without a"
|
|
2855
|
+
puts "status bar icon is asked for an emoji."
|
|
2782
2856
|
puts ""
|
|
2857
|
+
puts " --icon e Set the status bar icon (Omarchy bar, waybar, xbar)"
|
|
2783
2858
|
puts " --role r Assign an existing role"
|
|
2784
|
-
puts " --role-file f Create a role from a markdown file (named after the
|
|
2859
|
+
puts " --role-file f Create a role from a markdown file (named after the file) and assign it"
|
|
2785
2860
|
puts " --skip a,b Never set up these plugins for this agent (saved)"
|
|
2786
2861
|
puts " --only a,b Run just these plugins (also un-skips them)"
|
|
2787
2862
|
puts " --no-browser Print links instead of opening them"
|
|
@@ -2800,8 +2875,11 @@ when "agent"
|
|
|
2800
2875
|
open_browser = true
|
|
2801
2876
|
new_roles = []
|
|
2802
2877
|
role_file = nil
|
|
2878
|
+
icon = nil
|
|
2803
2879
|
while ARGV.any?
|
|
2804
2880
|
case ARGV.shift
|
|
2881
|
+
when "--icon"
|
|
2882
|
+
icon = ARGV.shift.to_s.strip
|
|
2805
2883
|
when "--role"
|
|
2806
2884
|
new_roles << role_name_arg(ARGV.shift)
|
|
2807
2885
|
when "--role-file"
|
|
@@ -2838,12 +2916,8 @@ when "agent"
|
|
|
2838
2916
|
|
|
2839
2917
|
display = entry["display_name"] || name
|
|
2840
2918
|
if role_file
|
|
2841
|
-
role_name = (new_roles
|
|
2842
|
-
|
|
2843
|
-
puts "❌ Role '#{role_name}' already exists. Pass --role <new-name> to name the role from #{role_file}."
|
|
2844
|
-
exit 1
|
|
2845
|
-
end
|
|
2846
|
-
puts "✓ Created role #{write_role_file(role_name, File.read(role_file), display)}"
|
|
2919
|
+
role_name, write_role = role_from_file(role_file, new_roles)
|
|
2920
|
+
puts "✓ Created role #{write_role_file(role_name, File.read(role_file))}" if write_role
|
|
2847
2921
|
new_roles |= [role_name]
|
|
2848
2922
|
elsif new_roles.empty? && entry["role"].nil? && $stdin.tty?
|
|
2849
2923
|
new_roles = prompt_for_agent_role(agent_key, display)
|
|
@@ -2855,6 +2929,12 @@ when "agent"
|
|
|
2855
2929
|
end
|
|
2856
2930
|
puts "✓ Role: #{assign_roles(entry, new_roles).join(", ")}" if new_roles.any?
|
|
2857
2931
|
|
|
2932
|
+
icon = prompt_for_bar_icon(display) if icon.nil? && bar_icon(display).nil? && $stdin.tty?
|
|
2933
|
+
if icon && !icon.empty?
|
|
2934
|
+
write_bar_icon(display, icon)
|
|
2935
|
+
puts "✓ Bar icon: #{icon}"
|
|
2936
|
+
end
|
|
2937
|
+
|
|
2858
2938
|
registry[agent_key] = entry
|
|
2859
2939
|
File.write(agent_registry_file, JSON.pretty_generate(registry))
|
|
2860
2940
|
|
|
@@ -2883,6 +2963,7 @@ when "agent"
|
|
|
2883
2963
|
File.write(agent_registry_file, JSON.pretty_generate(registry))
|
|
2884
2964
|
puts "✓ Removed agent '#{display}' (#{agent_key}) from registry"
|
|
2885
2965
|
puts " Note: Persona files at ~/.brainiac/brain/persona/#{agent_key}/ were not deleted."
|
|
2966
|
+
write_bar_icon(display, nil) if bar_icon(display)
|
|
2886
2967
|
|
|
2887
2968
|
# Let plugins clean up their config
|
|
2888
2969
|
notify_plugins_agent_removed(agent_key, display)
|
|
@@ -4543,7 +4624,7 @@ when "help", "--help", "-h", nil
|
|
|
4543
4624
|
Brainiac CLI - Manage projects with Brainiac server
|
|
4544
4625
|
|
|
4545
4626
|
Usage:
|
|
4546
|
-
brainiac setup Bootstrap a new machine (
|
|
4627
|
+
brainiac setup Bootstrap a new machine (dirs, example configs, CLI providers)
|
|
4547
4628
|
brainiac server [options] Start the Brainiac webhook server (foreground)
|
|
4548
4629
|
brainiac start [options] Alias for 'brainiac server'
|
|
4549
4630
|
brainiac stop Stop the running server
|
|
@@ -4618,6 +4699,9 @@ when "help", "--help", "-h", nil
|
|
|
4618
4699
|
role unassign <agent> <role> Remove a role from an agent
|
|
4619
4700
|
|
|
4620
4701
|
Agent Commands:
|
|
4702
|
+
agent create <name> [options] Add an agent: persona, role, icon, plugin accounts
|
|
4703
|
+
agent setup <name> [options] Finish or re-run plugin setup (skips what's done)
|
|
4704
|
+
agent remove <name> Remove an agent from the registry
|
|
4621
4705
|
agent list List all agents in the registry
|
|
4622
4706
|
agent <name> show Show agent configuration (tokens redacted)
|
|
4623
4707
|
agent <name> env <KEY> <VALUE> Set an env var for an agent
|
data/docs/waybar-config.md
CHANGED
|
@@ -30,6 +30,19 @@ This file configures how agents appear in the status bar — waybar on Linux, xb
|
|
|
30
30
|
}
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
## Setting an agent's icon
|
|
34
|
+
|
|
35
|
+
You don't need to edit this file by hand. `brainiac agent create` asks for an
|
|
36
|
+
icon (or takes `--icon`), and `brainiac agent setup` asks for one if the agent
|
|
37
|
+
has none. To change one later:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
brainiac agent setup "Judge Dredd" --icon ⚖️
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The Omarchy bar plugin, waybar and xbar all read this file, so one entry covers
|
|
44
|
+
every bar. Agents without an entry show `default_emoji`.
|
|
45
|
+
|
|
33
46
|
## Fields
|
|
34
47
|
|
|
35
48
|
- **name**: Agent name (must match agent registry)
|
data/lib/brainiac/version.rb
CHANGED