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

@zoink-dev/zoink-cli

v0.4.10

Published

AI Agent Swarm Orchestration CLI

Downloads

755

Readme

Zoink CLI

Multi-Framework AI Agent Swarm Orchestration

Zoink is an open-source CLI tool for orchestrating swarms of AI agents in isolated Docker containers. v0.3.0 evolves Zoink from a single-framework orchestrator into a multi-framework control plane — run OpenClaw and Hermes agents side-by-side in the same swarm. Define your AI team in a simple YAML file, launch it with one command, and watch your agents collaborate through a built-in terminal dashboard.

Installation

curl -fsSL https://zoink.dev/install.sh | sh

or

npm install -g @zoink-dev/zoink-cli

To start the swarm

Create a workflow directory and then:

zoink config init # Create minimal config file
zoink up          # Bring your AI swarm to life

Features

  • Multi-Framework Swarms — Mix OpenClaw and Hermes agents in a single swarm with per-agent runtime field
  • Declarative Configuration — Define agent teams in swarm.yaml v2.0 with roles, models, runtimes, and workspaces
  • One-Command Orchestrationzoink up handles Docker networking, container lifecycle, and agent coordination
  • Idempotent Operations — Run zoink up multiple times safely without duplicating resources
  • Persistent Agent State — Workspace-backed bind mounts per agent (workspace/agents/<name>/state); state survives zoink down/zoink up cycles. Disable with persistState: false for stateless agents.
  • Health Checks & Auto-Recovery — Framework-specific Docker health checks with crash-loop detection (3 failures in 60s → error state)
  • Resource Governance — Per-agent cpu_limit and memory_limit applied as Docker resource constraints
  • Graceful Config Reloadzoink config reload applies safe changes without container restarts; prompts for critical changes
  • Starter Templates — Three built-in swarm templates via zoink config init --template
  • API Key Redaction — All log output is scrubbed of API keys via RedactTransform
  • Dynamic Agent Management — Spawn, remove, pause, unpause, and exec into agents at runtime
  • Built-in Kanban Board — Shared kanban.yaml with CLI commands for add, move, assign, and watch
  • PM-Driven Delegation — Send high-level goals to a PM agent that decomposes and assigns work
  • Direct Agent Queries — Query any agent role directly via zoink run query
  • Autonomous Task Pickup — Workers self-claim cards assigned to them via per-agent autoPickup cron, clone the task's repoUrl, and move it to Done on success
  • Terminal Dashboard — Full-screen TUI with five tabs (Overview, Kanban, Logs, Agents, Chat) and approval modal
  • Web Dashboard — Browser-based SPA with the same five tabs, served by zoink daemon on a host of your choice
  • Daemon Modezoink daemon start runs a single-board HTTP service for remote Kanban access, agent control, chat, and SSE board events
  • Remote Kanban — Opt-in kanban: { mode: remote } in swarm.yaml routes all zoink kanban commands and worker pickup loops through the daemon over HTTP
  • Chat With Agents — Stream conversations with any gateway-enabled agent from the dashboard (TUI or web), powered by the OpenResponses adapter
  • Human-in-the-Loop Approval — Pause before risky actions with configurable approval flow
  • Global Configuration — User-level settings for theme, default model, and API key storage
  • Role Templates — Built-in and user-created role templates
  • Isolated Containers — Each agent runs in its own Docker container with secure networking
  • Enhanced Log Streaming — Color-coded logs with --follow, --tail, --since, --until

See docs/PRODUCT.md for a full feature breakdown and command reference.

Prerequisites

  • Docker - Docker Desktop or Docker Engine
  • Node.js 20+ - For running the CLI tool
  • API Keys - Anthropic/OpenAI API key for your agents (set as environment variables)

Installation

One-line installer (recommended)

The fastest way to install zoink on Linux or macOS is the hosted install script. It detects or installs Docker, installs the CLI binary, prefetches both runtime images, and writes a bearer token to ~/.zoink/daemon.token — all in one shot:

curl -fsSL https://zoink.dev/install.sh | sh

The installer never starts the daemon, registers OS services, or opens a browser. Those steps happen in your project workspace, under your control.

Flags (pipe sh -s -- before them):

# Skip Docker detection/install (you already have Docker)
curl -fsSL https://zoink.dev/install.sh | sh -s -- --no-docker

# Skip image prefetch
curl -fsSL https://zoink.dev/install.sh | sh -s -- --no-images

# Force the tarball path even when npm is available
curl -fsSL https://zoink.dev/install.sh | sh -s -- --prefer-tarball

# Pin a specific CLI version (for tarball path)
curl -fsSL https://zoink.dev/install.sh | sh -s -- --version 0.4.2

# Run as root (not recommended)
ZOINK_ALLOW_ROOT=1 curl -fsSL https://zoink.dev/install.sh | sh

After the installer exits:

# Verify the install
zoink --version

# Your daemon token is ready to use:
cat ~/.zoink/daemon.token

npm global install

If you already have Node.js 20+ and npm:

npm install -g @zoink-dev/zoink-cli

From source

git clone https://github.com/zoink-dev/zoink-cli.git
cd zoink-cli
npm install
npm link

Quick Start

1. Initialize a Swarm

mkdir my-project
cd my-project
zoink config init

This creates a swarm.yaml template (use --template for a pre-built starter):

version: '2.0'
name: my-swarm
workspace: ./workspace
frameworks:
  openclaw:
    defaultImage: ghcr.io/openclaw/openclaw:latest
agents:
  - name: pm-bot
    role: pm
    runtime: openclaw
    model: gpt-4
    provider:
      name: openai
      keyEnv: OPENAI_API_KEY
  - name: coder-1
    role: coder
    runtime: openclaw
    model: gpt-4
    provider:
      name: openai
      keyEnv: OPENAI_API_KEY
    cpu_limit: '2.0'
    memory_limit: '2GB'
  - name: researcher-1
    role: researcher
    runtime: hermes
    model: gpt-4
    provider:
      name: openai
      keyEnv: OPENAI_API_KEY

Or pick a ready-made starter:

zoink config init --template default              # PM + coder + researcher on OpenClaw
zoink config init --template hybrid               # PM + coder on OpenClaw, researcher on Hermes
zoink config init --template coding-team          # PM + coder + devops on OpenClaw

2. Launch Your Swarm

# Set your API key
export OPENAI_API_KEY="sk-..."

# Start the swarm — daemon auto-starts in the background
zoink up

Zoink will:

  • Pull the OpenClaw Docker image if needed
  • Create a dedicated network (zoink-my-swarm-net)
  • Start each agent in its own container
  • Create a workspace/kanban.yaml board for task coordination
  • Auto-start the workspace daemon (generates a token in workspace/.zoink-daemon.token)

3. Check Swarm Status

zoink ps

Output (includes runtime and health columns):

NAME           ROLE        RUNTIME    STATUS     HEALTH     CONTAINER ID
pm-bot         pm          openclaw   running    healthy    a1b2c3d4e5f6
coder-1        coder       openclaw   running    healthy    b2c3d4e5f6a1
researcher-1   researcher  hermes     running    healthy    c3d4e5f6a1b2

4. Delegate a Task

zoink run task "Research the best state management library for React and create a proof-of-concept"

The PM agent will:

  1. Decompose the high-level goal into subtasks
  2. Create cards on the Kanban board
  3. Assign work to appropriate agents
  4. Coordinate execution

5. Monitor with the Dashboard

zoink dashboard

Opens a full-screen TUI with five tabs:

  • Overview — Swarm health, agent status, activity feed, command input
  • Kanban — Interactive board with navigation and task management
  • Logs — Multi-agent log viewer with filtering and color-coded severity
  • Agents — Agent list with pause, logs, and detail views
  • Chat — Stream a conversation with any gateway-enabled agent

Prefer a browser? Start the daemon and open the dashboard with one command:

# Foreground (keep the terminal open)
zoink daemon serve --token-file ~/.zoink/daemon.token

# Or background + auto-open browser
zoink daemon start --token-file ~/.zoink/daemon.token --detach
zoink daemon open
# → opens http://localhost:9999/?token=… (auto-logs you in)

The daemon serves the web SPA from the same port and exposes the Kanban, agents, chat, and SSE event APIs behind bearer-token auth.

6. Reload Config

Apply changes to swarm.yaml without restarting in-flight agents:

zoink config reload

Safe changes (model, temperature) apply instantly. Critical changes (network, volumes) prompt for confirmation.

7. View Agent Logs

# Stream logs from a specific agent (API keys are automatically redacted)
zoink agent logs pm-bot --follow

# View Kanban board
zoink kanban show

8. Teardown

zoink down

Cleanly stops and removes all containers, networks, and the workspace daemon. Agent state directories in workspace/agents/<name>/state are preserved — state persists for the next zoink up. Use --keep-daemon if you want the daemon to remain running after teardown (e.g. to inspect the web dashboard post-mortem).

Commands

Swarm Lifecycle

zoink up [--dir <path>] [--no-daemon] [--daemon-port <n>] [--daemon-bind <addr>]
                                # Launch swarm + auto-start daemon (use --no-daemon to skip)
zoink down [--dir <path>] [--keep-daemon]
                                # Teardown swarm + stop daemon (use --keep-daemon to leave it running)
zoink ps [--dir <path>]         # List running agents
zoink dashboard [--dir <path>]  # Open terminal dashboard

Daemon (Web Dashboard & Remote Kanban API)

# Foreground (dev / tmux session)
zoink daemon serve --token-file ~/.zoink/daemon.token [--port 9999] [--bind 127.0.0.1]

# Background
zoink daemon start --token-file ~/.zoink/daemon.token --detach
zoink daemon open     # open dashboard in browser (reads port + token from sidecars)
zoink daemon restart  # stop + restart with the same options
zoink daemon status
zoink daemon stop

The daemon serves the browser dashboard (same five tabs as the TUI) and exposes a bearer-authenticated HTTP API for Kanban operations, agent control (pause/unpause/restart/logs), chat, and SSE board events.

--token-file vs --token-env

--token-file <path> reads the bearer token from a file on every auth check — token rotation works without restarting the daemon. The install script writes ~/.zoink/daemon.token for you.

--token-env <VAR> reads the token from an environment variable at startup (legacy behaviour, still fully supported). The two flags are mutually exclusive; passing both or neither exits with an error.

# Using the token file written by install.sh (recommended)
zoink daemon serve --token-file ~/.zoink/daemon.token

# Using an env var (ad-hoc / CI)
export ZOINK_TOKEN="$(openssl rand -hex 32)"
zoink daemon start --token-env ZOINK_TOKEN --detach

Pass --detach to run the daemon in the background so you can close the terminal:

zoink daemon start --token-file ~/.zoink/daemon.token --detach
# → Daemon started in background (pid=…, logs=<workspace>/.zoink-daemon.log)
zoink daemon open     # opens http://localhost:9999/?token=… in your browser
zoink daemon status
zoink daemon stop

zoink daemon open constructs the dashboard URL with the token from ~/.zoink/daemon.token (via .zoink-daemon.tokenfile sidecar) so you get a one-click authenticated session. On headless Linux (DISPLAY and WAYLAND_DISPLAY unset) it prints the URL to stdout instead.

Logs are written to <workspace>/.zoink-daemon.log. Files larger than 10 MiB are rotated to .zoink-daemon.log.old at each launch. Override the cap with ZOINK_DAEMON_LOG_MAX_BYTES=<bytes> (set to 0 to disable rotation).

Loopback auto-login

When you point a browser at http://127.0.0.1:9999/ on the same machine that runs the daemon, zoink automatically mints a session cookie for that first request — no token-paste required. The cookie is set on the very first call to /api/v1/auth/me (the SPA's bootstrap probe), so the dashboard loads directly without flashing the login page.

This only applies to connections that arrive on 127.0.0.1, ::1, or ::ffff:127.0.0.1 (the loopback interface). Any request from another host still requires a bearer token or an existing session cookie.

To disable auto-login (e.g. on a shared development machine where other local users should not get automatic access):

# One-off: pass the flag when starting
zoink daemon serve --token-file ~/.zoink/daemon.token --no-loopback-auto-login

# Permanently: set in global config
zoink config set dashboard.loopbackAutoLogin false

Security note — shared dev hosts. On a machine with multiple local users, any user with a browser can open the dashboard when loopback auto-login is enabled. The daemon token file's filesystem permissions (written as 0600 by the install script) are the only barrier. If you share the host with untrusted users, set dashboard.loopbackAutoLogin: false.

Agent Management

zoink agent spawn <name>        # Dynamically add a new agent
zoink agent rm <name>           # Remove an agent container
zoink agent logs <name> [-f]    # Stream agent logs
zoink agent pause <name>        # Suspend an agent
zoink agent unpause <name>      # Resume a paused agent
zoink agent exec <name> [cmd]   # Execute a command inside a container

Configuration

zoink config init [--template <name>]  # Generate swarm.yaml (use --template for starters)
zoink config validate                  # Validate swarm.yaml against schema v2.0 (with line numbers)
zoink config reload                    # Apply safe config changes without container restarts
zoink config set <key> <val>           # Set global config value
zoink config get [key]                 # Get global config value
zoink config role list                 # List role templates
zoink config role create <name>        # Create role template from running agent
zoink config role delete <name>        # Delete a role template

Kanban Board

zoink kanban show                                                          # Display Kanban board
zoink kanban add --title <text> [--repo-url <url>] [--assign <agent>]      # Add a new task; --repo-url enables autonomous pickup
                                [--priority low|medium|high]
zoink kanban move <id> <col>                                               # Move a task to a different column
zoink kanban assign <id> <agent>                                           # Assign a task to an agent
zoink kanban watch [--json]                                                # Watch for board changes in real-time

When kanban.mode: remote is set, every subcommand transparently routes to the daemon over HTTP instead of touching kanban.yaml directly.

Task Orchestration

zoink run task "<description>" [--repo-url <url>]  # Delegate task to PM agent (repo-url propagates to PM-decomposed cards)
zoink run query "<prompt>" --agent <role>          # Direct query to a specific agent role

Configuration

swarm.yaml v2.0 Structure

version: '2.0' # Schema version
name: my-swarm # Unique identifier for this swarm
workspace: ./workspace # Shared workspace directory

frameworks: # Framework-level defaults
  openclaw:
    defaultImage: ghcr.io/openclaw/openclaw:latest
  hermes:
    defaultImage: ghcr.io/nousresearch/hermes:v2026.4.23

orchestration: # Optional human-in-the-loop settings
  approval_mode: false
  approval_timeout_seconds: 300

kanban: # Optional; defaults to local file-backed mode
  mode: local # 'local' (default) or 'remote' — see Remote Kanban Mode below

agents:
  - name: pm-bot # Unique agent name
    role: pm # Agent role (pm, coder, researcher, devops)
    runtime: openclaw # Framework: openclaw (default) or hermes
    model: claude-3-5-sonnet-20241022
    provider:
      name: anthropic
      keyEnv: ANTHROPIC_API_KEY

  - name: coder-1
    role: coder
    runtime: openclaw
    model: claude-3-5-sonnet-20241022
    provider:
      name: anthropic
      keyEnv: ANTHROPIC_API_KEY
    cpu_limit: '2.0' # Docker CPU quota
    memory_limit: '2GB' # Docker memory limit
    persistState: true # default; set to false for a fully stateless agent
    autoPickup: true # opt in to autonomous Kanban pickup
    pickupIntervalSeconds: 300 # how often the agent sweeps the board

  - name: stateless-helper
    role: coder
    runtime: openclaw
    model: claude-3-5-sonnet-20241022
    provider:
      name: anthropic
      keyEnv: ANTHROPIC_API_KEY
    persistState: false # no state directory — ephemeral agent

  - name: researcher-1
    role: researcher
    runtime: hermes # Use Hermes for persistent-memory research
    model: claude-3-5-sonnet-20241022
    provider:
      name: anthropic
      keyEnv: ANTHROPIC_API_KEY
    profiles: 2 # Hermes: number of isolated profile instances

provider is the preferred way to select an LLM backend and auth source. v1.0 configs (no version, no runtime) remain fully valid, and apiKeyEnv is still accepted as a deprecated compatibility field for one release.

Supported Runtimes

| Runtime | Image | Best For | | -------------------- | ---------------------------------------- | ------------------------------------------ | | openclaw (default) | ghcr.io/openclaw/openclaw:latest | General coding, PM tasks | | hermes | ghcr.io/nousresearch/hermes:v2026.4.23 | Research, persistent memory, multi-profile |

Supported Roles

  • pm - Project manager; decomposes high-level goals and assigns work
  • coder - Writes code, implements features, fixes bugs
  • researcher - Gathers information, evaluates libraries, reads documentation
  • devops - Manages infrastructure, deployment, CI/CD

Per-Agent Personality (SOUL.md)

Both OpenClaw and Hermes support a SOUL.md file that sets an agent's voice, tone, and behavioral rules. Zoink auto-generates one from the soul block in swarm.yaml and seeds it into the container before it starts. zoink config init ships a starter soul block on every agent so you can edit and go:

agents:
  - name: pm-agent
    role: pm
    runtime: openclaw
    model: claude-sonnet-4-5
    soul:
      tone: "blunt, direct — no corporate filler"
      style: "concise; one sentence when one sentence is enough"
      personality: "opinionated, witty, calls out bad ideas early"
      rules:
        - "Never open with 'Great question' or 'Absolutely'"
        - "Skip preambles; answer the question"

  - name: researcher
    role: researcher
    runtime: hermes
    model: anthropic/claude-opus-4.7
    soul: false  # disable SOUL.md seeding entirely for this agent

All four fields (tone, style, personality, rules) are optional. If soul is omitted entirely, a minimal identity line is seeded. If soul: false, nothing is written.

Where the file lands:

  • OpenClaw: /root/.openclaw/workspace/SOUL.md
  • Hermes: /opt/data/SOUL.md (the HERMES_HOME mount)

Sidecar Config Files

For anything beyond model and soul — channels, custom skills, OpenClaw $include fragments, Hermes .env, memories/, AGENTS.md — use configFiles to drop files into the agent's state mount at first boot:

agents:
  - name: pm-agent
    role: pm
    runtime: openclaw
    configFiles:
      - source: ./prompts/pm.AGENTS.md     # relative to swarm.yaml
        target: AGENTS.md                  # relative to state mount root
      - source: ./configs/openclaw/plugins.json5
        target: openclaw.d/plugins.json5   # loaded via $include in openclaw.json
      - source: ./secrets/openclaw.env
        target: .env
        mode: "0600"                       # restrict permissions

  - name: researcher
    role: researcher
    runtime: hermes
    configFiles:
      - source: ./prompts/researcher.SOUL.md
        target: SOUL.md                    # overrides the auto-seeded SOUL.md
      - source: ./configs/hermes/researcher.env
        target: .env
        mode: "0600"
      - source: ./memories/researcher.MEMORY.md
        target: memories/MEMORY.md

target paths are relative to the per-runtime state mount root (/root/.openclaw for OpenClaw, /opt/data for Hermes). Absolute paths and .. traversal are rejected. If a configFiles entry targets the same path as the auto-seeded SOUL.md, the user-supplied file wins.

When persistState: false, OpenClaw configFiles must target either config/… (routes to the config volume) or workspace/… (routes to the workspace volume); any other prefix is skipped with a warning.

Resource Limits

Per-agent resource constraints are applied directly as Docker container limits:

agents:
  - name: coder-1
    cpu_limit: '2.0' # 2 CPU cores
    memory_limit: '4GB' # 4 GB RAM

Provider and API Key Configuration

Zoink now separates the model ID from the provider/auth settings. The recommended config shape is:

agents:
  - name: agent-1
    role: coder
    runtime: openclaw
    model: gpt-4o-mini
    provider:
      name: openai
      keyEnv: OPENAI_API_KEY

Use the provider block like this:

  • provider.name selects the backend. Common values include openai, anthropic, openrouter, google, and custom.
  • provider.keyEnv reads the API key from the named environment variable. This is the preferred option.
  • provider.key stores the key inline in swarm.yaml. It is supported, but not recommended because the secret is stored in plaintext.
  • provider.baseUrl overrides the provider endpoint, which is useful for OpenAI-compatible gateways and self-hosted endpoints.

Examples:

agents:
  - name: claude-agent
    role: pm
    runtime: openclaw
    model: claude-sonnet-4-5
    provider:
      name: anthropic
      keyEnv: ANTHROPIC_API_KEY

  - name: gateway-agent
    role: coder
    runtime: hermes
    model: gpt-4.1-mini
    provider:
      name: custom
      keyEnv: AI_GATEWAY_API_KEY
      baseUrl: https://gateway.example.com/v1

If you do not want to pass secrets via shell environment variables, you can store a provider key in Zoink's global config and reference only the provider in swarm.yaml:

zoink config set api_keys.openai sk-...
zoink config set api_keys.anthropic sk-ant-...
agents:
  - name: agent-1
    role: coder
    runtime: openclaw
    model: gpt-4o-mini
    provider:
      name: openai

Key resolution order is:

  1. provider.keyEnv
  2. provider.key
  3. deprecated apiKeyEnv
  4. zoink config set api_keys.<provider> ...

Legacy configs that still use apiKeyEnv continue to work during the deprecation window:

agents:
  - name: legacy-agent
    role: coder
    model: claude-3-5-sonnet-20241022
    apiKeyEnv: ANTHROPIC_API_KEY

Autonomous Task Pickup

Workers can self-claim assigned cards on a recurring interval, clone the task's repository into their persistent state, execute it, and move the card to Done. Enable it by setting autoPickup: true on a worker agent and adding --repo-url when you create the card.

agents:
  - name: coder-1
    role: coder
    runtime: openclaw
    autoPickup: true
    pickupIntervalSeconds: 300 # board sweep cadence
zoink kanban add \
  --title "Add health-check endpoint" \
  --repo-url https://github.com/your-org/api.git \
  --assign coder-1

A card is eligible for pickup when it is in To Do, its assignee matches the agent name exactly, repoUrl is set, and it is not already claimed. Claiming is deterministic: if the board changed mid-claim the worker simply skips and retries on the next interval. Each successful claim stamps claimedBy and claimedAt and moves the card to In Progress. Repository checkouts land under workspace/agent-state/<agent>/<runtime>/tasks/<taskId>/.

zoink run task --repo-url <url> "<goal>" propagates the same repoUrl to PM-decomposed cards so the entire downstream slice is pickup-ready.

Remote Kanban Mode

By default the board is a local kanban.yaml file. For distributed setups (one shared board, multiple host machines) start a daemon on the host that owns the board and point your swarm at it:

# On the daemon host (token from install.sh, or ad-hoc via --token-env)
zoink daemon start --token-file ~/.zoink/daemon.token --bind 0.0.0.0 --port 9999
# In each consumer swarm.yaml
kanban:
  mode: remote
  daemonUrl: http://kanban-host:9999
  authTokenEnv: KANBAN_TOKEN # the consumer reads its bearer token from this env var
  timeoutMs: 30000 # optional

When mode: remote is set:

  • All zoink kanban subcommands (show, add, move, assign, watch) route through the daemon over HTTP.
  • zoink up skips the workspace bind mount and injects daemon-endpoint env vars into agent containers instead of file paths.
  • The autonomous pickup cron uses --board-endpoint and --board-token-env so workers reach the same board over HTTP.
  • The daemon also serves the web SPA dashboard and SSE board events on the same port. TLS termination is left to a reverse proxy (nginx, Caddy, etc.).

Uninstalling

zoink uninstall        # interactive confirmation
zoink uninstall --yes  # skip confirmation prompt

# Or via the install script
curl -fsSL https://zoink.dev/install.sh | sh -s -- --uninstall

zoink uninstall (or install.sh --uninstall):

  1. Stops any running daemon — treating a missing PID file, stale PID, ESRCH, EPERM, and any signal error as warnings, never errors.
  2. Removes the CLI binary (npm uninstall -g @zoink-dev/zoink-cli for npm installs, rm -rf ~/.zoink/bin for tarball installs).
  3. Removes ~/.zoink/daemon.token.
  4. Prints what was left untouched:
Containers and `~/.zoink/{config,assets,roles}` left in place.

To remove Docker containers and networks created by zoink:
  docker ps --filter "label=zoink.swarm" -q | xargs docker rm -f
  docker network ls --filter "label=zoink.swarm" -q | xargs docker network rm

To fully remove ~/.zoink state:
  rm -rf "/Users/you/.zoink"

Running install.sh again after zoink uninstall produces a clean installation from scratch.

Architecture

Zoink uses a hexagonal architecture (Ports & Adapters) with strict separation of concerns: domain services contain pure business logic, ports define contracts, adapters handle I/O, and the CLI/TUI layers provide the user interface. A centralized event bus decouples components.

See docs/ARCHITECTURE.md for the full architecture documentation.

Development

Setup

git clone https://github.com/zoink-dev/zoink-cli.git
cd zoink-cli
npm install

Testing

# Unit tests (fast, no Docker required)
npm test

# Watch mode
npm test:watch

# Coverage report
npm test:coverage

# E2E tests (requires Docker daemon)
npm run e2e:full

# Run specific test file
npx vitest run src/domain/services/SwarmLifecycleService.spec.ts

Contributing

Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.

Development Workflow

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/my-feature
  3. Make changes and add tests
  4. Run tests: npm test && npm run e2e:full
  5. Commit with descriptive messages
  6. Push and open a pull request

Roadmap

See docs/PRODUCT.md for the feature overview and roadmap.

License

MIT License - see LICENSE for details.


Made with ❤️ by the Zoink community