Skip to content

nexscope-ai/nexscope-plugin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 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 15 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 — 15 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

2 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors