Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 23 additions & 23 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,11 @@ jobs:
- name: Build (typecheck + emit bundle artefacts)
# `build` runs `tsc && esbuild`, which is a strict superset of
# `typecheck` (the bare `tsc --noEmit` we used to run here). It
# ALSO produces the per-agent bundles AND `openclaw/dist/`. The
# ALSO produces the per-agent bundles AND `harnesses/openclaw/dist/`. The
# latter is gitignored, so it doesn't exist after a fresh
# `actions/checkout` — and several bundle-scan tests under
# `claude-code/tests/skillify-session-start-injection.test.ts` read
# `openclaw/dist/index.js` and `openclaw/dist/skillify-worker.js`
# `harnesses/claude-code/tests/skillify-session-start-injection.test.ts` read
# `harnesses/openclaw/dist/index.js` and `harnesses/openclaw/dist/skillify-worker.js`
# directly. Without this rebuild they fail with ENOENT (see PR #98
# — first CI run after the openclaw skillify wiring landed).
run: npm run build
Expand Down Expand Up @@ -294,19 +294,19 @@ jobs:
set -e
for f in \
bundle/cli.js \
claude-code/bundle/capture.js \
claude-code/bundle/session-start.js \
claude-code/bundle/session-end.js \
claude-code/bundle/plugin-cache-gc.js \
claude-code/bundle/skillify-worker.js \
codex/bundle/capture.js \
codex/bundle/session-start.js \
harnesses/claude-code/bundle/capture.js \
harnesses/claude-code/bundle/session-start.js \
harnesses/claude-code/bundle/session-end.js \
harnesses/claude-code/bundle/plugin-cache-gc.js \
harnesses/claude-code/bundle/skillify-worker.js \
harnesses/codex/bundle/capture.js \
harnesses/codex/bundle/session-start.js \
cursor/bundle/capture.js \
cursor/bundle/session-start.js \
hermes/bundle/capture.js \
hermes/bundle/session-start.js \
harnesses/hermes/bundle/capture.js \
harnesses/hermes/bundle/session-start.js \
mcp/bundle/server.js \
pi/bundle/skillify-worker.js; do
harnesses/pi/bundle/skillify-worker.js; do
if [ ! -f "$f" ]; then
echo "::error::expected bundle entrypoint missing: $f"
exit 1
Expand Down Expand Up @@ -417,19 +417,19 @@ jobs:
set -e
for f in \
bundle/cli.js \
claude-code/bundle/capture.js \
claude-code/bundle/session-start.js \
claude-code/bundle/session-end.js \
claude-code/bundle/plugin-cache-gc.js \
claude-code/bundle/skillify-worker.js \
codex/bundle/capture.js \
codex/bundle/session-start.js \
harnesses/claude-code/bundle/capture.js \
harnesses/claude-code/bundle/session-start.js \
harnesses/claude-code/bundle/session-end.js \
harnesses/claude-code/bundle/plugin-cache-gc.js \
harnesses/claude-code/bundle/skillify-worker.js \
harnesses/codex/bundle/capture.js \
harnesses/codex/bundle/session-start.js \
cursor/bundle/capture.js \
cursor/bundle/session-start.js \
hermes/bundle/capture.js \
hermes/bundle/session-start.js \
harnesses/hermes/bundle/capture.js \
harnesses/hermes/bundle/session-start.js \
mcp/bundle/server.js \
pi/bundle/skillify-worker.js; do
harnesses/pi/bundle/skillify-worker.js; do
if [ ! -f "$f" ]; then
echo "::error::expected bundle entrypoint missing: $f"
exit 1
Expand Down
28 changes: 14 additions & 14 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,12 @@ jobs:
git add -A
git add -f \
bundle \
claude-code/bundle \
codex/bundle \
harnesses/claude-code/bundle \
harnesses/codex/bundle \
cursor/bundle \
hermes/bundle \
harnesses/hermes/bundle \
mcp/bundle \
pi/bundle
harnesses/pi/bundle
git commit -m "release: v$VERSION"
RELEASE_SHA=$(git rev-parse HEAD)
echo "release_sha=$RELEASE_SHA" >> "$GITHUB_OUTPUT"
Expand All @@ -133,17 +133,17 @@ jobs:
# them on disk for npm publish).
git rm --cached -r \
bundle \
claude-code/bundle \
codex/bundle \
harnesses/claude-code/bundle \
harnesses/codex/bundle \
cursor/bundle \
hermes/bundle \
harnesses/hermes/bundle \
mcp/bundle \
pi/bundle
harnesses/pi/bundle
# Update marketplace.json's git-subdir source.sha to the release
# commit. Users doing `claude plugin marketplace add activeloopai/hivemind`
# clone main (HEAD = this cleanup commit), read marketplace.json, see
# the sha → clone activeloopai/hivemind at that sha (which DOES have
# bundles tracked) → extract `claude-code/` → install.
# bundles tracked) → extract `harnesses/claude-code/` → install.
node -e "
const fs = require('fs');
const path = '.claude-plugin/marketplace.json';
Expand Down Expand Up @@ -263,9 +263,9 @@ jobs:
- name: Build bundles
# Must run BEFORE the quality gate. `npm run ci` includes vitest,
# and the bundle-scan tests under
# claude-code/tests/skillify-session-start-injection.test.ts read
# openclaw/dist/index.js + openclaw/dist/skillify-worker.js
# directly. openclaw/dist/ is gitignored — it only exists after
# harnesses/claude-code/tests/skillify-session-start-injection.test.ts read
# harnesses/openclaw/dist/index.js + harnesses/openclaw/dist/skillify-worker.js
# directly. harnesses/openclaw/dist/ is gitignored — it only exists after
# `npm run build`. Without this step before the gate, vitest
# fails with ENOENT and the publish aborts. Same root cause as
# 64cac0b in ci.yml; that fix never propagated to this job.
Expand Down Expand Up @@ -336,8 +336,8 @@ jobs:
run: clawhub login --token "$CLAWHUB_TOKEN" --no-browser

- name: Publish openclaw bundle to ClawHub
# The release job above already synced openclaw/package.json and
# openclaw/openclaw.plugin.json versions to the bumped root
# The release job above already synced harnesses/openclaw/package.json and
# harnesses/openclaw/openclaw.plugin.json versions to the bumped root
# version, so this publishes the same X.Y.Z that npm just got.
#
# --family code-plugin: the existing `hivemind` package on ClawHub
Expand Down
8 changes: 4 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ deploy-to-cache.sh
# marketplace.json sha-pinned source can resolve to a bundle-containing
# commit; the very next commit untracks them so main HEAD stays clean.
bundle/
claude-code/bundle/
codex/bundle/
harnesses/claude-code/bundle/
harnesses/codex/bundle/
cursor/bundle/
hermes/bundle/
harnesses/hermes/bundle/
mcp/bundle/
pi/bundle/
harnesses/pi/bundle/
evals/
.cursor/
cursor_hivemind_environment_variables_c.md
4 changes: 2 additions & 2 deletions .jscpd.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"**/*.test.ts",
"**/tests/**",
"**/fixtures/**",
"**/claude-code/.claude-plugin/**",
"**/codex/.codex-plugin/**",
"**/harnesses/claude-code/.claude-plugin/**",
"**/harnesses/codex/.codex-plugin/**",
"**/src/hooks/cursor/wiki-worker.ts",
"**/src/hooks/cursor/spawn-wiki-worker.ts",
"**/src/hooks/cursor/capture.ts",
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,14 @@ Hivemind runs **alongside** OpenClaw's built-in `memory-core` plugin. It does **
Tell Codex to fetch and follow the install instructions:

```
Fetch and follow instructions from https://raw.githubusercontent.com/activeloopai/hivemind/main/codex/INSTALL.md
Fetch and follow instructions from https://raw.githubusercontent.com/activeloopai/hivemind/main/harnesses/codex/INSTALL.md
```

Or run the installer script directly:

```bash
git clone https://github.com/activeloopai/hivemind.git ~/.codex/hivemind
~/.codex/hivemind/codex/install.sh
~/.codex/hivemind/harnesses/codex/install.sh
```

Restart Codex to activate.
Expand Down Expand Up @@ -342,12 +342,12 @@ hivemind rules list # latest 10 active
hivemind rules edit <rule-id> "<new text>" # bumps version
hivemind rules done <rule-id> # mark closed

# Cross-agent diagnostic / pi/openclaw fallback
# Cross-agent diagnostic / harnesses/pi/openclaw fallback
hivemind context # print the injection block on demand
```

**What's injected at SessionStart** (claude-code, cursor, hermes. Codex is
deliberately excluded to keep its user-visible TUI clean; pi/openclaw
deliberately excluded to keep its user-visible TUI clean; harnesses/pi/openclaw
fall back to `hivemind context`):

```text
Expand Down Expand Up @@ -435,7 +435,7 @@ Setup, BYOC, agent integrations, or workflow. Come ask in the community:
git clone https://github.com/activeloopai/hivemind.git
cd hivemind
npm install
npm run build # tsc + esbuild → claude-code/bundle/ + codex/bundle/ + cursor/bundle/ + openclaw/dist/ + mcp/bundle/ + bundle/cli.js
npm run build # tsc + esbuild → harnesses/claude-code/bundle/ + harnesses/codex/bundle/ + cursor/bundle/ + harnesses/openclaw/dist/ + mcp/bundle/ + bundle/cli.js
npm test # vitest
```

Expand Down
12 changes: 6 additions & 6 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@ hivemind/
│ ├── hooks/codex/ ← Codex hooks
│ ├── hooks/cursor/ ← Cursor hooks
│ ├── hooks/hermes/ ← Hermes shell hooks
│ ├── hooks/pi/ ← pi wiki-worker (extension lives in pi/extension-source/)
│ ├── hooks/pi/ ← pi wiki-worker (extension lives in harnesses/pi/extension-source/)
│ ├── embeddings/ ← nomic embed-daemon + protocol + SQL helpers
│ ├── mcp/ ← MCP server (used by Hermes; available to any future MCP-aware client)
│ ├── commands/ ← auth, auth-creds, auth-login, session-prune
│ └── cli/ ← unified `hivemind install` CLI + per-agent installers
├── claude-code/ ← Claude Code plugin source (marketplace-distributed)
├── codex/ ← Codex plugin build output (npm-distributed)
├── harnesses/claude-code/ ← Claude Code plugin source (marketplace-distributed)
├── harnesses/codex/ ← Codex plugin build output (npm-distributed)
├── cursor/ ← Cursor plugin build output (npm-distributed)
├── hermes/ ← Hermes plugin build output (npm-distributed)
├── harnesses/hermes/ ← Hermes plugin build output (npm-distributed)
├── mcp/ ← MCP server build output (shared by Hermes + future MCP clients)
├── openclaw/ ← OpenClaw plugin source + build output (ClawHub-distributed)
├── pi/ ← pi extension source (ships raw .ts; pi compiles at load)
├── harnesses/openclaw/ ← OpenClaw plugin source + build output (ClawHub-distributed)
├── harnesses/pi/ ← pi extension source (ships raw .ts; pi compiles at load)
└── bundle/ ← unified `hivemind` CLI build output
```
44 changes: 22 additions & 22 deletions esbuild.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { chmodSync, writeFileSync, readFileSync } from "node:fs";

const esmPackageJson = '{"type":"module"}\n';
const hivemindVersion = JSON.parse(readFileSync("package.json", "utf-8")).version;
const openclawVersion = JSON.parse(readFileSync("openclaw/package.json", "utf-8")).version;
const openclawSkillBody = readFileSync("openclaw/skills/SKILL.md", "utf-8");
const openclawVersion = JSON.parse(readFileSync("harnesses/openclaw/package.json", "utf-8")).version;
const openclawSkillBody = readFileSync("harnesses/openclaw/skills/SKILL.md", "utf-8");

// Claude Code plugin
const ccHooks = [
Expand Down Expand Up @@ -54,7 +54,7 @@ await build({
bundle: true,
platform: "node",
format: "esm",
outdir: "claude-code/bundle",
outdir: "harnesses/claude-code/bundle",
external: [
"node:*",
"node-liblzma",
Expand Down Expand Up @@ -82,9 +82,9 @@ await build({
});

for (const h of ccAll) {
chmodSync(`claude-code/bundle/${h.out}.js`, 0o755);
chmodSync(`harnesses/claude-code/bundle/${h.out}.js`, 0o755);
}
writeFileSync("claude-code/bundle/package.json", esmPackageJson);
writeFileSync("harnesses/claude-code/bundle/package.json", esmPackageJson);

// Codex plugin
const codexHooks = [
Expand Down Expand Up @@ -122,7 +122,7 @@ await build({
bundle: true,
platform: "node",
format: "esm",
outdir: "codex/bundle",
outdir: "harnesses/codex/bundle",
external: [
"node:*",
"node-liblzma",
Expand All @@ -149,9 +149,9 @@ await build({
});

for (const h of codexAll) {
chmodSync(`codex/bundle/${h.out}.js`, 0o755);
chmodSync(`harnesses/codex/bundle/${h.out}.js`, 0o755);
}
writeFileSync("codex/bundle/package.json", esmPackageJson);
writeFileSync("harnesses/codex/bundle/package.json", esmPackageJson);

// Cursor plugin (1.7+ hooks API). Same shell + commands as the other agents.
const cursorHooks = [
Expand Down Expand Up @@ -253,7 +253,7 @@ await build({
bundle: true,
platform: "node",
format: "esm",
outdir: "hermes/bundle",
outdir: "harnesses/hermes/bundle",
external: [
"node:*",
"node-liblzma",
Expand All @@ -280,12 +280,12 @@ await build({
});

for (const h of hermesAll) {
chmodSync(`hermes/bundle/${h.out}.js`, 0o755);
chmodSync(`harnesses/hermes/bundle/${h.out}.js`, 0o755);
}

// Pi (badlogic/pi-mono) — ships a wiki-worker bundle, a skillify-worker
// bundle, and an autopull-worker bundle. The pi extension itself is raw .ts
// at pi/extension-source/hivemind.ts; we don't bundle it because pi's
// at harnesses/pi/extension-source/hivemind.ts; we don't bundle it because pi's
// runtime compiles + loads the .ts file directly. Embed daemon reuses the
// canonical ~/.hivemind/embed-deps/embed-daemon.js — no per-pi embed
// bundle needed. Skillify worker is the same shared module used by
Expand All @@ -306,7 +306,7 @@ await build({
bundle: true,
platform: "node",
format: "esm",
outdir: "pi/bundle",
outdir: "harnesses/pi/bundle",
external: [
"node:*",
"node-liblzma",
Expand All @@ -321,10 +321,10 @@ await build({
},
});
for (const h of piWorker) {
chmodSync(`pi/bundle/${h.out}.js`, 0o755);
chmodSync(`harnesses/pi/bundle/${h.out}.js`, 0o755);
}
writeFileSync("pi/bundle/package.json", esmPackageJson);
writeFileSync("hermes/bundle/package.json", esmPackageJson);
writeFileSync("harnesses/pi/bundle/package.json", esmPackageJson);
writeFileSync("harnesses/hermes/bundle/package.json", esmPackageJson);

// OpenClaw plugin bundle. The shared CC/Codex source modules reference a
// handful of HIVEMIND_* env vars for dev-only overrides. Those env paths are
Expand All @@ -333,13 +333,13 @@ writeFileSync("hermes/bundle/package.json", esmPackageJson);
// with `undefined` at build time to avoid shipping dead env-read code in the
// plugin bundle.
await build({
entryPoints: { index: "openclaw/src/index.ts" },
entryPoints: { index: "harnesses/openclaw/src/index.ts" },
bundle: true,
splitting: true,
chunkNames: "chunks/[name]-[hash]",
platform: "node",
format: "esm",
outdir: "openclaw/dist",
outdir: "harnesses/openclaw/dist",
external: ["node:*"],
// Guarantee `globalThis.__hivemind_tuning__` exists as an object before any
// bundled module's lazy env reads execute. esbuild's `define` rewrites
Expand Down Expand Up @@ -403,7 +403,7 @@ await build({
},
plugins: [{
// Dead-code elimination for transitively bundled CC/Codex-only features.
// openclaw/src/index.ts imports shared modules from ../../src/ (DeeplakeApi,
// harnesses/openclaw/src/index.ts imports shared modules from ../../../src/ (DeeplakeApi,
// grep-core, virtual-table-query, auth device-flow). Several of those
// modules also host CC-specific helpers that shell out with execSync —
// opening the browser for SSO, nudging claude-plugin-update, spawning the
Expand All @@ -425,7 +425,7 @@ await build({
},
}],
});
writeFileSync("openclaw/dist/package.json", esmPackageJson);
writeFileSync("harnesses/openclaw/dist/package.json", esmPackageJson);

// OpenClaw skillify-worker bundle. Same shared module CC/Codex/Cursor/Hermes/Pi
// use; openclaw spawns it from its agent_end hook to mine reusable skills out
Expand All @@ -436,15 +436,15 @@ writeFileSync("openclaw/dist/package.json", esmPackageJson);
// with no stubs.
// 2. The main bundle uses code splitting (chunks/), and we don't want the
// worker's modules entangled with the gateway's chunk graph.
// Lands at openclaw/dist/skillify-worker.js — install-openclaw.ts already
// Lands at harnesses/openclaw/dist/skillify-worker.js — install-openclaw.ts already
// copies the entire dist/ recursively, so it ships to
// ~/.openclaw/extensions/hivemind/dist/skillify-worker.js with no other change.
await build({
entryPoints: { "skillify-worker": "dist/src/skillify/skillify-worker.js" },
bundle: true,
platform: "node",
format: "esm",
outdir: "openclaw/dist",
outdir: "harnesses/openclaw/dist",
external: ["node:*"],
// Same banner as the main openclaw bundle — see the comment there for
// the rationale. The worker entry itself overwrites this with the
Expand Down Expand Up @@ -500,7 +500,7 @@ await build({
"process.env.HIVEMIND_STATE_DIR": "globalThis.__hivemind_tuning__.HIVEMIND_STATE_DIR",
},
});
chmodSync("openclaw/dist/skillify-worker.js", 0o755);
chmodSync("harnesses/openclaw/dist/skillify-worker.js", 0o755);

// Hivemind MCP server (stdio). Reused by Cline / Roo / Kilo / any MCP-aware
// agent. Lives at ~/.hivemind/mcp/server.js after install.
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Empty file added harnesses/cursor/.gitkeep
Empty file.
Empty file added harnesses/hermes/.gitkeep
Empty file.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading
Loading