feat: unified npx installer across all hivemind assistants#75
feat: unified npx installer across all hivemind assistants#75
Conversation
One command installs hivemind into every supported assistant (Claude Code,
Codex, OpenClaw) with a single browser-based login shared across all three:
npx @activeloop/hivemind@latest install
The CLI auto-detects ~/.claude, ~/.codex, ~/.openclaw and wires each with
its existing bundle. Marketplace and ClawHub install paths keep working;
all three paths converge on the same filesystem layout and credentials.
- New src/cli/ and bundle/cli.js esbuild target
- Package renamed to @activeloop/hivemind (previous 'hivemind' on npm is
squatted since 2014); openclaw plugin npmSpec updated to match
- codex/install.sh reduced to a shim that execs the unified CLI;
README and codex/INSTALL.md lead with the single npx line
|
Claude finished @kaghni's task in 2m 12s —— View job
Found 2 issues (inline comments posted):
|
| if (existsSync(srcSkills)) copyDir(srcSkills, join(PLUGIN_DIR, "skills")); | ||
|
|
||
| tryEnableCodexHooks(); | ||
| writeJson(HOOKS_PATH, buildHooksJson()); |
There was a problem hiding this comment.
Data loss: existing Codex hooks are silently overwritten. Unlike the Claude installer which has mergeHooks that strips only hivemind entries and preserves everything else, this call replaces the entire hooks.json on every install — any hooks the user added (e.g., a custom PostToolUse hook) are deleted without warning.
Read the existing file first, strip old hivemind entries by path, then merge buildHooksJson() into the result:
| writeJson(HOOKS_PATH, buildHooksJson()); | |
| const existing = readJson<{ hooks?: Record<string, unknown[]> }>(HOOKS_PATH) ?? {}; | |
| const ours = buildHooksJson(); | |
| const merged: Record<string, unknown[]> = { ...(existing.hooks ?? {}) }; | |
| for (const [event, entries] of Object.entries(ours.hooks)) { | |
| const stripped = (merged[event] ?? []).filter( | |
| (e: unknown) => !((e as { hooks?: { command?: string }[] })?.hooks?.[0]?.command?.includes(`${PLUGIN_DIR}/bundle/`)) | |
| ); | |
| merged[event] = [...stripped, ...entries]; | |
| } | |
| writeJson(HOOKS_PATH, { ...existing, hooks: merged }); |
|
|
||
| ensureDir(PLUGIN_DIR); | ||
| copyDir(srcDist, join(PLUGIN_DIR, "dist")); | ||
| if (existsSync(srcManifest)) copyDir(srcManifest, join(PLUGIN_DIR, "openclaw.plugin.json")); |
There was a problem hiding this comment.
Wrong function for single-file copy. copyDir calls cpSync with { recursive: true } and is designed for directories; calling it on a file path works today but is semantically wrong — if PLUGIN_DIR ever contains an existing directory named openclaw.plugin.json, the file lands inside it instead of replacing it. Use copyFileSync for individual files.
| if (existsSync(srcManifest)) copyDir(srcManifest, join(PLUGIN_DIR, "openclaw.plugin.json")); | |
| if (existsSync(srcManifest)) copyFileSync(srcManifest, join(PLUGIN_DIR, "openclaw.plugin.json")); | |
| if (existsSync(srcPkg)) copyFileSync(srcPkg, join(PLUGIN_DIR, "package.json")); |
Summary
One command installs hivemind into every supported assistant — Claude Code, Codex, OpenClaw — with a single browser-based login shared across all three:
The CLI auto-detects
~/.claude,~/.codex,~/.openclawand wires each with the existing platform bundle. Marketplace (Claude Code) and ClawHub (OpenClaw) install paths keep working as discovery surfaces; all three paths converge on the same filesystem layout and the same~/.deeplake/credentials.json, so users land in the same state regardless of entry point.What changed
src/cli/— platform detection, per-assistant installers, thin wrapper around the existing device-flow loginbundle/cli.js;hivemindbin added topackage.jsonhivemindto@activeloop/hivemind— the unscoped name on npm has been squatted by an unrelated 2014 package ("Awesome web platform for distributed projects" byamark); our OpenClaw manifestnpmSpecwas pointing at that squatted name and is now correctedcodex/install.shreduced to a one-line shim that execs the unified CLIREADME.mdandcodex/INSTALL.mdlead with the singlenpxline; per-assistant marketplace instructions moved into collapsible "Alternative install paths"Subcommands
Test plan
npm run typecheckcleannpm run buildclean (9 CC + 8 Codex + 1 OpenClaw + 1 CLI bundle)npm packproduces 34-file tarball; all expected artifacts presentnpm install -g ./tarball.tgzinto a throwaway prefix works;hivemindbin exposed~/.deeplake/credentials.jsonreused across all installs, no repeated browser popupinstallyields 8 Claude hooks + 5 Codex hooks (no duplicates)uninstall: settings.json cleared,~/.codex/hooks.jsonremoved, skill symlink removed, OpenClaw plugin dir removed--only <platforms>filter works~/.codex→ onlyclaude,clawtargetedFollow-ups (not in this PR)
@activeloop/hivemindto npm (first publish creates the@activeloopscope)npmSpec: @activeloop/hivemindis live in the registryengines.nodefrom>=22to>=20so Node 20 users don't see anEBADENGINEwarning onnpx