SLOPSHOPPER

ts-demo

Fixture: a TypeScript mod that imports the claude-code SDK surface.

newguard
A shopper browsing a rack in a slop shop
README

<img src="doc_en/banner.svg" alt="OpenSquad" width="720" />

<strong>English</strong> | <a href="README_ZH.md">中文</a>

CI License: MIT Release Python 3.11+ Node 18+ Code style: ruff

Stars Forks Issues Last commit PRs Welcome

OpenSquad is a local-first multi-agent collaboration framework. Multiple autonomous agents (PM, Coder, QA, etc.) communicate via group chat to coordinate and complete complex tasks.


<img src="doc_en/screenshots/agent_web.png" alt="OpenSquad single-agent web workspace" width="900" />

<img src="doc_shared/screenshots/chat_group.png" alt="OpenSquad group chat" width="900" />


What is OpenSquad

OpenSquad enables multiple AI agents to collaborate like a real team. Each agent runs as an independent process with its own LLM connection, tool set, and memory. Agents communicate through group chat, coordinated by a PM agent, to tackle complex tasks that a single agent cannot handle alone.

What Problems It Solves

A single AI agent has clear limitations when dealing with complex projects:

  • Limited context window — Cannot handle the full context of requirements, coding, and testing simultaneously
  • Role confusion — One agent juggling multiple roles leads to oversight
  • No parallelism — Serial execution results in low efficiency
  • No review process — No independent QA role for quality assurance

OpenSquad solves these through multi-agent collaboration: PM handles task decomposition and coordination, Coder focuses on implementation, QA independently verifies — each with a clear responsibility.

Architecture (overview)

flowchart TB
    User["User / Web UI"] --> GW["Gateway :9555"]
    GW --> LA["Launcher :9600"]
    LA --> PM["PM Agent"]
    LA --> Dev["Coder Agent"]
    LA --> QA["QA Agent"]
    PM & Dev & QA --> IM["Group chat / IM"]
    PM & Dev & QA --> Plugins["Plugins / MCP / Skills"]
    Plugins --> Svc["Service plugins e.g. websearch :9001"]

Details: Architecture · Documentation hub

Key Features

  • Collab Card driven — Predefined workflow templates (software dev, code review, research, etc.) with PM coordinating the team per card protocol
  • Group chat communication — Agents collaborate via natural language group chat with @mentions, sleep/wake, and status queries
  • Independent process architecture — Each agent runs independently, can be restarted and configured separately
  • Long-term memory — Cross-session semantic memory system for agents to accumulate experience and knowledge
  • Interruptible sleep — Agents can proactively sleep and wait for events, auto-waking on new messages
  • Plugin system — 20 built-in plugins covering search, voice, version control, platform integrations, and more
  • Skill system — Reusable task instructions defined via Markdown files
  • MCP support — Dynamically connect external MCP servers to extend tool capabilities
  • Multi-platform access — Web UI, Telegram, Feishu/Lark, QQ, and other interaction channels
  • Local-first — Data and API keys stay on your machine, no third-party upload required

Quick Start (about 10 minutes)

  1. Clone this repository.
  2. Install with uv sync (or install.bat / install.sh).
  3. Configure LLM: copy a model card template and set api_key in src/model_cards/ (see model cards guide).
  4. Initialize workspace: uv run opensquad init (creates ~/.opensquad/workspace by default).
  5. Start services: uv run opensquad start.
  6. Open UI: http://127.0.0.1:5173 (or Gateway port from system_config).

Prerequisites

  • Python 3.11+ (officially tested on 3.11 / 3.12 / 3.13)
  • Node.js 18+ for frontend development; the Mods host needs Node.js 20.6+ (it loads mods through module.register, and transpiles their .ts / .tsx with a vendored sucrase — so no Node-version-dependent type stripping)
  • A compatible LLM API (DeepSeek, GPT-4, Claude, Gemini, GLM, etc.)

Option 1: One-Click Script (Recommended, Beginner Friendly)

Windows

git clone https://github.com/opensquad-ai/opensquad.git && cd opensquad && install.bat

Linux / macOS

git clone https://github.com/opensquad-ai/opensquad.git && cd opensquad && bash install.sh

The script automatically: checks prerequisites → installs dependencies → initializes workspace → starts all services.

Note: After first start, add your LLM API key to a model card under src/model_cards/.

Option 2: uv (Recommended)

uv is a fast Python package manager. Recommended.

# Install uv (if not already)
pip install uv

# Clone the project
git clone https://github.com/opensquad-ai/opensquad.git
cd opensquad

# Install dependencies (uses uv.lock for reproducible builds)
uv sync

# Install frontend dependencies
cd src/opensquad/gateway/nexuschat-pro && npm install && cd ../../..

# Initialize and start
uv run opensquad init
uv run opensquad start

Option 3: pip

From PyPI — runtime, built web UI and the default resources:

pip install opensquad

opensquad init
opensquad start

Since 0.8.48 the wheel is a complete deployment. It ships the default model_cards/, plugins/, agents/, pymcp/, collab_cards/, role_cards/ and skills/ next to the opensquad package, so opensquad init seeds a runnable workspace and opensquad start finds every service. One gap remains: a fresh pip workspace has no system_config.json (the wheel carries no template), so ports stay on their defaults — gateway 9555, launcher 9600, registry 9720, frontend 5173 — until you save one from the Web UI's Settings.

From a checkout — full deployment, editable install:

git clone https://github.com/opensquad-ai/opensquad.git
cd opensquad

pip install -e .

# Install frontend dependencies
cd src/opensquad/gateway/nexuschat-pro && npm install && cd ../../..

# Initialize and start
opensquad init
opensquad start

Option 4: npm (Node.js users)

The npm package is a thin bootstrap: on first run it installs the matching Python opensquad CLI, then forwards every command to it.

npm install -g opensquad-ai

opensquad init
opensquad start

Requires Node.js 18+ (Mods host: 20.6+) and Python 3.11+. npx opensquad-ai works too, with no global install.

Option 5: Docker

git clone https://github.com/opensquad-ai/opensquad.git
cd opensquad

# Start (auto-builds image)
docker compose up -d

# View logs
docker compose logs -f

After start, visit http://localhost:9555. Data is persisted in Docker volumes.

Custom configuration:

# Edit config
cp src/system_config.example.json src/system_config.json
# Fill in your LLM API Key...

# Mount config and start
docker run -d \
  -p 9555:9555 -p 9600:9600 -p 9720:9720 \
  -v opensquad-data:/data \
  -v ./src/system_config.json:/app/src/system_config.json:ro \
  opensquad

Updating

Use the row that matches how you installed OpenSquad:

Installed viaUpdate withNotes
Desktop app (installer)In-app Check for updates, or opensquad updateFully automatic: it downloads the installer, installs it silently and relaunches the app. Builds older than v0.8.43 must download the installer once by hand — the relaunch-on-update logic shipped in that version.
pip install opensquadpip install --upgrade opensquad
npm install -g opensquad-ainpm install -g opensquad-ai@latestThe wrapper re-installs the matching Python package when the versions differ.
git clone (uv sync / pip install -e .)git pull, then re-run the same install commandRe-run npm install under src/opensquad/gateway/nexuschat-pro if the frontend changed; npm run build there to serve the UI statically instead of through Vite.
Dockergit pull && docker compose up -d --buildThe image is built from the local Dockerfile, not pulled from a registry.

opensquad update only installs anything for the packaged desktop app. It cannot rewrite a pip / npm / source install, so on those it prints the command from the table and exits — without touching your environment or your git state.


Services

opensquad start launches all 4 services:

ServicePortDescription
Gateway Backend9555FastAPI backend (WebSocket + HTTP)
Plugin Registry9720Plugin store API
Frontend Dev5173Vite React frontend
Launcher9600Agent process manager

Open http://127.0.0.1:5173 in your browser to create and configure agents via the Web UI.


CLI Commands

CommandDescription
opensquad init [--workspace <path>]Initialize workspace (default: ~/.opensquad/workspace)
opensquad start [--port <port>]Start all services
opensquad stopStop all OpenSquad services (frontend, gateway, launcher, adapters, agent processes)
opensquad statusShow agent and service status
opensquad plugin listList installed plugins
opensquad plugin install <id>Install a plugin from the store or Git URL
opensquad plugin uninstall <id>Uninstall a plugin

Run without installing:

python -m opensquad.cli start

Configuration

Copy system_config.example.json to your workspace or src/system_config.json (see architecture-paths):

{
  "hosts": { "gateway": "127.0.0.1" },
  "ports": { "gateway": 9555, "launcher": 9600, "websearch": 9001 },
  "auth": { "node_secret": "your-secret-here" }
}

Never commit real system_config.json, auth.json, or model cards with API keys.

LLM API keys live in model cards (src/model_cards/*.json). Agents are created via the Web UI at runtime.


Documentation

Start here: Documentation hub → Getting started (EN)

DocumentDescription
ArchitectureSystem design and module map
CollaborationMulti-agent workflows
Plugin ecosystemBuilt-in plugins vs Registry
ContributingHow to contribute
ReleasingMaintainer release checklist

Contributing

Issues and Pull Requests are welcome! Please read the Contributing Guide and Code of Conduct first.


License

MIT License — see LICENSE for details.

Powered by OpenSquad Core

Source 1 files
hooks/register.ts 29 lines
1// Fixture for P6-B1: a TypeScript mod, run as-is on Node 24's type stripping,
2// importing the `claude-code` SDK surface that the host answers with a shim.
3//
4// Type-only imports are erased at runtime; the value import must resolve.
5import { atom, memberOf, read, update } from 'claude-code'
6import type { EngineInterface, Register } from 'claude-code'
7
8type Counter = { hits: number }
9
10const hits = atom({ plugin: 'ts-demo', key: 'hits' } as const, 0)
11const seen = atom({ plugin: 'ts-demo', key: 'seen' } as const, 0)
12
13export const register: Register = (on: (event: string, matcher: unknown, handler: unknown) => void) => {
14  on('tool.call', { tool: 'demo.typed' }, async ($: EngineInterface, e: { tool: string }, next: () => unknown) => {
15    const before: number = read(hits) ?? 0
16    update(hits, (value: number) => (value ?? 0) + 1)
17    const after: number = read(hits) ?? 0
18    // `memberOf` gives this member its own cell, reached with the `$`-first shape.
19    // `elsewhere` is a *different* member, read to prove the cells are not shared.
20    const member = memberOf(seen, e)
21    const mine: number = read($, member) ?? 0
22    update($, member, mine + 1)
23    const elsewhere: number = read($, memberOf(seen, { requestId: 'demo-elsewhere' })) ?? 0
24    return {
25      deny: `ts-demo: typed ts works, hits ${before} -> ${after}, seen ${mine} -> ${mine + 1}, elsewhere ${elsewhere}`,
26    }
27  })
28}
29