@statechange/council 0.1.0 → 0.3.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.
Files changed (137) hide show
  1. package/README.md +126 -95
  2. package/dist/cli.js +15 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/gui.d.ts +1 -0
  5. package/dist/commands/gui.js +63 -0
  6. package/dist/commands/gui.js.map +1 -0
  7. package/dist/commands/install.d.ts +5 -0
  8. package/dist/commands/install.js +131 -0
  9. package/dist/commands/install.js.map +1 -0
  10. package/dist-electron/index-B7VRloBj.js +1293 -0
  11. package/dist-electron/index-C03cLUYg.js +5911 -0
  12. package/dist-electron/index-Dw6I25AL.js +5911 -0
  13. package/dist-electron/index-NMn1koXq.js +31737 -0
  14. package/dist-electron/index-zpksia2X.js +5911 -0
  15. package/dist-electron/main-C_og2Wvn.js +32969 -0
  16. package/dist-electron/main-DBohq-SO.js +32969 -0
  17. package/dist-electron/main.js +791 -1217
  18. package/dist-electron/multipart-parser-Bdb1JOpV.js +353 -0
  19. package/dist-electron/multipart-parser-Cc_drctG.js +353 -0
  20. package/dist-electron/multipart-parser-Do9VIIY5.js +353 -0
  21. package/dist-electron/preload.mjs +1 -0
  22. package/dist-renderer/assets/Tableau10-B-NsZVaP.js +1 -0
  23. package/dist-renderer/assets/_commonjs-dynamic-modules-TDtrdbi3.js +1 -0
  24. package/dist-renderer/assets/ar-SA-G6X2FPQ2-CNUtTBRd.js +10 -0
  25. package/dist-renderer/assets/arc-BsV2XMg-.js +1 -0
  26. package/dist-renderer/assets/array-BKyUJesY.js +1 -0
  27. package/dist-renderer/assets/az-AZ-76LH7QW2-BU-6SB21.js +1 -0
  28. package/dist-renderer/assets/bg-BG-XCXSNQG7-L1xMEEzs.js +5 -0
  29. package/dist-renderer/assets/blockDiagram-38ab4fdb-BHS1f8SU.js +118 -0
  30. package/dist-renderer/assets/bn-BD-2XOGV67Q-BgaYSNWB.js +5 -0
  31. package/dist-renderer/assets/c4Diagram-3d4e48cf-D2Rl9Buo.js +10 -0
  32. package/dist-renderer/assets/ca-ES-6MX7JW3Y-DsFYhkLC.js +8 -0
  33. package/dist-renderer/assets/channel-D6rvl4sk.js +1 -0
  34. package/dist-renderer/assets/classDiagram-70f12bd4-BGxDdVFC.js +2 -0
  35. package/dist-renderer/assets/classDiagram-v2-f2320105-BuoUwdmW.js +2 -0
  36. package/dist-renderer/assets/clone-ya1OS7ZU.js +1 -0
  37. package/dist-renderer/assets/createText-2e5e7dd3-BX6eAgL1.js +7 -0
  38. package/dist-renderer/assets/cs-CZ-2BRQDIVT-CXV-i633.js +11 -0
  39. package/dist-renderer/assets/da-DK-5WZEPLOC-DmYIifsm.js +5 -0
  40. package/dist-renderer/assets/de-DE-XR44H4JA-B2T52TzN.js +8 -0
  41. package/dist-renderer/assets/directory-open-01563666-DWU9wJ6I.js +1 -0
  42. package/dist-renderer/assets/directory-open-4ed118d0-CunoC1EB.js +1 -0
  43. package/dist-renderer/assets/edges-e0da2a9e-ChSiyO2u.js +4 -0
  44. package/dist-renderer/assets/el-GR-BZB4AONW-DlS_8ZJJ.js +10 -0
  45. package/dist-renderer/assets/erDiagram-9861fffd-REAc3tDU.js +51 -0
  46. package/dist-renderer/assets/es-ES-U4NZUMDT-DL-zHXpT.js +9 -0
  47. package/dist-renderer/assets/eu-ES-A7QVB2H4-Cq0Kx947.js +11 -0
  48. package/dist-renderer/assets/fa-IR-HGAKTJCU-DJqZOqAL.js +8 -0
  49. package/dist-renderer/assets/fi-FI-Z5N7JZ37-CQiIDJrs.js +6 -0
  50. package/dist-renderer/assets/file-open-002ab408-DIuFHtCF.js +1 -0
  51. package/dist-renderer/assets/file-open-7c801643-684qeFg4.js +1 -0
  52. package/dist-renderer/assets/file-save-3189631c-C1wFhQhH.js +1 -0
  53. package/dist-renderer/assets/file-save-745eba88-Bb9F9Kg7.js +1 -0
  54. package/dist-renderer/assets/flowDb-956e92f1-iZnRwdLd.js +10 -0
  55. package/dist-renderer/assets/flowDiagram-66a62f08-Cww5ErID.js +4 -0
  56. package/dist-renderer/assets/flowDiagram-v2-96b9c2cf-DMQnUrJv.js +1 -0
  57. package/dist-renderer/assets/flowchart-elk-definition-4a651766-B3GjdX0I.js +139 -0
  58. package/dist-renderer/assets/fr-FR-RHASNOE6-DXRyDBSp.js +9 -0
  59. package/dist-renderer/assets/ganttDiagram-c361ad54-Dh5UuCf5.js +257 -0
  60. package/dist-renderer/assets/gitGraphDiagram-72cf32ee-CUrdiK9f.js +70 -0
  61. package/dist-renderer/assets/gl-ES-HMX3MZ6V-DB2LhjQl.js +10 -0
  62. package/dist-renderer/assets/graph-KS9cHKTv.js +1 -0
  63. package/dist-renderer/assets/he-IL-6SHJWFNN-CWdud4mG.js +10 -0
  64. package/dist-renderer/assets/hi-IN-IWLTKZ5I-DkfCxaBI.js +4 -0
  65. package/dist-renderer/assets/hu-HU-A5ZG7DT2-DVX9rddx.js +7 -0
  66. package/dist-renderer/assets/id-ID-SAP4L64H-CIosyByg.js +10 -0
  67. package/dist-renderer/assets/image-blob-reduce.esm-BLtmMM_J.js +2 -0
  68. package/dist-renderer/assets/index-3862675e-CVxUAJo4.js +1 -0
  69. package/dist-renderer/assets/index-3RkkhxnO.js +36 -0
  70. package/dist-renderer/assets/index-B61Czmwn.js +95 -0
  71. package/dist-renderer/assets/index-BF6L2_KC.css +1 -0
  72. package/dist-renderer/assets/infoDiagram-f8f76790-CWACEGb6.js +7 -0
  73. package/dist-renderer/assets/init-Gi6I4Gst.js +1 -0
  74. package/dist-renderer/assets/it-IT-JPQ66NNP-D-TuMToN.js +11 -0
  75. package/dist-renderer/assets/ja-JP-DBVTYXUO-CK6puaHx.js +8 -0
  76. package/dist-renderer/assets/journeyDiagram-49397b02-DM-laNCt.js +139 -0
  77. package/dist-renderer/assets/kaa-6HZHGXH3-CiRWfMKd.js +1 -0
  78. package/dist-renderer/assets/kab-KAB-ZGHBKWFO-D4w9BQ8H.js +8 -0
  79. package/dist-renderer/assets/katex-DhXJpUyf.js +261 -0
  80. package/dist-renderer/assets/kk-KZ-P5N5QNE5-RZi2AGvr.js +1 -0
  81. package/dist-renderer/assets/km-KH-HSX4SM5Z-Dm-OPxhU.js +11 -0
  82. package/dist-renderer/assets/ko-KR-MTYHY66A-PbPGVqVz.js +9 -0
  83. package/dist-renderer/assets/ku-TR-6OUDTVRD-Bw0cMtYj.js +9 -0
  84. package/dist-renderer/assets/layout-zADYSvqS.js +1 -0
  85. package/dist-renderer/assets/line-DfBkzhQg.js +1 -0
  86. package/dist-renderer/assets/linear-O3lyK7Iz.js +1 -0
  87. package/dist-renderer/assets/lt-LT-XHIRWOB4-06ru_RZe.js +3 -0
  88. package/dist-renderer/assets/lv-LV-5QDEKY6T-DsGBjFui.js +7 -0
  89. package/dist-renderer/assets/mindmap-definition-fc14e90a-Bg9UaNPK.js +415 -0
  90. package/dist-renderer/assets/mr-IN-CRQNXWMA-C1kWOErC.js +13 -0
  91. package/dist-renderer/assets/my-MM-5M5IBNSE-C8wD2OFs.js +1 -0
  92. package/dist-renderer/assets/nb-NO-T6EIAALU-B7ac-R_W.js +10 -0
  93. package/dist-renderer/assets/nl-NL-IS3SIHDZ-Up67nxB7.js +8 -0
  94. package/dist-renderer/assets/nn-NO-6E72VCQL-BPlkzXM9.js +8 -0
  95. package/dist-renderer/assets/oc-FR-POXYY2M6-TRLIkgml.js +8 -0
  96. package/dist-renderer/assets/ordinal-BENe2yWM.js +1 -0
  97. package/dist-renderer/assets/pa-IN-N4M65BXN-Dl7hF9RX.js +4 -0
  98. package/dist-renderer/assets/path-CbwjOpE9.js +1 -0
  99. package/dist-renderer/assets/percentages-BXMCSKIN-wBXtRqNn.js +199 -0
  100. package/dist-renderer/assets/pica-CGZUgvhx.js +2 -0
  101. package/dist-renderer/assets/pieDiagram-8a3498a8-ZPRkRtpu.js +35 -0
  102. package/dist-renderer/assets/pl-PL-T2D74RX3-DkwkT852.js +9 -0
  103. package/dist-renderer/assets/pt-BR-5N22H2LF-BMFWH_jN.js +9 -0
  104. package/dist-renderer/assets/pt-PT-UZXXM6DQ-BPSC-yrG.js +9 -0
  105. package/dist-renderer/assets/quadrantDiagram-120e2f19-DB1TyNBK.js +7 -0
  106. package/dist-renderer/assets/requirementDiagram-deff3bca-DqVc_A29.js +52 -0
  107. package/dist-renderer/assets/ro-RO-JPDTUUEW-CgkEXyU-.js +11 -0
  108. package/dist-renderer/assets/roundRect-mAH3dD0p.js +1 -0
  109. package/dist-renderer/assets/ru-RU-B4JR7IUQ-BJIahd0q.js +9 -0
  110. package/dist-renderer/assets/sankeyDiagram-04a897e0-DZqGbQ0e.js +8 -0
  111. package/dist-renderer/assets/sequenceDiagram-704730f1-D0Q04jBP.js +122 -0
  112. package/dist-renderer/assets/si-LK-N5RQ5JYF-DZ97xsfW.js +1 -0
  113. package/dist-renderer/assets/sk-SK-C5VTKIMK-3O0GcaTE.js +6 -0
  114. package/dist-renderer/assets/sl-SI-NN7IZMDC-x_-Ca4Po.js +6 -0
  115. package/dist-renderer/assets/stateDiagram-587899a1-BkW3tbK-.js +1 -0
  116. package/dist-renderer/assets/stateDiagram-v2-d93cdb3a-CZYVILLk.js +1 -0
  117. package/dist-renderer/assets/styles-6aaf32cf-BQKVAqEs.js +207 -0
  118. package/dist-renderer/assets/styles-9a916d00-DTjDY-zu.js +160 -0
  119. package/dist-renderer/assets/styles-c10674c1-CviHLZ2K.js +116 -0
  120. package/dist-renderer/assets/subset-shared.chunk-DIxPfZhi.js +22 -0
  121. package/dist-renderer/assets/subset-worker.chunk-DDMwauN2.js +1 -0
  122. package/dist-renderer/assets/sv-SE-XGPEYMSR-DmtUCQiw.js +10 -0
  123. package/dist-renderer/assets/svgDrawCommon-08f97a94-B6bAmadW.js +1 -0
  124. package/dist-renderer/assets/ta-IN-2NMHFXQM-D7fiXwNW.js +9 -0
  125. package/dist-renderer/assets/th-TH-HPSO5L25-D_F5D_Tj.js +2 -0
  126. package/dist-renderer/assets/timeline-definition-85554ec2-BZuaxri2.js +61 -0
  127. package/dist-renderer/assets/tr-TR-DEFEU3FU-CzwSWbpN.js +7 -0
  128. package/dist-renderer/assets/uk-UA-QMV73CPH-BaaxaBLn.js +6 -0
  129. package/dist-renderer/assets/vi-VN-M7AON7JQ-BQ9szPme.js +5 -0
  130. package/dist-renderer/assets/xychartDiagram-e933f94c-7rTYP6vy.js +7 -0
  131. package/dist-renderer/assets/zh-CN-LNUGB5OW-DDjjE3j0.js +10 -0
  132. package/dist-renderer/assets/zh-HK-E62DVLB3-CUaw1jmU.js +1 -0
  133. package/dist-renderer/assets/zh-TW-RAJ6MFWO-BFOuD9P0.js +9 -0
  134. package/dist-renderer/index.html +13 -0
  135. package/package.json +8 -4
  136. package/skills/council-install/SKILL.md +63 -0
  137. package/skills/council-manage/SKILL.md +1 -1
package/README.md CHANGED
@@ -1,124 +1,143 @@
1
1
  # @statechange/council
2
2
 
3
- A CLI + Electron GUI for orchestrating round-robin AI counsellor discussions. Build a council of AI personas each with their own backend, model, personality, and source material and have them debate topics in structured or freeform formats.
3
+ Build a council of AI personas and have them debate any topic. Each counsellor has their own LLM backend, model, personality, and source material. Run discussions in a structured **debate** format or an open **freeform** group chat — via the CLI, an Electron GUI, or Claude Code skills.
4
4
 
5
- ## Quick Start with Claude Code Skills
5
+ ## Getting Started with Claude Code Skills
6
6
 
7
- The fastest way to get started is through [Claude Code](https://claude.com/claude-code) skills. Install the package, and the skills handle the rest:
7
+ The fastest path is to add the skills to [Claude Code](https://claude.com/claude-code). They handle installation, configuration, counsellor creation, and running discussions for you.
8
8
 
9
9
  ```bash
10
- npm install -g @statechange/council
10
+ npx skills add statechangelabs/ai-council
11
11
  ```
12
12
 
13
- Then in Claude Code:
13
+ This gives you two skills:
14
14
 
15
- - **`/council-manage`** Create counsellors, run discussions, manage your council. Ask it to "create a counsellor based on [person]" or "run a debate about [topic]".
16
- - **`/council-setup-keys`** — Find API keys scattered across your env files and shell profiles, then consolidate them into `~/.ai-council/config.json`.
15
+ | Skill | What it does |
16
+ |-------|-------------|
17
+ | `/council-manage` | Create counsellors, run discussions, manage your council. Try: *"create a counsellor based on Warren Buffett"* or *"run a debate about whether AI should be open source"* |
18
+ | `/council-setup-keys` | Finds API keys scattered across your env files and shell profiles, then imports them into `~/.ai-council/config.json` |
17
19
 
18
- The skills know how to use the CLI, create counsellors from source material, and troubleshoot configuration issues.
20
+ The skills will install the `council` CLI automatically if it's not already on your system.
19
21
 
20
22
  ## Install
21
23
 
22
24
  ```bash
23
- # Global install (recommended for CLI use)
25
+ # Global install (gives you the `council` command)
24
26
  npm install -g @statechange/council
25
27
 
26
- # Or run directly
28
+ # Or run one-off without installing
27
29
  npx @statechange/council discuss "Should we adopt microservices?"
28
30
  ```
29
31
 
30
- ## CLI Usage
32
+ ## CLI
33
+
34
+ ### Run a discussion
31
35
 
32
36
  ```bash
33
- # Run a freeform discussion (default)
37
+ # Freeform (default) open group chat, everyone sees everything
34
38
  council discuss "Should we pivot to enterprise?" --rounds 3
35
39
 
36
- # Run a structured debate
40
+ # Debate structured constructive/rebuttal format
37
41
  council discuss "Should AI be open source?" --mode debate --rounds 3
38
42
 
39
- # Use specific counsellors
43
+ # Pick specific counsellors
40
44
  council discuss "Topic" --counsellors ./council/strategist ./council/critic
41
45
 
42
46
  # Topic from a file
43
47
  council discuss ./topics/architecture.md
48
+ ```
44
49
 
45
- # List available counsellors
46
- council list
50
+ ### Manage counsellors
47
51
 
48
- # View past discussions
49
- council history
50
- council history <id>
52
+ ```bash
53
+ council list # Show available counsellors
54
+ council counsellor add ./path/to/counsellor # Register from local directory
55
+ council counsellor add https://github.com/user/counsellors.git # From git
56
+ council counsellor remove my-counsellor # Unregister
51
57
  ```
52
58
 
53
- ### Discussion Modes
59
+ ### View history
60
+
61
+ ```bash
62
+ council history # List past discussions
63
+ council history <id> # View a specific discussion
64
+ ```
54
65
 
55
- **Freeform** (default) — Open group chat. Every counsellor sees the full conversation history on every turn. The first speaker sets the tone and later speakers react.
66
+ ### Configure backends
56
67
 
57
- **Debate** — Structured argument with three key differences:
58
- 1. **Round 1 (Constructive)**: Each counsellor argues their position based only on the question — no visibility into what others said.
59
- 2. **Rebuttal rounds**: Counsellors see the constructives plus only the previous round. Speaker order is shuffled each round.
60
- 3. **Interim summaries**: A brief secretary summary after each round, creating a running debate narrative.
68
+ ```bash
69
+ council config show # See what's configured
70
+ council config scan # Find API keys across your system
71
+ council config scan ~/project/.env # Scan additional paths
72
+ council config import # Import discovered keys into config
73
+ ```
61
74
 
62
- ### Options
75
+ ### All CLI options
63
76
 
64
77
  ```
65
- --council, -c Path to council directory (default: ./council/)
66
- --counsellors Specific counsellor directory paths (space-separated)
67
- --rounds, -r Number of discussion rounds (default: 2)
68
- --mode, -m freeform or debate (default: freeform)
69
- --output, -o Output directory (default: ./output)
70
- --format, -f md, json, or both (default: both)
71
- --infographic, -i Generate an infographic after discussion
78
+ council discuss <topic> [options]
79
+
80
+ --mode, -m freeform or debate (default: freeform)
81
+ --rounds, -r Number of discussion rounds (default: 2)
82
+ --council, -c Path to council directory (default: ./council/)
83
+ --counsellors Specific counsellor directory paths (space-separated)
84
+ --output, -o Output directory (default: ./output)
85
+ --format, -f md, json, or both (default: both)
86
+ --infographic, -i Generate an infographic after discussion
72
87
  ```
73
88
 
74
89
  ## GUI
75
90
 
76
- Launch the Electron app for a visual interface with real-time streaming, counsellor management, and discussion history:
91
+ The Electron app gives you a visual interface with real-time streaming, point-and-click counsellor management, and full discussion history.
77
92
 
78
93
  ```bash
79
- # Development
80
- council-gui # if installed globally
81
- # or from source:
94
+ # From the cloned repo
95
+ git clone https://github.com/statechangelabs/ai-council.git
96
+ cd ai-council
97
+ bun install
82
98
  bun run dev:gui
83
99
  ```
84
100
 
85
- The GUI includes:
86
- - Counsellor selection chips with health indicators
87
- - Freeform/Debate mode toggle with explanatory tooltips
88
- - Real-time streaming of counsellor responses
89
- - Round dividers and interim summaries in debate mode
90
- - Secretary summary with Excalidraw position diagrams
91
- - Infographic generation (OpenAI / Google)
92
- - Full discussion history with search
101
+ ### What you get
93
102
 
94
- ## Configuration
103
+ - **Discussion page** — Topic input with file attachments, counsellor selection chips, freeform/debate mode toggle, real-time streaming of responses, round dividers and interim summaries in debate mode, inject messages mid-discussion
104
+ - **Counsellors page** — Browse, search, create, edit, and delete counsellors with a form editor or raw ABOUT.md editing; register external counsellors from local paths or git repos
105
+ - **History page** — Browse past discussions, view full transcripts with round summaries, copy as markdown, generate infographics
106
+ - **Settings page** — Configure API keys per backend, test connections, see available models
95
107
 
96
- ### API Keys
108
+ ## Discussion Modes
97
109
 
98
- Backends need API keys (except Ollama which runs locally). Keys can come from:
110
+ ### Freeform
99
111
 
100
- 1. **Environment variables**: `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GOOGLE_API_KEY`
101
- 2. **Config file**: `~/.ai-council/config.json`
102
- 3. **`.env` file** in the project root
112
+ The default. An open group chat where every counsellor sees the full conversation history on every turn. The first speaker sets the tone and later speakers react to what's been said. Counsellor order stays the same each round.
103
113
 
104
- Use the CLI to find and import keys:
114
+ ### Debate
105
115
 
106
- ```bash
107
- council config show # See what's configured
108
- council config scan # Find keys in env files and shell profiles
109
- council config scan ~/project/.env # Scan additional paths
110
- council config import # Import discovered keys
111
- ```
116
+ A structured argument format designed to prevent pile-on and anchoring bias:
117
+
118
+ 1. **Round 1 Constructive**: Each counsellor argues their position based *only* on the question. They can't see what anyone else said. Even a "critic" persona has to stand up their own argument first.
112
119
 
113
- Or configure in the GUI under Settings.
120
+ 2. **Rebuttal rounds (2+)**: Counsellors now see the constructive round plus *only* the previous rebuttal round — not the entire history. This keeps context growth bounded. Speaker order is shuffled each round so nobody is always first or last.
121
+
122
+ 3. **Interim summaries**: If a secretary is configured, a brief summary is generated after every round, tracking emerging agreements, disagreements, and shifts in position.
123
+
124
+ ## Configuration
125
+
126
+ ### API Keys
127
+
128
+ Each backend needs an API key (except Ollama, which runs locally). Keys are resolved in order:
129
+
130
+ 1. `~/.ai-council/config.json` (managed by `council config import` or the GUI)
131
+ 2. Environment variables: `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GOOGLE_API_KEY`
132
+ 3. `.env` file in the working directory
114
133
 
115
134
  ### Secretary
116
135
 
117
- Add a `secretary` block to `~/.ai-council/config.json` to enable post-discussion summaries and debate interim summaries:
136
+ Enable post-discussion summaries (and debate interim summaries) by adding a `secretary` block to `~/.ai-council/config.json`:
118
137
 
119
138
  ```json
120
139
  {
121
- "backends": { ... },
140
+ "backends": { "..." : "..." },
122
141
  "secretary": {
123
142
  "backend": "anthropic",
124
143
  "model": "claude-sonnet-4-5-20250929"
@@ -126,9 +145,18 @@ Add a `secretary` block to `~/.ai-council/config.json` to enable post-discussion
126
145
  }
127
146
  ```
128
147
 
148
+ ### Supported Backends
149
+
150
+ | Backend | Default Model | API Key |
151
+ |---------|--------------|---------|
152
+ | anthropic | claude-sonnet-4-5-20250929 | `ANTHROPIC_API_KEY` |
153
+ | openai | gpt-4o | `OPENAI_API_KEY` |
154
+ | google | gemini-2.0-flash | `GOOGLE_API_KEY` |
155
+ | ollama | llama3.2 | None (local) |
156
+
129
157
  ## Creating Counsellors
130
158
 
131
- Each counsellor is a directory with an `ABOUT.md` file:
159
+ A counsellor is a directory containing an `ABOUT.md` file with YAML frontmatter and a system prompt:
132
160
 
133
161
  ```
134
162
  council/
@@ -137,7 +165,7 @@ council/
137
165
  avatar.jpg # optional
138
166
  ```
139
167
 
140
- ### ABOUT.md Format
168
+ ### ABOUT.md format
141
169
 
142
170
  ```markdown
143
171
  ---
@@ -151,55 +179,58 @@ avatar: "avatar.jpg"
151
179
  ---
152
180
 
153
181
  You are The Strategist. You sit on a council of experts and bring a
154
- strategic lens to every discussion...
182
+ strategic lens to every discussion.
183
+
184
+ When contributing:
185
+ - Think about second and third-order effects
186
+ - Consider offensive and defensive strategic positions
187
+ - Ground your thinking in frameworks when relevant
188
+ - Be direct and opinionated
189
+
190
+ Keep your responses focused. Aim for 2-4 paragraphs per turn.
155
191
  ```
156
192
 
157
- ### Supported Backends
193
+ ### Frontmatter fields
158
194
 
159
- | Backend | Default Model | API Key |
160
- |---------|--------------|---------|
161
- | anthropic | claude-sonnet-4-5-20250929 | `ANTHROPIC_API_KEY` |
162
- | openai | gpt-4o | `OPENAI_API_KEY` |
163
- | google | gemini-2.0-flash | `GOOGLE_API_KEY` |
164
- | ollama | llama3.2 | None (local) |
195
+ | Field | Required | Description |
196
+ |-------|----------|-------------|
197
+ | `name` | Yes | Display name |
198
+ | `description` | Yes | One-line summary of this counsellor's perspective |
199
+ | `backend` | Yes | `anthropic`, `openai`, `google`, or `ollama` |
200
+ | `model` | No | Specific model ID; uses backend default if omitted |
201
+ | `temperature` | No | 0.0–2.0; higher = more creative (default varies by backend) |
202
+ | `interests` | No | Tags shown in the UI |
203
+ | `avatar` | No | Path to local image or URL |
165
204
 
166
- ### Registering External Counsellors
205
+ ### Included counsellors
167
206
 
168
- ```bash
169
- # From a local directory
170
- council counsellor add ./path/to/counsellor
207
+ The package ships with three starter counsellors:
171
208
 
172
- # From a git repository
173
- council counsellor add https://github.com/user/my-counsellors.git
209
+ | Counsellor | Backend | Perspective |
210
+ |-----------|---------|-------------|
211
+ | **The Strategist** | Anthropic (Haiku) | Strategic business advisor — positioning, growth, competitive advantage |
212
+ | **The Creative** | Anthropic (Opus) | Lateral thinker — unexpected analogies, reframing, unconventional connections |
213
+ | **The Critic** | Google (Gemini Flash) | Devil's advocate — stress-tests ideas, surfaces assumptions, finds failure modes |
174
214
 
175
- # List registered counsellors
176
- council counsellor list
215
+ ### Building counsellors from source material
177
216
 
178
- # Remove
179
- council counsellor remove my-counsellor
180
- ```
217
+ You can create counsellors based on real people or bodies of work by appending reference material below the system prompt. The `/council-manage` skill in Claude Code can automate this — ask it to *"create a counsellor based on [person or book]"* and it'll handle downloading source text, writing the system prompt, and assembling the ABOUT.md.
181
218
 
182
219
  ## Logging
183
220
 
184
- Errors are logged to `~/.ai-council/council.log` with timestamps, context, and full stack traces. Check this file when a counsellor fails to respond or a summary doesn't generate.
221
+ Errors are logged to `~/.ai-council/council.log` with timestamps, context tags, and full stack traces. Check this file when a counsellor fails to respond or a summary doesn't generate.
185
222
 
186
223
  ## Development
187
224
 
188
225
  ```bash
189
- # Install dependencies
226
+ git clone https://github.com/statechangelabs/ai-council.git
227
+ cd ai-council
190
228
  bun install
191
229
 
192
- # CLI development
193
- bun run dev -- discuss "topic"
194
-
195
- # GUI development
196
- bun run dev:gui
197
-
198
- # Build CLI
199
- bun run build
200
-
201
- # Build GUI
202
- bun run build:gui
230
+ bun run dev -- discuss "topic" # CLI development
231
+ bun run dev:gui # GUI development
232
+ bun run build # Build CLI
233
+ bun run build:gui # Build GUI
203
234
  ```
204
235
 
205
236
  ## License
package/dist/cli.js CHANGED
@@ -9,6 +9,8 @@ import { ListCommand } from "./commands/list.js";
9
9
  import { ConfigCommand } from "./commands/config.js";
10
10
  import { CounsellorCommand } from "./commands/counsellor.js";
11
11
  import { HistoryCommand } from "./commands/history.js";
12
+ import { GuiCommand } from "./commands/gui.js";
13
+ import { InstallCommand } from "./commands/install.js";
12
14
  const cli = meow(`
13
15
  Usage
14
16
  $ council <command> [options]
@@ -21,6 +23,9 @@ const cli = meow(`
21
23
  counsellor add <path-or-url> Register a counsellor from a local path or git URL
22
24
  counsellor remove <id> Unregister a counsellor (--yes to delete cloned files)
23
25
  counsellor list List all registered counsellors
26
+ gui Launch the Electron GUI
27
+ install Install AI Council as a macOS application
28
+ install --uninstall Remove AI Council from Applications
24
29
  config show Show current configuration and key status
25
30
  config scan [paths..] Scan for API keys in env files and shell profiles
26
31
  config import [paths..] Import discovered keys into ~/.ai-council/config.json
@@ -93,6 +98,10 @@ const cli = meow(`
93
98
  shortFlag: "y",
94
99
  default: false,
95
100
  },
101
+ uninstall: {
102
+ type: "boolean",
103
+ default: false,
104
+ },
96
105
  },
97
106
  });
98
107
  const command = cli.input[0];
@@ -136,6 +145,12 @@ switch (command) {
136
145
  render(_jsx(CounsellorCommand, { subcommand: sub, target: target, yes: cli.flags.yes }));
137
146
  break;
138
147
  }
148
+ case "gui":
149
+ render(_jsx(GuiCommand, {}));
150
+ break;
151
+ case "install":
152
+ render(_jsx(InstallCommand, { uninstall: cli.flags.uninstall }));
153
+ break;
139
154
  case "config": {
140
155
  const sub = cli.input[1];
141
156
  if (!sub || !["show", "scan", "import"].includes(sub)) {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function GuiCommand(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,63 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { Text } from "ink";
4
+ import { spawn, execSync } from "node:child_process";
5
+ import { fileURLToPath } from "node:url";
6
+ import { resolve, dirname } from "node:path";
7
+ import { existsSync } from "node:fs";
8
+ export function GuiCommand() {
9
+ const [status, setStatus] = useState("Locating Electron...");
10
+ const [error, setError] = useState(null);
11
+ useEffect(() => {
12
+ async function launch() {
13
+ // Resolve dist-electron/main.js relative to this package
14
+ const pkgRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
15
+ const mainJs = resolve(pkgRoot, "dist-electron/main.js");
16
+ if (!existsSync(mainJs)) {
17
+ setError(`Could not find Electron entry point at ${mainJs}\n` +
18
+ "Make sure the GUI has been built: bun run build:gui");
19
+ return;
20
+ }
21
+ // Try to find the electron binary
22
+ let electronPath = null;
23
+ // Method 1: require.resolve("electron") — the npm package exports the binary path
24
+ try {
25
+ const { createRequire } = await import("node:module");
26
+ const require = createRequire(import.meta.url);
27
+ electronPath = require("electron");
28
+ }
29
+ catch {
30
+ // not installed locally
31
+ }
32
+ // Method 2: check PATH
33
+ if (!electronPath) {
34
+ try {
35
+ electronPath = execSync("which electron", { encoding: "utf-8" }).trim();
36
+ }
37
+ catch {
38
+ // not in PATH
39
+ }
40
+ }
41
+ if (!electronPath) {
42
+ setError("The GUI requires Electron. Install it with:\n\n" +
43
+ " npm install -g electron\n");
44
+ return;
45
+ }
46
+ // Spawn electron as a detached process so the CLI can exit
47
+ setStatus("Launching AI Council GUI...");
48
+ const child = spawn(electronPath, [mainJs], {
49
+ detached: true,
50
+ stdio: "ignore",
51
+ });
52
+ child.unref();
53
+ // Give it a moment then exit
54
+ setTimeout(() => process.exit(0), 500);
55
+ }
56
+ launch();
57
+ }, []);
58
+ if (error) {
59
+ return _jsx(Text, { color: "red", children: error });
60
+ }
61
+ return _jsx(Text, { children: status });
62
+ }
63
+ //# sourceMappingURL=gui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gui.js","sourceRoot":"","sources":["../../src/commands/gui.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,MAAM,UAAU,UAAU;IACxB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAS,sBAAsB,CAAC,CAAC;IACrE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAExD,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,UAAU,MAAM;YACnB,yDAAyD;YACzD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC1E,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;YAEzD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBACxB,QAAQ,CACN,0CAA0C,MAAM,IAAI;oBAClD,qDAAqD,CACxD,CAAC;gBACF,OAAO;YACT,CAAC;YAED,kCAAkC;YAClC,IAAI,YAAY,GAAkB,IAAI,CAAC;YAEvC,kFAAkF;YAClF,IAAI,CAAC;gBACH,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;gBACtD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC/C,YAAY,GAAG,OAAO,CAAC,UAAU,CAAsB,CAAC;YAC1D,CAAC;YAAC,MAAM,CAAC;gBACP,wBAAwB;YAC1B,CAAC;YAED,uBAAuB;YACvB,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,IAAI,CAAC;oBACH,YAAY,GAAG,QAAQ,CAAC,gBAAgB,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC1E,CAAC;gBAAC,MAAM,CAAC;oBACP,cAAc;gBAChB,CAAC;YACH,CAAC;YAED,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,QAAQ,CACN,iDAAiD;oBAC/C,6BAA6B,CAChC,CAAC;gBACF,OAAO;YACT,CAAC;YAED,2DAA2D;YAC3D,SAAS,CAAC,6BAA6B,CAAC,CAAC;YACzC,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC,MAAM,CAAC,EAAE;gBAC1C,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE,QAAQ;aAChB,CAAC,CAAC;YACH,KAAK,CAAC,KAAK,EAAE,CAAC;YAEd,6BAA6B;YAC7B,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,EAAE,CAAC;IACX,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,KAAC,IAAI,IAAC,KAAK,EAAC,KAAK,YAAE,KAAK,GAAQ,CAAC;IAC1C,CAAC;IAED,OAAO,KAAC,IAAI,cAAE,MAAM,GAAQ,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,5 @@
1
+ interface Props {
2
+ uninstall?: boolean;
3
+ }
4
+ export declare function InstallCommand({ uninstall }: Props): import("react/jsx-runtime").JSX.Element;
5
+ export {};
@@ -0,0 +1,131 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { Text } from "ink";
4
+ import { execSync } from "node:child_process";
5
+ import { fileURLToPath } from "node:url";
6
+ import { resolve, dirname } from "node:path";
7
+ import { existsSync, mkdirSync, writeFileSync, chmodSync, rmSync } from "node:fs";
8
+ const APP_PATH = "/Applications/AI Council.app";
9
+ export function InstallCommand({ uninstall }) {
10
+ const [status, setStatus] = useState(uninstall ? "Removing AI Council..." : "Installing AI Council...");
11
+ const [error, setError] = useState(null);
12
+ useEffect(() => {
13
+ if (uninstall) {
14
+ if (!existsSync(APP_PATH)) {
15
+ setStatus("AI Council is not installed in /Applications.");
16
+ return;
17
+ }
18
+ try {
19
+ rmSync(APP_PATH, { recursive: true, force: true });
20
+ setStatus("AI Council removed from /Applications.");
21
+ }
22
+ catch (err) {
23
+ setError(`Failed to remove ${APP_PATH}: ${err.message}`);
24
+ }
25
+ return;
26
+ }
27
+ async function install() {
28
+ // Install flow
29
+ const pkgRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
30
+ const mainJs = resolve(pkgRoot, "dist-electron/main.js");
31
+ if (!existsSync(mainJs)) {
32
+ setError(`Could not find Electron entry point at ${mainJs}\n` +
33
+ "Make sure the GUI has been built: bun run build:gui");
34
+ return;
35
+ }
36
+ // Verify electron is available
37
+ let electronPath = null;
38
+ try {
39
+ const { createRequire } = await import("node:module");
40
+ const req = createRequire(import.meta.url);
41
+ electronPath = req("electron");
42
+ }
43
+ catch {
44
+ // not installed locally
45
+ }
46
+ if (!electronPath) {
47
+ try {
48
+ electronPath = execSync("which electron", { encoding: "utf-8" }).trim();
49
+ }
50
+ catch {
51
+ // not in PATH
52
+ }
53
+ }
54
+ if (!electronPath) {
55
+ setError("The GUI requires Electron. Install it with:\n\n" +
56
+ " npm install -g electron\n");
57
+ return;
58
+ }
59
+ // Build the .app structure
60
+ const contentsDir = resolve(APP_PATH, "Contents");
61
+ const macosDir = resolve(contentsDir, "MacOS");
62
+ const resourcesDir = resolve(contentsDir, "Resources");
63
+ try {
64
+ mkdirSync(macosDir, { recursive: true });
65
+ mkdirSync(resourcesDir, { recursive: true });
66
+ // Info.plist
67
+ const plist = `<?xml version="1.0" encoding="UTF-8"?>
68
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
69
+ <plist version="1.0">
70
+ <dict>
71
+ <key>CFBundleName</key>
72
+ <string>AI Council</string>
73
+ <key>CFBundleDisplayName</key>
74
+ <string>AI Council</string>
75
+ <key>CFBundleIdentifier</key>
76
+ <string>com.statechange.council</string>
77
+ <key>CFBundleVersion</key>
78
+ <string>1.0</string>
79
+ <key>CFBundlePackageType</key>
80
+ <string>APPL</string>
81
+ <key>CFBundleExecutable</key>
82
+ <string>ai-council</string>
83
+ </dict>
84
+ </plist>`;
85
+ writeFileSync(resolve(contentsDir, "Info.plist"), plist);
86
+ // Launcher shell script
87
+ const launcher = `#!/bin/bash
88
+ MAIN_JS="${mainJs}"
89
+
90
+ # Find electron binary
91
+ ELECTRON=""
92
+
93
+ # Method 1: npm global modules
94
+ if [ -z "$ELECTRON" ]; then
95
+ NPM_ROOT=$(npm root -g 2>/dev/null)
96
+ if [ -n "$NPM_ROOT" ] && [ -f "$NPM_ROOT/electron/dist/Electron.app/Contents/MacOS/Electron" ]; then
97
+ ELECTRON="$NPM_ROOT/electron/dist/Electron.app/Contents/MacOS/Electron"
98
+ elif [ -n "$NPM_ROOT" ] && [ -f "$NPM_ROOT/electron/cli.js" ]; then
99
+ ELECTRON=$(node "$NPM_ROOT/electron/cli.js" --print-path 2>/dev/null || echo "")
100
+ fi
101
+ fi
102
+
103
+ # Method 2: PATH
104
+ if [ -z "$ELECTRON" ]; then
105
+ ELECTRON=$(which electron 2>/dev/null || echo "")
106
+ fi
107
+
108
+ if [ -z "$ELECTRON" ]; then
109
+ osascript -e 'display alert "Electron not found" message "Install Electron with: npm install -g electron" as critical'
110
+ exit 1
111
+ fi
112
+
113
+ exec "$ELECTRON" "$MAIN_JS"
114
+ `;
115
+ const launcherPath = resolve(macosDir, "ai-council");
116
+ writeFileSync(launcherPath, launcher);
117
+ chmodSync(launcherPath, 0o755);
118
+ setStatus("AI Council installed to /Applications.\nYou can find it in Spotlight or Launchpad.");
119
+ }
120
+ catch (err) {
121
+ setError(`Failed to create ${APP_PATH}: ${err.message}`);
122
+ }
123
+ }
124
+ install();
125
+ }, []);
126
+ if (error) {
127
+ return _jsx(Text, { color: "red", children: error });
128
+ }
129
+ return _jsx(Text, { color: "green", children: status });
130
+ }
131
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.tsx"],"names":[],"mappings":"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"}