npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

squad-openclaw

v2026.2.2708

Published

Entity registry, filesystem tools, and version management plugin for OpenClaw gateway

Readme

squad-openclaw

OpenClaw gateway plugin for Squad — provides entity registry, locked-down filesystem tools, agent setup wrappers, plugin safety controls, and Tailnet internal routes for onboarding helpers.

Features

| Tool / Method / Endpoint | Description | |---|---| | entity_list, entity_search, entity_sync | In-memory entity registry with filesystem watching (agents, skills, plugins, tools, media) | | fs_read, fs_write, fs_list, fs_delete, fs_rename, fs_mkdir | Remote filesystem access for browser clients (subject to security restrictions below) | | squad.agents.add | Plugin wrapper for creating agent scaffolding (workspace seed files, sessions skeleton, and config list entry) | | squad.version.check | Plugin version reporting | | squad.questions.validate-envelope | HUMAN_INPUT_REQUIRED envelope validation | | squad.extensions.list, squad.extensions.update, squad.extensions.updateStatus | Installed extension metadata, cached version checks, and update lifecycle status | | squad.gateway.restart | Trigger gateway restart for extension-update activation | | tools.invoke, tools.list, squad.layout.get | Core plugin RPC entrypoints for tool invocation/listing and gateway layout metadata | | squad.plugin.status, squad.plugin.recover, squad.plugin.disable | Plugin safety-state RPC control (status, recovery, manual disable) | | GET /squad-internal/health | Tailnet internal health + pairing capability metadata | | GET /squad-internal/plugin/status | Tailnet internal plugin safety-state status | | POST /squad-internal/plugin/recover, POST /squad-internal/plugin/disable | Tailnet internal plugin safety-state controls | | POST /squad-internal/pairing/request, GET /squad-internal/pairing/status | Tailnet internal pairing helper routes with origin/Tailnet/browser-proof checks |

Internal Endpoint Reference

All /squad-internal/* routes enforce Tailnet context and origin checks. CORS preflight (OPTIONS) is handled for these routes.

| Route | Method | Purpose | |---|---|---| | /squad-internal/health | GET | Returns plugin safety snapshot and pairing capability hints | | /squad-internal/plugin/status | GET | Returns current plugin safety state | | /squad-internal/plugin/recover | POST | Recovers plugin safety state back to active (unless env kill-switch is set) | | /squad-internal/plugin/disable | POST | Manually disables plugin safety state | | /squad-internal/pairing/request | POST | Creates pairing request via gateway-native pairing methods (node/devices/device.pair.request) | | /squad-internal/pairing/status | GET | Resolves pairing status via gateway-native status methods (node/devices/device.pair.status/get) |

Extension-management routes intentionally do not expose install commands. Only update/status/restart are available via RPC methods.

State Directory Resolution

All paths in this plugin (and throughout this README) that reference ~/.openclaw resolve via environment override when set. This supports Docker and other containerized deployments where the OpenClaw data directory may not be at the default location.

Resolution priority:

  1. OPENCLAW_STATE_DIR (canonical)
  2. OPENCLAW_DIR (compat alias)
  3. os.homedir() + "/.openclaw" (default)

| Environment | Typical path | How it's resolved | |---|---|---| | Standard install | ~/.openclaw | Default — os.homedir() + "/.openclaw" | | Docker | /data/.openclaw | OPENCLAW_STATE_DIR=/data/.openclaw (or OPENCLAW_DIR=/data/.openclaw) | | Custom / NAS | /mnt/data/.openclaw | OPENCLAW_STATE_DIR=/mnt/data/.openclaw |

This variable only controls where the plugin looks for OpenClaw's own data directory. It does not grant the plugin access to the parent directory or any other part of the filesystem. All security restrictions (blocked directories, allowed roots, write protection) are enforced relative to the resolved state directory — not the filesystem root.

The resolution logic lives in a single shared module (src/paths.ts) imported by every file that needs the state directory path.

Docker Workspace Mapping

If your container mounts the real workspace outside the OpenClaw state directory (for example, /data/workspace), create a symlink so OpenClaw-compatible tools can still resolve .../.openclaw/workspace:

mkdir -p /data/.openclaw /data/workspace
ln -sfn /data/workspace /data/.openclaw/workspace

Then start your gateway/server with explicit env vars (useful when .env is not loaded):

PORT=3334 \
OPENCLAW_STATE_DIR=/data/.openclaw \
OPENCLAW_DIR=/data/.openclaw \
node server.js

Quick verification:

ls -ld /data/.openclaw /data/.openclaw/workspace /data/workspace /data/.openclaw/openclaw.json

Security Model

This plugin enforces a defense-in-depth security model with four independent layers. All security rules are hard-coded and non-configurable (except allowedRoots) so they can be verified by reading the source code. The bundle is intentionally not minified to allow security auditing of the distributed code.

Note: Throughout this section, ~/.openclaw refers to the resolved state directory (see above). In Docker or custom installs, substitute the actual path set by OPENCLAW_STATE_DIR.

Layer 1: Blocked Directories (hardcoded, non-configurable)

These directories are completely blocked from all filesystem operations (read, write, list, delete, rename):

| Path | Contents | |---|---| | ~/.openclaw/credentials/ | OAuth tokens, API keys | | ~/.openclaw/devices/ | Device pairing secrets, private keys | | ~/.openclaw/identity/ | Operator identity material |

Layer 1b: Blocked Files (hardcoded, non-configurable)

| Path | Reason | |---|---| | ~/.openclaw/squad-ceo-data/relay/squad-relay.json | Legacy relay-state material from older transport flows (blocked to prevent accidental secret disclosure) | | ~/.openclaw/*.bak | Backup files at the top level contain unredacted config (tokens, keys) that would bypass redaction |

Layer 2: Redacted Files (hardcoded, non-configurable)

~/.openclaw/openclaw.json is readable but with sensitive fields replaced with "[REDACTED]" before returning to clients:

  • channels.*.botToken — channel bot tokens
  • gateway.auth.* — all auth keys
  • gateway.token — legacy token location
  • gateway.remote.token — legacy remote token

Layer 3: Allowed Roots (configurable, defaults to ~/.openclaw)

Filesystem operations are restricted to configured root directories. By default, only ~/.openclaw/ is accessible — covering all application needs:

  • ~/.openclaw/squad-ceo-data/ — entity databases, data files
  • ~/.openclaw/media/ — asset uploads
  • ~/.openclaw/workspace*/ — agent workspaces
  • ~/.openclaw/skills/ — skill definitions
  • ~/.openclaw/extensions/ — plugin manifests

Operators can customize via the fs.allowedRoots config option.

Layer 4: Filesystem Write Protection

These files/directories cannot be written via filesystem tools (fs_write, fs_rename, etc.), even if they fall within allowedRoots:

  • ~/.openclaw/openclaw.json — operator configuration (tool-level read-only with redaction)
  • ~/.openclaw/squad-ceo-data/relay/squad-relay.json — legacy relay-state secret file (blocked)
  • All blocked directories above (credentials, devices, identity)
  • All .bak files at ~/.openclaw/ top level

Startup Config Migration (one-time, localized)

On plugin startup, Squad runs an internal migration harness. Current migration behavior:

  • Checks ~/.openclaw/squad-ceo-data/migrations.json for completed migration IDs.
  • If 001-enable-main-subagent-access is not recorded, applies a localized config.patch that sets only:
    • agents.defaults.maxConcurrent = 4
    • agents.defaults.subagents.maxConcurrent = 8
    • agents.list[id=main].identity.name = "Pepper"
    • agents.list[id=main].tools.allow = ["*"]
    • agents.list[id=main].subagents.allowAgents = ["*"]
  • Records completion in ~/.openclaw/squad-ceo-data/migrations.json.

This migration is designed to run once. If an operator later changes these values manually, the plugin does not overwrite them again because the migration is already marked complete.

Plugin Safety State (Kill Switch + Quarantine)

The plugin persists runtime safety state in:

  • ~/.openclaw/squad-ceo-data/safety/plugin-state.json

State values:

  • ACTIVE
  • DISABLED_MANUAL
  • QUARANTINED_AUTO

Behavior:

  • If disabled/quarantined, plugin methods return typed errors (PLUGIN_DISABLED / PLUGIN_QUARANTINED) instead of crashing startup/runtime.
  • Quarantine auto-expires after a cooldown window and transitions back to ACTIVE.
  • Environment kill switch overrides persisted state and is authoritative.

Environment controls:

  • SQUAD_PLUGIN_DISABLED=1 — force disable plugin
  • SQUAD_PLUGIN_DISABLE_REASON="..." — optional operator-facing reason
  • SQUAD_PLUGIN_FAILURE_THRESHOLD — failures before auto-quarantine (default 3)
  • SQUAD_PLUGIN_FAILURE_WINDOW_MS — failure counting window (default 300000)
  • SQUAD_PLUGIN_QUARANTINE_MS — quarantine duration (default 600000)

Recovery paths:

  • RPC: openclaw gateway call squad.plugin.recover --json
  • HTTP (Tailnet): POST /squad-internal/plugin/recover
  • If env kill switch is active, unset SQUAD_PLUGIN_DISABLED and restart gateway.

Tailnet Pairing and Locator Security

The active onboarding path is Tailnet-direct and gateway-owned:

  • Browser connects directly to wss://<gateway>.ts.net
  • OpenClaw gateway enforces pairing approval state
  • Relay service is used for account auth and locator metadata only

Pairing Model (Current)

Pairing does not rely on plugin-owned approval state:

  1. Browser receives gateway connect.challenge
  2. Browser signs challenge with its per-browser device key
  3. Browser sends native connect request
  4. If unpaired, gateway returns pairing-required error (with requestId when available)
  5. UI shows openclaw devices approve <requestId>
  6. UI polls reconnect automatically in the background until approved

This means approval is native to gateway pairing and not stored in plugin-local state.

Plugin Route Security (/squad-internal/pairing/*)

Pairing helper routes enforce:

  • Allowed browser origin (SQUAD_ALLOWED_ORIGINS or built-in defaults)
  • Tailnet context (Tailnet headers/hostname checks)
  • Browser proof (device ID/public key/signature/nonce/signedAt) on pairing request creation
  • Nonce freshness and per-device/IP rate limits

Pairing Helper Routes (Compatibility)

/squad-internal/pairing/request and /squad-internal/pairing/status are still present for compatibility, but the current SPA pairing flow no longer depends on them as primary path.

POST /squad-internal/pairing/request expects browser proof fields:

  • deviceId
  • publicKey (Ed25519) or publicKeyJwk (P-256)
  • signature
  • nonce
  • signedAt

GET /squad-internal/pairing/status expects:

  • requestId query param
  • deviceId query param

Legacy Relay-State File Handling

~/.openclaw/squad-ceo-data/relay/squad-relay.json is still blocked by filesystem security rules to protect historical secrets from older relay transport versions.

Remote Tool Invocation (tools.invoke)

The tools.invoke gateway method allows the browser to call plugin tools over WebSocket transport when direct HTTP tool calls are unavailable. This is not a generic RPC gateway — it is scoped exclusively to the tools registered by this plugin:

| Tool | What it can access | Restrictions | |---|---|---| | fs_read, fs_write, fs_list, fs_delete, fs_rename, fs_mkdir | ~/.openclaw/ only | All 4 security layers apply (blocked dirs, blocked files, redaction, allowed roots, write protection) | | entity_list, entity_search, entity_sync | In-memory entity index | Read-only metadata (names, types, paths) |

It cannot invoke gateway core tools (exec, bash, read, write, web_fetch, etc.) — only the tools this plugin registers via api.registerTool(). Every invoked tool enforces its own security restrictions independently — tools.invoke is just a transport layer, not a privilege escalation.

Build Transparency

The build configuration (tsup.config.ts) is optimized for security auditing:

| Setting | Value | Reason | |---|---|---| | minify | false | Unminified bundle for human/AI security review | | sourcemap | false | No internal path exposure | | treeshake | false | All code preserved for complete auditing |

Configuration

Configure in your gateway's openclaw.json under the plugin section:

| Key | Type | Default | Description | |---|---|---|---| | fs.allowedRoots | string[] | [resolved OpenClaw state dir] | Restrict filesystem operations to these directories. Hardcoded blocks on credentials/, devices/, identity/, legacy relay/squad-relay.json, and .bak files always apply regardless. |

Source Code

  • Repository: github.com/WorldBrain/squad
  • Plugin directory: extensions/squad-openclaw/
  • Security-critical files:
    • src/filesystem.ts — path blocking, redaction, write protection
    • src/agents.ts — wrapper for agent setup (workspace/session skeleton + config entry update)
    • src/http-routes.ts — Tailnet internal routes and browser-proof validation
    • src/shared-api.ts — gateway method + tool registration boundaries
    • src/plugin-safety-gateway.ts, src/plugin-safety-state.ts — plugin safety-state control and persistence

License

MIT