setup

star 6

Run initial Corsair setup. Use when a user wants to install, configure, or get started with their Corsair agent for the first time. Triggers on "setup", "install", "get started", or first-time setup requests.

corsairdev By corsairdev schedule Updated 2/25/2026

name: setup description: Run initial Corsair setup. Use when a user wants to install, configure, or get started with their Corsair agent for the first time. Triggers on "setup", "install", "get started", or first-time setup requests.

Corsair Setup

Credentials

Never ask the user to paste a credential into chat. Instead:

  1. Run pwd to get the absolute project path — call it $DIR.
  2. Tell the user to run this command, with a clear placeholder showing exactly what to replace:
    echo 'SOME_API_KEY=YOUR_KEY_HERE' >> $DIR/.env
    
  3. In any setup script you write, read the value from process.env — never hardcode it:
    const API_KEY = process.env.SOME_API_KEY!;
    
  4. After the script runs successfully, delete each temp line from .env yourself. The sed command must always include the absolute path to the file — never run it without it:
    sed -i '' '/^SOME_API_KEY=/d' $DIR/.env
    
    Run one sed command per env var you added.

Run all steps automatically. Pause only when the user must take a manual action (entering a key, making a choice). When something is broken or missing, fix it yourself. Only ask the user when you genuinely need their input.

Principle: Do the exciting stuff first. Get their agent running and talking on messaging apps before asking for any plugin keys. Each plugin key is an unlock — present them that way.


Phase 1: Bootstrap

1a. Check prerequisites

The agent runs inside Docker, so the host Node version doesn't matter for running the server. However, pnpm on the host is still needed for IDE tooling (type completions, imports). Check Docker and pnpm:

docker --version && pnpm --version
  • Docker missing: Ask the user if they'd like you to install it:
  • Docker installed but not running:
    • macOS: open -a Docker, wait ~15s, retry
    • Linux: sudo systemctl start docker, retry
  • pnpm missing: npm install -g pnpm (only needed for IDE support — the container manages its own)

1b. Environment file

Check if .env exists. If not:

cp .env.example .env

1c. Generate security key

Generate a KEK and write it into .env automatically — the user doesn't need to do anything:

openssl rand -base64 32

Read .env, find the CORSAIR_KEK line, and replace its value with the generated string using a file edit (not sed). The line should look like: CORSAIR_KEK="<generated-value>"

1d. AI provider

Ask the user:

"Which AI provider do you want to use? OpenAI (GPT) or Anthropic (Claude)?"

Direct the user to get their key (OpenAI: https://platform.openai.com/api-keys, Anthropic: https://console.anthropic.com/settings/keys). Give them the exact echo '...' >> .env command following the Credentials convention above. Then update server/agent.ts to use the chosen provider if it isn't already set.

1e. Install host dependencies (for IDE support only)

pnpm install

This installs packages on the host purely for editor intellisense and type checking. The agent itself runs in Docker on Node 22 — the host Node version doesn't affect it.

If this fails due to native module build errors, it's non-critical. Skip it and continue — the agent will run fine, the user just loses some IDE type hints.

1f. Build and start everything

docker compose up --build -d

This builds all images and starts the full stack:

Service URL Purpose
Agent (server) http://localhost:3000 tRPC API + webhook receiver
UI (Next.js) http://localhost:3001 Web chat interface
Drizzle Studio http://localhost:4983 Database browser
ngrok http://localhost:4040 Tunnel dashboard + public URL

The first build takes a couple of minutes. Subsequent starts are instant since Docker caches the dependency layers.

Database migrations run automatically at container startup before the server starts — no manual migration step needed.

Both the agent server (tsx watch) and the UI (next dev) hot-reload on file changes. node_modules is managed entirely by the container; the host version is never used at runtime.

If Docker isn't running, start it and wait for it to be ready:

  • macOS: open -a Docker
  • Linux: sudo systemctl start docker

Then poll until it's actually up before retrying:

until docker info &>/dev/null 2>&1; do sleep 2; done

Get the ngrok public URL (needed for webhooks). ngrok runs as a Docker service and needs an authtoken. Tell the user to:

  1. Sign up at https://ngrok.com and copy their authtoken from the dashboard
  2. Add it to .env using the Credentials convention above:
    echo 'NGROK_AUTHTOKEN=YOUR_TOKEN_HERE' >> $DIR/.env
    
  3. For a stable URL that doesn't change on restart (recommended), claim their free static domain at https://dashboard.ngrok.com/domains. Then edit the ngrok command directly in docker-compose.yml:
    command: http --domain=your-domain.ngrok-free.app agent:3000
    

After .env is updated, restart the stack so ngrok picks up the token:

docker compose up -d

Get the public URL from the ngrok container:

curl -s http://localhost:4040/api/tunnels | grep -o '"public_url":"https://[^"]*"' | head -1 | cut -d'"' -f4

Save the URL to BASE_PERMISSION_URL and WEBHOOK_URL in the .env file. Since it is a tunnel, we use it for both.

The WEBHOOK_URL is the BASE_PERMISSION_URL + /api/webhook

This URL is how external services (WhatsApp, Slack, etc.) reach the agent.

To follow the agent logs:

docker compose logs -f agent

This seeds the agent's code context into the database so it can reason about its own codebase. Wait for it to complete before moving on.


Phase 2: Choose plugins

Run:

docker compose exec agent pnpm available-plugins

Show the output to the user. Then ask:

"Which of these do you want to enable? These are the integrations your agent will be able to use. You can always add more later — just pick what you need right now."

Note their selection. Then update server/corsair.ts:

  • Keep only the plugins they selected in the plugins array
  • Remove the imports and entries for plugins they didn't choose
  • Leave all selected plugins with empty options for now — e.g. slack() — keys come in Phase 4

Phase 3: Choose your messaging channel

Tell the user:

"Now let's get your agent live on a messaging app. Once this is done, you'll be able to message it directly. The plugin keys can wait — let's get you something working first.

Which would you prefer?

  • WhatsApp — Connect a WhatsApp number (your own or a dedicated one). Uses a pairing code, no phone to buy.
  • Telegram — Create a Telegram bot via BotFather (just a token, no phone number needed). Easier to set up."

Wait for their answer, then:

  • WhatsApp: Start the /add-whatsapp skill now. Return here when it's complete.
  • Telegram: Start the /add-telegram skill now. Return here when it's complete.

Phase 4: Keys

The agent is now running. Phase 4 unlocks each plugin the user selected.

No restarts needed. Keys are stored encrypted in the database and the agent reads them on every request. Each plugin sub-skill writes a temporary script, runs it, and deletes it.

Read /add-keys for a full explanation of how Corsair's key model works before starting.

Work through the selected plugins one at a time. For each plugin, start the corresponding sub-skill listed below. After each one completes, ask:

"[Plugin] is connected! Want to set up [Next Plugin] now, or try your agent out first?"

This lets the user exit at any point and return later — each sub-skill can be run independently at any time.

Plugin Skill to start
Slack /add-keys/slack
Linear /add-keys/linear
Resend /add-keys/resend
Discord /add-keys/discord
Google Calendar /add-keys/google
Google Drive /add-keys/google (same credentials as Calendar)

Google Calendar and Google Drive share the same OAuth app. If the user selected both, run /add-keys/google once and it covers both.


Phase 5: Custom integrations

Tell the user they can set up any other integration you want once the setup is done.


Phase 6: Launch

All services are already running from step 1f. If any were restarted during plugin setup, confirm the stack is healthy:

docker compose ps
docker compose logs --tail=30 agent

Check for:

  • All services status: running
  • [whatsapp] Connected to WhatsApp — if WhatsApp was set up
  • [telegram] Bot started (long polling) — if Telegram was set up
  • No plugin errors or crashes

Confirm the ngrok tunnel is still running in its terminal and the URL in .env is up to date. If the user restarted ngrok and the URL changed (and they don't have a static domain), they'll need to update BASE_PERMISSION_URL and WEBHOOK_URL in .env and re-register any webhooks.

Tell the user to send a test message on their chosen channel and confirm the agent responds. Let them know the web UI is at http://localhost:3001 and Drizzle Studio at http://localhost:4983.

Congratulate them — their agent is live.

Useful commands to share with the user:

docker compose logs -f agent        # follow agent logs
docker compose logs -f ui           # follow UI logs
docker compose up -d agent          # restart agent and pick up .env changes
docker compose up -d ngrok          # restart ngrok (e.g. after updating NGROK_AUTHTOKEN)
docker compose down                 # stop everything
docker compose up -d                # start everything again
docker compose up --build -d        # rebuild after package.json changes
curl -s http://localhost:4040/api/tunnels | grep -o '"public_url":"https://[^"]*"' | head -1 | cut -d'"' -f4  # get ngrok URL

Note: Use docker compose up -d <service> (not restart) whenever .env changes — restart preserves the old environment from container creation.


Troubleshooting

docker compose up --build fails during image build: Usually a network issue or missing build tools. Check Docker is running. If it fails on pnpm install inside the container, check Dockerfile.dev (agent) or Dockerfile.ui.dev (UI) — the apt-get step in Dockerfile.dev installs build tools needed by baileys.

No ngrok URL / tunnel not working: Check that NGROK_AUTHTOKEN is set in .env and the ngrok container is running (docker compose ps). If it exited, check docker compose logs ngrok — a missing or invalid token is the most common cause. Restart with docker compose up -d ngrok after fixing .env. Get the URL with curl -s http://localhost:4040/api/tunnels. For a stable URL that survives restarts, set up a free static domain at https://dashboard.ngrok.com/domains and hardcode the domain directly in the ngrok command in docker-compose.yml: http --domain=your-domain.ngrok-free.app agent:3000.

Agent crashes on startup: Run docker compose logs agent. Common causes:

  • Missing CORSAIR_KEK in .env
  • Missing AI provider key (OPENAI_API_KEY or ANTHROPIC_API_KEY)
  • Migration failure — check logs for db:push errors; usually means Postgres isn't healthy yet. Run docker compose logs postgres to diagnose, then docker compose up -d to retry.

Plugin throws key error: Make sure the plugin's env var is in .env and is being passed to the plugin function in server/corsair.ts. Then docker compose restart agent.

WhatsApp not responding: See the /add-whatsapp skill's troubleshooting section.

Telegram not responding: See the /add-telegram skill's troubleshooting section.

Added a new npm package: Edit package.json directly (never pnpm add inside a running container — pnpm store paths conflict). Then clear the named volume and rebuild:

docker compose down && docker volume rm corsair-2_agent_node_modules && docker compose up --build -d

(Adjust the volume name prefix to match your project directory — check with docker volume ls.)

Want to add a plugin later: Come back and run setup again, or run the /add-plugin skill directly.

Install via CLI
npx skills add https://github.com/corsairdev/agent --skill setup
Repository Details
star Stars 6
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator