cocosuperintelligence 1.6.1 → 1.7.1
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/README.md +8 -16
- package/bin/coco-bootstrap.sh +1 -1
- package/bin/coco.js +145 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
[](https://github.com/coco-research/coco/actions/workflows/ci.yml)
|
|
11
11
|
[](https://github.com/coco-research/coco/releases)
|
|
12
|
-
[](skills/)
|
|
13
|
+
[](commands/)
|
|
14
14
|
[](systems/superintelligence/)
|
|
15
15
|
|
|
16
16
|
Open-core: the core is [MIT](LICENSE), and Super Intelligence is [proprietary](systems/superintelligence/LICENSE). Files stay on your machine. No telemetry. A version check may contact GitHub once a day.
|
|
@@ -38,7 +38,7 @@ An illustration built from a real `/SI-Decide` run (Claude Sonnet 5.5, 30 Septem
|
|
|
38
38
|
|
|
39
39
|
Prerequisites: git, bash, Node.js 14 or newer (for `npx`), and python3 (it generates the `/SI-*` commands).
|
|
40
40
|
|
|
41
|
-
`npx cocosuperintelligence` installs the latest release. It clones the pinned release tag (currently `v1.
|
|
41
|
+
`npx cocosuperintelligence` installs the latest release. It clones the pinned release tag (currently `v1.7.1`, not floating `main`) into `./coco` of the current directory, then runs `install.sh`. Run it from your home folder, so the clone is `~/coco` and not a folder inside another project. On a fresh machine it took about 3 minutes, including the download. <!-- x-release-please-version -->
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
44
|
npx cocosuperintelligence
|
|
@@ -78,26 +78,20 @@ You type a question. The orchestrator scores 495 personas across 13 departments
|
|
|
78
78
|
|
|
79
79
|
How the router scores teams: [`systems/superintelligence/README.md`](systems/superintelligence/README.md). What each editor actually receives: [`adapters/INDEX.md`](adapters/INDEX.md).
|
|
80
80
|
|
|
81
|
-
## Status
|
|
81
|
+
## Status
|
|
82
82
|
|
|
83
|
-
Released
|
|
83
|
+
Released on npm: `npx cocosuperintelligence` installs the latest release ([CHANGELOG](CHANGELOG.md)).
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
Measured on main, a default Claude Code install delivers 190 of the 228 skills (the rest are the opt-in security pack and Cursor-only skills), 387 commands and 34 agents ([`docs/delivered-counts.json`](docs/delivered-counts.json)).
|
|
86
86
|
|
|
87
87
|
Known gap: most GSD skills need the upstream GSD toolkit at `~/.claude/get-shit-done` (see [`systems/gsd/README.md`](systems/gsd/README.md)).
|
|
88
88
|
|
|
89
|
-
Next three milestones:
|
|
90
|
-
|
|
91
|
-
1. v1.6.0, so `npx` installs what main already has.
|
|
92
|
-
2. Bundle the GSD runtime, so those skills work without a separate toolkit.
|
|
93
|
-
3. Installer safety: an uninstall guard, and a clearer clone location.
|
|
94
|
-
|
|
95
89
|
<details>
|
|
96
90
|
<summary><strong>Other install paths, updates, uninstall</strong></summary>
|
|
97
91
|
|
|
98
92
|
From a checkout you already have, `bash install.sh` auto-detects the editor. Narrow it with `--adapter cursor` or `--systems gsd,brain`. `--core-only` skips bundles. `reverse-skill` stays opt-in: `--systems reverse-skill`.
|
|
99
93
|
|
|
100
|
-
The remote bootstrap clones the pinned release tag
|
|
94
|
+
The remote bootstrap clones the same pinned release tag as `npx` (not floating `main`) to `~/.coco`, prints the commit, and waits for you to type `y` before it runs `install.sh`:
|
|
101
95
|
|
|
102
96
|
```bash
|
|
103
97
|
bash <(curl -fsSL https://raw.githubusercontent.com/coco-research/coco/main/bin/coco-bootstrap.sh)
|
|
@@ -201,8 +195,6 @@ Six bundles install by default. `--core-only` skips them. `--systems <list>` ins
|
|
|
201
195
|
|
|
202
196
|
A default Claude Code install delivers **190 skills, 387 commands and 34 agents**, measured by running the installer. The repository holds 228 skills; the difference is the opt-in security pack and Cursor-only skills. The measured row is main.
|
|
203
197
|
|
|
204
|
-
The v1.5.0 release `npx` installs today is older. See [Status and roadmap](#status-and-roadmap).
|
|
205
|
-
|
|
206
198
|
<table align="center">
|
|
207
199
|
<tr>
|
|
208
200
|
<td align="center" width="20%"><h3>228</h3><sub>Skills</sub><br><small>76 Core + 152 Bundle · 190 install by default</small></td>
|
|
@@ -220,7 +212,7 @@ The v1.5.0 release `npx` installs today is older. See [Status and roadmap](#stat
|
|
|
220
212
|
</div>
|
|
221
213
|
|
|
222
214
|
<table>
|
|
223
|
-
<tr><td><strong>Spec Version</strong></td><td>
|
|
215
|
+
<tr><td><strong>Spec Version</strong></td><td><a href="https://github.com/coco-research/coco/releases/latest">latest release</a></td></tr>
|
|
224
216
|
<tr><td><strong>License</strong></td><td>Open-core — <a href="LICENSE">MIT</a> core; Super Intelligence is <a href="systems/superintelligence/LICENSE">proprietary</a></td></tr>
|
|
225
217
|
<tr><td><strong>Total Skills</strong></td><td>228 in the repository (76 Core + 152 Bundle); 190 install by default on Claude Code</td></tr>
|
|
226
218
|
<tr><td><strong>Slash Commands</strong></td><td>387 on a default install — 45 Core (shipped) + 342 Super Intelligence (325 per-team + 17 cross-team, generated at install)</td></tr>
|
package/bin/coco-bootstrap.sh
CHANGED
|
@@ -25,7 +25,7 @@ set -euo pipefail
|
|
|
25
25
|
|
|
26
26
|
REPO_URL="https://github.com/coco-research/coco.git"
|
|
27
27
|
# Keep in sync with package.json version. Clone the last tagged release, not floating main.
|
|
28
|
-
PINNED_TAG="v1.
|
|
28
|
+
PINNED_TAG="v1.7.1" # x-release-please-version
|
|
29
29
|
INSTALL_DIR="${COCO_DIR:-$HOME/.coco}"
|
|
30
30
|
YES="${COCO_BOOTSTRAP_YES:-}"
|
|
31
31
|
PASS_THROUGH=()
|
package/bin/coco.js
CHANGED
|
@@ -131,30 +131,142 @@ function which(cmd) {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
function run(cmd, args, opts = {}) {
|
|
134
|
-
|
|
134
|
+
// git ignores cwd/-C when GIT_DIR is set. Git calls get gitEnv(); SSH and proxies stay.
|
|
135
|
+
const r = spawnSync(cmd, args, { stdio: 'inherit', ...opts, ...(cmd === 'git' ? { env: gitEnv() } : {}) });
|
|
135
136
|
if (r.status !== 0) {
|
|
136
137
|
process.exit(r.status || 1);
|
|
137
138
|
}
|
|
138
139
|
}
|
|
139
140
|
|
|
141
|
+
// Any common spelling of github.com/coco-research/coco: https/ssh/git URLs with optional
|
|
142
|
+
// user[:token]@ and :port, or scp form with or without user@. GitHub names are case-insensitive.
|
|
143
|
+
const ORIGIN_RE = /^(?:(?:https?|ssh|git):\/\/(?:[^@\/]+@)?github\.com(?::\d+)?\/|(?:[^@\/:]+@)?github\.com:)coco-research\/coco(?:\.git)?\/?$/i;
|
|
144
|
+
|
|
145
|
+
// Hooks and scripts export GIT_DIR. git -C does not override it: config and
|
|
146
|
+
// remote get-url then read that repo, while show-toplevel still prints -C.
|
|
147
|
+
// Drop only vars that redirect which repo or config git uses. Keep
|
|
148
|
+
// GIT_SSH_COMMAND, GIT_SSH, GIT_ASKPASS, GIT_TERMINAL_PROMPT, and proxies.
|
|
149
|
+
const GIT_REDIRECT = new Set([
|
|
150
|
+
'GIT_DIR', 'GIT_WORK_TREE', 'GIT_COMMON_DIR', 'GIT_INDEX_FILE',
|
|
151
|
+
'GIT_OBJECT_DIRECTORY', 'GIT_ALTERNATE_OBJECT_DIRECTORIES', 'GIT_NAMESPACE',
|
|
152
|
+
'GIT_CEILING_DIRECTORIES', 'GIT_DISCOVERY_ACROSS_FILESYSTEM', 'GIT_CONFIG',
|
|
153
|
+
'GIT_CONFIG_GLOBAL', 'GIT_CONFIG_SYSTEM', 'GIT_CONFIG_NOSYSTEM',
|
|
154
|
+
'GIT_CONFIG_PARAMETERS', 'GIT_CONFIG_COUNT',
|
|
155
|
+
]);
|
|
156
|
+
|
|
157
|
+
function gitEnv() {
|
|
158
|
+
const env = { ...process.env };
|
|
159
|
+
for (const key of Object.keys(env)) {
|
|
160
|
+
if (GIT_REDIRECT.has(key) || /^GIT_CONFIG_(?:KEY|VALUE)_\d+$/.test(key)) delete env[key];
|
|
161
|
+
}
|
|
162
|
+
return env;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function gitIn(dir, args) {
|
|
166
|
+
// 1 MiB default maxBuffer raises ENOBUFS on a large status and must not look clean.
|
|
167
|
+
return spawnSync('git', ['-C', dir, ...args], {
|
|
168
|
+
encoding: 'utf8', env: gitEnv(), maxBuffer: 64 * 1024 * 1024,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function sameReal(a, b) {
|
|
173
|
+
try { return fs.realpathSync(a) === fs.realpathSync(b); } catch (_) { return false; }
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function isEmptyDir(dir) {
|
|
177
|
+
try { return fs.statSync(dir).isDirectory() && fs.readdirSync(dir).length === 0; } catch (_) { return false; }
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Null when dir is a coco-research/coco clone. Git missing or an unreadable origin fails closed.
|
|
181
|
+
function cloneRejection(dir) {
|
|
182
|
+
if (!fs.existsSync(dir)) return 'it does not exist';
|
|
183
|
+
let name = null;
|
|
184
|
+
try { name = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf8')).name; } catch (_) { name = null; }
|
|
185
|
+
if (name !== 'cocosuperintelligence') return 'package.json name is not "cocosuperintelligence"';
|
|
186
|
+
let gitSt = null;
|
|
187
|
+
try { gitSt = fs.statSync(path.join(dir, '.git')); } catch (_) { gitSt = null; }
|
|
188
|
+
if (!gitSt || (!gitSt.isDirectory() && !gitSt.isFile())) return 'it has no .git directory or file';
|
|
189
|
+
const top = gitIn(dir, ['rev-parse', '--show-toplevel']);
|
|
190
|
+
if (top.error && top.error.code === 'ENOENT') return 'its origin could not be verified; remove the directory by hand';
|
|
191
|
+
// A .git file of `gitdir: <other>/.git` still reports this directory as toplevel.
|
|
192
|
+
// Accept only this dir's own .git, or a linked worktree whose gitdir file points back here.
|
|
193
|
+
const gitDirR = gitIn(dir, ['rev-parse', '--absolute-git-dir']);
|
|
194
|
+
const gitDir = String(gitDirR.stdout || '').trim();
|
|
195
|
+
let owns = gitDirR.status === 0 && sameReal(gitDir, path.join(dir, '.git'));
|
|
196
|
+
if (!owns && gitDir) {
|
|
197
|
+
try {
|
|
198
|
+
const back = fs.readFileSync(path.join(gitDir, 'gitdir'), 'utf8').trim();
|
|
199
|
+
owns = sameReal(path.resolve(gitDir, back), path.join(dir, '.git'));
|
|
200
|
+
} catch (_) { owns = false; }
|
|
201
|
+
}
|
|
202
|
+
if (top.status !== 0 || !sameReal(String(top.stdout || '').trim(), dir) || !owns) {
|
|
203
|
+
return 'its git toplevel is not this directory';
|
|
204
|
+
}
|
|
205
|
+
// Raw stored value. `remote get-url` applies insteadOf, so an alias can look official.
|
|
206
|
+
const remote = gitIn(dir, ['config', '--local', '--get', 'remote.origin.url']);
|
|
207
|
+
if ((remote.error && remote.error.code === 'ENOENT') || remote.status !== 0) {
|
|
208
|
+
return 'its origin could not be verified; remove the directory by hand';
|
|
209
|
+
}
|
|
210
|
+
if (!ORIGIN_RE.test(String(remote.stdout || '').trim())) {
|
|
211
|
+
return 'its origin must be stored as a github.com/coco-research/coco URL';
|
|
212
|
+
}
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Names of local work, or null when a check errored or exited non-zero (fail closed).
|
|
217
|
+
// untracked=false for update: ~/.coco holds untracked Coco state (knowledge/, sessions/, m0-token)
|
|
218
|
+
// that a plain checkout keeps.
|
|
219
|
+
function localWork(dir, untracked = true) {
|
|
220
|
+
const gitOut = (args) => {
|
|
221
|
+
const r = gitIn(dir, args);
|
|
222
|
+
if (r.error || r.status !== 0) return null;
|
|
223
|
+
return String(r.stdout || '').trim();
|
|
224
|
+
};
|
|
225
|
+
// CLI cache and the Codex adapter's generated si-commands/ are not local work.
|
|
226
|
+
const status = gitOut(['status', '--porcelain', `--untracked-files=${untracked ? 'all' : 'no'}`, '--', '.', ':(exclude).update-check.json', ':(exclude)si-commands']);
|
|
227
|
+
const stash = gitOut(['stash', 'list']);
|
|
228
|
+
// HEAD: the install is detached at the pin, so a commit there is on no branch.
|
|
229
|
+
// Release tags only: the pinned tag is not local work, but a local `git tag wip` is.
|
|
230
|
+
const ahead = gitOut(['rev-list', 'HEAD', '--branches', '--not', '--remotes', '--tags=v[0-9]*']);
|
|
231
|
+
if (status === null || stash === null || ahead === null) return null;
|
|
232
|
+
const found = [];
|
|
233
|
+
if (status) found.push('uncommitted changes');
|
|
234
|
+
if (stash) found.push('a stash');
|
|
235
|
+
if (ahead) found.push('unpushed commits');
|
|
236
|
+
return found;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function refuseClone(dir, why) {
|
|
240
|
+
console.error(`Not removing ${dir}: ${why}. Nothing was deleted.`);
|
|
241
|
+
process.exit(2);
|
|
242
|
+
}
|
|
243
|
+
|
|
140
244
|
function cloneOrUpdate(dir) {
|
|
141
|
-
|
|
245
|
+
const empty = isEmptyDir(dir);
|
|
246
|
+
if (fs.existsSync(dir) && !empty) {
|
|
247
|
+
const why = cloneRejection(dir);
|
|
248
|
+
if (why) refuseClone(dir, why);
|
|
249
|
+
}
|
|
250
|
+
if (!empty && fs.existsSync(dir) && fs.existsSync(path.join(dir, '.git'))) {
|
|
142
251
|
// Detached HEAD is the tagged install. A branch checkout (typical `git clone` of
|
|
143
252
|
// main) must not be force-moved onto an older pin.
|
|
144
|
-
const head = spawnSync('git', ['symbolic-ref', '-q', 'HEAD'], { cwd: dir });
|
|
253
|
+
const head = spawnSync('git', ['symbolic-ref', '-q', 'HEAD'], { cwd: dir, env: gitEnv() });
|
|
145
254
|
if (head.status !== 0) {
|
|
255
|
+
// The checkout below would strand local commits on the pinned install. Untracked state is
|
|
256
|
+
// fine: without --force, git refuses to overwrite an untracked file and nothing is lost.
|
|
257
|
+
const found = localWork(dir, false);
|
|
258
|
+
if (found == null || found.length) {
|
|
259
|
+
console.error(`Not updating ${dir}: ${found == null ? 'the local-work check could not run' : `it has ${found.join(' and ')}`}. Move that work elsewhere or remove the clone. Nothing was changed.`);
|
|
260
|
+
process.exit(2);
|
|
261
|
+
}
|
|
146
262
|
console.log(`Coco already at ${dir} (detached). Updating to ${PINNED_TAG}...`);
|
|
147
263
|
run('git', ['fetch', '--tags', '--force', '--depth', '1', 'origin', `refs/tags/${PINNED_TAG}:refs/tags/${PINNED_TAG}`], { cwd: dir });
|
|
148
|
-
run('git', ['checkout',
|
|
264
|
+
run('git', ['checkout', PINNED_TAG], { cwd: dir });
|
|
149
265
|
} else {
|
|
150
266
|
console.log(`Coco already at ${dir}. Pulling latest...`);
|
|
151
267
|
run('git', ['pull', '--ff-only'], { cwd: dir });
|
|
152
268
|
}
|
|
153
269
|
} else {
|
|
154
|
-
if (fs.existsSync(dir)) {
|
|
155
|
-
console.error(`Error: ${dir} exists but is not a git repo. Move it or pick a different location.`);
|
|
156
|
-
process.exit(1);
|
|
157
|
-
}
|
|
158
270
|
console.log(`Cloning Coco ${PINNED_TAG} to ${dir}...`);
|
|
159
271
|
run('git', ['clone', '--branch', PINNED_TAG, '--depth', '1', REPO, dir]);
|
|
160
272
|
}
|
|
@@ -188,7 +300,7 @@ function cmdInstall(argv) {
|
|
|
188
300
|
|
|
189
301
|
function cmdUpdate(argv) {
|
|
190
302
|
const dir = argv[0] && !argv[0].startsWith('--') ? argv[0] : DEFAULT_DIR;
|
|
191
|
-
if (!fs.existsSync(path.join(dir, '.git'))) {
|
|
303
|
+
if (!isEmptyDir(dir) && !fs.existsSync(path.join(dir, '.git'))) {
|
|
192
304
|
console.error(`Error: ${dir} is not a Coco clone. Run \`npx cocosuperintelligence install\` first.`);
|
|
193
305
|
process.exit(1);
|
|
194
306
|
}
|
|
@@ -197,7 +309,21 @@ function cmdUpdate(argv) {
|
|
|
197
309
|
}
|
|
198
310
|
|
|
199
311
|
function cmdUninstall(argv) {
|
|
200
|
-
const
|
|
312
|
+
const force = argv.includes('--force');
|
|
313
|
+
const dirArg = argv.find((a) => !a.startsWith('--'));
|
|
314
|
+
const dir = path.resolve(dirArg || DEFAULT_DIR);
|
|
315
|
+
if (fs.existsSync(dir)) {
|
|
316
|
+
const why = cloneRejection(dir);
|
|
317
|
+
// Empty: no data to lose. tests/check-cli-uninstall-cleanup.sh uninstalls an empty dir.
|
|
318
|
+
let entries = 1; // not a readable directory (a file, no permission): refuse, never crash
|
|
319
|
+
try { entries = fs.readdirSync(dir).length; } catch (_) {}
|
|
320
|
+
if (why && entries) refuseClone(dir, why);
|
|
321
|
+
if (!why && !force) {
|
|
322
|
+
const found = localWork(dir);
|
|
323
|
+
if (found == null) refuseClone(dir, 'the local-work check could not run; pass --force to remove it');
|
|
324
|
+
if (found.length) refuseClone(dir, `it has ${found.join(' and ')}; pass --force to remove it`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
201
327
|
// Prefix match on the resolved clone path plus a trailing slash, so a clone
|
|
202
328
|
// named `coco` cannot also delete links into `coco-research` / `coco-connect`.
|
|
203
329
|
const prefix = dir.endsWith(path.sep) ? dir : dir + path.sep;
|
|
@@ -212,6 +338,15 @@ function cmdUninstall(argv) {
|
|
|
212
338
|
if (!fs.existsSync(home)) continue;
|
|
213
339
|
run('find', [home, '-type', 'l', '-lname', `${prefix}*`, '-delete']);
|
|
214
340
|
}
|
|
341
|
+
// grok also writes generated files (SI commands, config block, hooks); its installer removes them.
|
|
342
|
+
// Best-effort: an older pinned clone may not know --uninstall; never abort the uninstall over it.
|
|
343
|
+
const grokInstaller = path.join(dir, 'adapters', 'grok', 'install.sh');
|
|
344
|
+
if (fs.existsSync(path.join(os.homedir(), '.grok')) && fs.existsSync(grokInstaller)) {
|
|
345
|
+
const r = spawnSync('bash', [grokInstaller, '--uninstall'], { stdio: 'inherit' });
|
|
346
|
+
if (r.status !== 0) {
|
|
347
|
+
console.log('Note: grok installer cleanup failed (possibly an older pin without --uninstall); continuing.');
|
|
348
|
+
}
|
|
349
|
+
}
|
|
215
350
|
console.log(`Removing clone at ${dir}...`);
|
|
216
351
|
if (fs.existsSync(dir)) {
|
|
217
352
|
fs.rmSync(dir, { recursive: true, force: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cocosuperintelligence",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"description": "CoCo Super Intelligence — summon an advisory board of 495 world-class minds inside your AI coding session. A vendor-neutral orchestration layer for Claude Code, Cursor, and Codex: 228 skills (190 installed by default), 387 commands, 34 agents, and disk-persistent state. 100% local, no telemetry. Open-core: MIT core, proprietary Super Intelligence.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"coco": "bin/coco.js"
|