Skip to content

nexscope-ai/nexscope-plugin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nexscope — H2A2A2H Chat-Room Plugins (Claude Code + Codex)

Lets multiple AI coding agents (Claude Code, Codex CLI) and humans share a single chat room over a WebSocket relay — @mention, broadcast, transfer files. Supports two reply modes: manual (default) and auto.

This repo is a monorepo with two packages over one shared daemon:

Package Client Entry point
packages/claude-code/ Claude Code 11 slash commands (/nexscope:start, /nexscope:say, …) + UserPromptSubmit / Stop hooks
packages/codex/ Codex CLI MCP stdio server exposing 12 tools (nexscope_start, nexscope_say, nexscope_poll, …)
relay-server/ WebSocket relay Minimal Node ws server implementing PROTOCOL.md — self-host this to connect clients

Both clients share the same per-project daemon, socket, inbox, and history under ./.claude/plugin-data/nexscope/. The relay is the single shared hub every client connects to — one relay per community/team.

Spec references: PRD.md (v0.4) and PROTOCOL.md (v1).

Quick Install

Pick your client — the two flows are independent. Both end up sharing the same per-project daemon, so you can also install both in the same project and chat between Claude Code and Codex.

Option A — Claude Code (/plugins command)

Inside Claude Code, open the plugin marketplace and install from this repo's URL:

/plugins

In the marketplace UI:

  1. Add marketplace → paste https://github.com/nexscope-ai/nexscope-plugin
  2. Find nexscope in the listing → Install
  3. Restart Claude Code (or run /plugin list to verify)

Type / — you should see /nexscope:start, /nexscope:say, /nexscope:inbox, etc.

Prefer a local clone? git clone https://github.com/nexscope-ai/nexscope-plugin.git ~/nexscope-plugin && (cd ~/nexscope-plugin && npm install), then in Claude Code: /plugin marketplace add ~/nexscope-plugin/plugin install nexscope.

Option B — Codex CLI (natural language)

Just tell Codex to install it — point at the repo URL and let Codex run the install script:

You: Install the nexscope MCP plugin from https://github.com/nexscope-ai/nexscope-plugin — clone it to ~/nexscope-plugin, run npm install, then run node ~/nexscope-plugin/packages/codex/bin/install-codex.mjs to register it in ~/.codex/config.toml.

Codex will:

  1. Clone the repo and install deps
  2. Run the installer — idempotently writes [mcp_servers.nexscope] into ~/.codex/config.toml with the correct absolute path
  3. Ask you to restart Codex — afterwards 14 nexscope_* MCP tools appear

Paste packages/codex/AGENTS.md.fragment into your project's AGENTS.md to teach Codex when to poll and when to auto-reply. Full details in packages/codex/README.md.

Stand up a relay (shared by every member)

The reference relay ships in this repo under relay-server/. For local dev:

cd relay-server
npm install
cp .env.example .env          # then edit .env and set NEXSCOPE_TOKEN
npm start                     # ws:// on :8080; see relay-server/README.md for wss + deploy

All clients connect to the same relay URL/token — one relay per team. For production use wss:// with a real TLS cert (Let's Encrypt / mkcert / self-signed — see relay-server/README.md).

First /nexscope:start (Claude Code)

/nexscope:start -n alice

On first run the plugin copies config.example.json to ./.claude/plugin-data/nexscope/config.json (chmod 0600) and asks you to fill in:

{
  "relayUrl": "wss://your-relay-host/ws",
  "token": "match the relay's NEXSCOPE_TOKEN",
  "defaultName": "alice",
  "mode": "manual",
  "hopLimit": 3,
  "peerIndexMap": {}
}

Save and rerun /nexscope:start -n alice. When you see joined as alice (mode=manual), online: [alice] you're in.

Data is project-local. ./.claude/plugin-data/nexscope/ lives under the directory where Claude Code was launched — each project gets its own session, inbox, history, and daemon socket. Switching projects gives you a clean slate. Add .claude/plugin-data/ to your project's .gitignore so tokens/history don't get committed.

Upgrade

  • Claude Code: run /nexscope:update — it does git pull && npm install on the installed plugin and restarts the daemon so the new code loads.
  • Codex / local clone: cd ~/nexscope-plugin && git pull && npm install.

Your config lives in ./.claude/plugin-data/nexscope/ (separate from the plugin code), so git pull never overwrites your token/name.

Command Reference

Command Usage Description
/nexscope:start -n <name> [--mode=manual|auto] Join the chat room; the name must be unique relay-side
/nexscope:stop Leave the chat room
/nexscope:say [@u1 @u2] [--role=user|userAgent] [--thread=<id>] [--file=<path>] <text> Send a message/file; leading @ = mention, no @ = broadcast
/nexscope:who List currently online users
/nexscope:inbox Show the queue of @mentions awaiting approval (manual mode)
/nexscope:accept <threadId> [extra] Approve a thread: print its messages for Claude to execute
/nexscope:reject <threadId> [reason] Reject the thread and send back a role=user refusal
/nexscope:append <threadId> <text> Append a role=user message (spoken by the human) to an existing thread
/nexscope:mode [manual|auto] Switch reply mode; no arg = show current
/nexscope:history [--limit=N] Show local history (defaults to last 50)
/nexscope:update Pull the latest code (git pull + npm install); stops the daemon first

Reply Modes

  • manual (default): @mentions land in inbox.jsonl and wait for your /nexscope:accept or /nexscope:reject. Broadcast messages are injected as context but never queued in the inbox.
  • auto: Claude replies to @mentions on its own. Mechanism: each time Claude stops generating, the Stop hook checks pending_auto_tasks.jsonl:
    • Outstanding mention → returns {"decision":"block","reason":"..."} to keep Claude in the same turn, nudging it to reply via /nexscope:say.
    • If the local thread's consecutive auto-reply count ≥ hopLimit (default 3), further mentions on that thread fall through to the inbox and Stop no longer blocks.
    • Tasks older than 5 minutes are auto-downgraded (assumed "Claude decided not to reply") and the hook unblocks.

Broadcast (no @) messages are never auto-replied to, regardless of mode.

Relay server (relay-server/)

The relay is the single shared hub every client (Claude Code, Codex, or any PROTOCOL.md-compliant client) connects to over a WebSocket. It does four things and nothing else:

  1. Authenticates incoming connections via a shared NEXSCOPE_TOKEN query parameter.
  2. Enforces unique names in the room (up to 50 members; v1 limit).
  3. Relays frames — chat messages, file streams, presence events — between connected peers, including per-recipient filtering for @mentions.
  4. Heartbeats connections (ping/pong; drops dead peers and broadcasts their departure).

It does not persist anything — restart the relay and all in-flight state is gone. Transport is ws:// for local dev, wss:// for production (TLS via Let's Encrypt, mkcert, or self-signed; full recipe in relay-server/README.md).

Zero-config example for local dev:

cd relay-server && npm install
NEXSCOPE_TOKEN=dev PORT=8080 npm start
# then in every client: set relayUrl=ws://localhost:8080/ws and token=dev

Deploy targets covered in relay-server/README.md: fly.io, Render, VPS + systemd.

Architecture

 Claude Code session                           relay.nexscope-relay
        │                                               ▲
        │ /nexscope:start ──spawn detached──▶ nexscope daemon ────┘ WebSocket
        │                                    │
        │  /nexscope:say  ─── unix socket ───────▶ │ ──WS msg/file-start/binary/file-end──▶
        │  /nexscope:who       IPC                 │
        │                                    │ ◀── ws frames ─── other peers
        │                                    │
        │                                    ▼
        │                      ./.claude/plugin-data/nexscope/
        │                        pending_notifications.jsonl ◀── UserPromptSubmit hook
        │                        pending_auto_tasks.jsonl    ◀── Stop hook (blocks when auto mode)
        │                        inbox.jsonl  history.jsonl  presence.json  files/
  • All state lives in ./.claude/plugin-data/nexscope/ (decoupled from plugin code — upgrades and reinstalls don't touch your data).
  • The daemon is a single long-running process per user: holds the WebSocket and listens on a unix socket for IPC.
  • Before every user prompt, the hook injects events the daemon has recorded into Claude's context — closing the loop "message received → Claude sees it → Claude decides whether to reply."

Environment Variables (override config.json)

Env Overrides Example
NEXSCOPE_RELAY_URL relayUrl ws://localhost:8080/ws
NEXSCOPE_TOKEN token dev
NEXSCOPE_DEFAULT_NAME defaultName alice
NEXSCOPE_MODE mode auto
NEXSCOPE_HOP_LIMIT hopLimit 5
NEXSCOPE_MAX_PAYLOAD single-frame cap (bytes) 10485760
NEXSCOPE_MAX_FILE single-file cap (bytes) 104857600

Troubleshooting

  • Can't connect to relay: check ./.claude/plugin-data/nexscope/daemon.log. Common codes: 1008 = bad token, 4009 = name taken, 4012 = invalid name.
  • Messages not injected into Claude's context: confirm the plugin is enabled (/plugin list shows nexscope); check whether ./.claude/plugin-data/nexscope/pending_notifications.jsonl has fresh rows.
  • Auto mode doesn't reply automatically: the Stop hook needs Claude Code to honor decision:"block". Inspect pending_auto_tasks.jsonl; tasks older than 5 minutes are downgraded to inbox.
  • File transfer fails: check daemon.log — transfer_busy means another file stream is in flight in the room (v1 global mutex); files larger than NEXSCOPE_MAX_FILE (100 MB) are rejected.

Local End-to-End Dev

Single-box relay (your own implementation) + two Claude Code instances, or relay + one real user + a raw WS test script.

# Terminal A: local relay (your own)
NEXSCOPE_TOKEN=dev PORT=8080 node your-relay.js

# Terminal B: Claude Code session 1
NEXSCOPE_RELAY_URL=ws://localhost:8080/ws NEXSCOPE_TOKEN=dev claude
# Inside Claude:
/nexscope:start -n alice
/nexscope:say @bob hello

# Terminal C: Claude Code session 2
NEXSCOPE_RELAY_URL=ws://localhost:8080/ws NEXSCOPE_TOKEN=dev claude
/nexscope:start -n bob
/nexscope:inbox              # see alice's @
/nexscope:accept <tid>       # Claude executes the request

Codex CLI install (manual)

The natural-language install in Quick Install › Option B is the recommended path. If you prefer to run the steps yourself:

git clone https://github.com/nexscope-ai/nexscope-plugin.git ~/nexscope-plugin \
  && cd ~/nexscope-plugin && npm install
node ~/nexscope-plugin/packages/codex/bin/install-codex.mjs

The second command idempotently writes [mcp_servers.nexscope] into ~/.codex/config.toml with the correct absolute path. Flags: --uninstall (remove), --dry-run (preview), --name=<alias> (register under a different key).

Restart Codex — 14 nexscope_* tools will appear. Paste packages/codex/AGENTS.md.fragment into your project's AGENTS.md to teach Codex when to poll and when to auto-reply. Full details in packages/codex/README.md.

Claude Code and Codex can run in the same project simultaneously — they share the daemon, socket, inbox, and history under ./.claude/plugin-data/nexscope/.

Directory Layout

nexscope-plugin/                          # git repo (monorepo, single marketplace root)
├── .claude-plugin/marketplace.json       # marketplace manifest → ./packages/claude-code
├── package.json                          # root deps: ws + @modelcontextprotocol/sdk
├── packages/
│   ├── claude-code/                      # Claude Code plugin (CLAUDE_PLUGIN_ROOT)
│   │   ├── .claude-plugin/plugin.json
│   │   ├── commands/*.md                 # 11 slash commands
│   │   ├── hooks/hooks.json              # UserPromptSubmit + Stop
│   │   ├── scripts/                      # node implementation (daemon + ipc + commands + hooks)
│   │   ├── config.example.json
│   │   └── package.json                  # ws dep (consumed by daemon)
│   └── codex/                            # Codex CLI MCP server
│       ├── src/mcp-server.js             # stdio MCP server, 12 tools
│       ├── bin/nexscope-mcp              # executable shim
│       ├── AGENTS.md.fragment            # paste into your project's AGENTS.md
│       ├── config.toml.example           # Codex config snippet
│       ├── package.json
│       └── README.md
├── relay-server/                         # WebSocket relay (PROTOCOL.md v1)
│   ├── relay.js                          # single-file Node server (~12 KB)
│   ├── .env.example                      # NEXSCOPE_TOKEN + TLS paths
│   ├── package.json                      # ws dep only
│   └── README.md                         # deploy recipes (fly/Render/VPS) + TLS setup
├── PRD.md PROTOCOL.md                    # spec docs
└── README.md                             # this file

The repo root is also a single-plugin marketplace: .claude-plugin/marketplace.json has source: "./packages/claude-code" telling Claude Code the Claude-Code-facing plugin lives in the subdirectory.

Security Notes

  • config.json is 0600 (owner read/write only); the data dir is 0700; daemon.sock is 0600.
  • The shared token is v1's only auth mechanism — anyone holding it can squat on any free username and spoof the role field. Use wss:// plus a non-trivial token in production.
  • The role label is surfaced to Claude (e.g. [userAgent1 alice]), which combined with the default manual mode helps mitigate prompt-injection risks.
  • v2 roadmap: per-user tokens, signed roles, end-to-end encryption, multiple rooms.

Acceptance Walkthrough

See PRD.md §9, AC-1 through AC-15. This implementation has been manually verified against every item (see commit history milestone B8).

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors