SuperAPI AI Directory

squad-init

Office & productivity

View repository

Updated 10-16 08:09

About this skill

Registers the current project in PostgreSQL (shared central DB) and creates a local config so /squad knows which project to use. No per-project DB file is created — the central PostgreSQL server handles storage for all projects automatically.

Usage

/squad-init                                      — project name = basename of current directory, board = https://squad-api-285415501393.asia-south1.run.app
/squad-init my-project-name                      — explicit project name, board = https://squad-api-285415501393.asia-south1.run.app
/squad-init my-project-name https://board.example.com
                                                 — explicit project name + custom board URL
/squad-init https://board.example.com           — current directory name + custom board URL

If a URL argument is present, treat it as base_url. Strip any leading dashes from the project token: squad-init -unahouse.finance → project unahouse.finance.

Procedure

1. Determine project name and board URL

# Split raw args
set -- $ARG
ARG1="${1:-}"
ARG2="${2:-}"

# Accept either:
#   /squad-init my-project
#   /squad-init my-project https://board.example.com
#   /squad-init https://board.example.com
if printf '%s' "$ARG1" | grep -Eq '^https?://'; then
  PROJECT=$(basename "$(pwd)")
  BASE_URL="$ARG1"
else
  PROJECT=$(printf '%s' "$ARG1" | sed 's/^-*//')
  [ -z "$PROJECT" ] && PROJECT=$(basename "$(pwd)")
  BASE_URL="${ARG2:-https://squad-api-285415501393.asia-south1.run.app}"
fi

2. Write local project config

Create one tool-agnostic file at the current project root, committed to git so the whole team's agents target the same board project:

.squadrc

SQUAD_PROJECT=<PROJECT_NAME>
SQUAD_ORG=<ORG_SLUG>          # REQUIRED — every board call is org-scoped (/api/orgs/<org>/...)

.squadrc holds the project name and the org slug (both non-secret → safe to commit). The SQUAD_ORG=<slug> line is REQUIRED and ALWAYS written — every board call is org-scoped (/api/orgs/<org>/...), including squad-init's own POST /api/orgs/<org>/projects. Resolve the slug from an explicit init arg or the mint dialog's SQUAD_ORG=<slug> line (env or an existing .squadrc):

# Org slug — env (the mint dialog exports it) > existing .squadrc. REQUIRED.
SQUAD_ORG="${SQUAD_ORG:-}"
[ -z "$SQUAD_ORG" ] && [ -f .squadrc ] && SQUAD_ORG=$(grep '^SQUAD_ORG=' .squadrc | cut -d= -f2-)
if [ -z "$SQUAD_ORG" ]; then
  echo "ERROR: SQUAD_ORG is not set. Every board call is org-scoped (/api/orgs/<org>/...)." >&2
  echo "Set it from the mint dialog's \`SQUAD_ORG=<slug>\` line — add \`SQUAD_ORG=<slug>\` to .squadrc" >&2
  echo "(committed) or export SQUAD_ORG=<slug> for this shell. Resolution order: env > .squadrc." >&2
  exit 1
fi

The slug is never auto-derived from the board (the project API exposes no org slug today — a noted follow-up). The token never lives in .squadrc; it lives in ~/.squad/auth as the bare SQUAD_AUTH_TOKEN= line.

Use the Write tool to create .squadrc with both the SQUAD_PROJECT= and the SQUAD_ORG=<slug> lines (always write SQUAD_ORG; if no slug can be resolved, stop with the error above — do NOT register without it).

2b. Detect auth (no token store here)

The token is resolved via the shared.md chain (env > bare SQUAD_AUTH_TOKEN=). squad-init never stores a token, never echoes/cats it, and never asks for a pasted one — the token-store command lives only at the web mint UI — Settings → Personal Access Tokens (the single place the real token exists). On no token, squad-init just prints a one-line POINTER to that UI:

# Detect whether a token is configured (env > bare `SQUAD_AUTH_TOKEN=`) to decide the warning
# below — never echo it. The board call itself goes through api.py, which owns the header.
SQUAD_ORG="${SQUAD_ORG:-}"
[ -z "$SQUAD_ORG" ] && [ -f .squadrc ] && SQUAD_ORG=$(grep '^SQUAD_ORG=' .squadrc | cut -d= -f2-)
AUTH_TOKEN="${SQUAD_AUTH_TOKEN:-}"; AUTH_SOURCE=$([ -n "$AUTH_TOKEN" ] && echo env || echo none)
if [ -z "$AUTH_TOKEN" ] && [ -f "$HOME/.squad/auth" ]; then
  AUTH_TOKEN=$(grep '^SQUAD_AUTH_TOKEN=' "$HOME/.squad/auth" | cut -d= -f2-)
  [ -n "$AUTH_TOKEN" ] && AUTH_SOURCE=file
fi

if [ -z "$AUTH_TOKEN" ]; then
  echo "No Squad Personal Access Token configured — mint one in your Squad board's web UI (Settings → Personal Access Tokens) and run the store command it shows."
fi

# Persist a custom (non-default) board URL only — to ~/.squad/config
if [ -n "$BASE_URL" ] && [ "$BASE_URL" != "https://squad-api-285415501393.asia-south1.run.app" ]; then
  mkdir -p "$HOME/.squad"
  grep -q '^SQUAD_BASE_URL=' "$HOME/.squad/config" 2>/dev/null || printf 'SQUAD_BASE_URL=%s\n' "$BASE_URL" >> "$HOME/.squad/config"
fi

2c. Auto-register project in projects table

After writing the config, upsert the current project to the projects table via POST /api/projects. Infer project metadata from the local environment:

# Category defaults to "personal"; change it on the board if needed.
CATEGORY="personal"
echo "$PROJECT" | grep -qiE 'skill|squad' && CATEGORY="skills"
echo "$PROJECT" | grep -qiE 'tool|api|cli'  && CATEGORY="tools"

# Infer purpose + stack from CLAUDE.md (best-effort)
PURPOSE=""; STACK=""
if [ -f "CLAUDE.md" ]; then
  PURPOSE=$(grep -v '^#' CLAUDE.md | grep -v '^---' | grep -v '^[[:space:]]*$' | head -1 | cut -c1-300)
  STACK=$(grep -iE 'stack|tech|typescript|javascript|python|react|vue|next|node|vite' CLAUDE.md | head -1 | cut -c1-200)
fi
REPO_URL=$(git remote get-url origin 2>/dev/null || echo "")

# Build the payload safely with jq — never interpolate file/user text into code (see shared.md "JSON Safety").
PROJ_PAYLOAD=$(jq -n \
  --arg id "$PROJECT" --arg name "$PROJECT" --arg category "$CATEGORY" \
  --arg purpose "$PURPOSE" --arg stack "$STACK" --arg repo_url "$REPO_URL" \
  '{id: $id, name: $name, category: $category,
    purpose:  (if $purpose  == "" then null else $purpose  end),
    stack:    (if $stack    == "" then null else $stack    end),
    repo_url: (if $repo_url == "" then null else $repo_url end)}')
api POST /projects --json "$PROJ_PAYLOAD" > /dev/null 2>&1 || true

This is best-effort — if the API call fails (e.g., board unreachable), init still succeeds.

3. Output confirmation

Output:

✅ Project '<PROJECT_NAME>' registered in squad.

  Config:  .squadrc (committed)
  Org:     <ORG_SLUG>   (required — written to .squadrc; every board call is org-scoped)
  DB:      PostgreSQL (shared central DB)
  Board:   <BASE_URL>/?project=<PROJECT_NAME>
  Auth:    Personal Access Token — SQUAD_AUTH_TOKEN env / ~/.squad/auth (global secret; configured / empty, value-free)

Add tasks with /squad add <title>

Notes

Existing config detection

If .squadrc already exists, read SQUAD_PROJECT and ask before overwriting:

.squadrc already exists:
  Current project: "<name>"

Options:
1. Overwrite — update SQUAD_PROJECT
2. Keep as-is — leave .squadrc unchanged
  • /squad-init defaults to https://squad-api-285415501393.asia-south1.run.app unless you provide another deployment URL.
  • Tokens are Personal Access Tokens (PATs) stored globally in ~/.squad/auth (mode 600) as a bare SQUAD_AUTH_TOKEN= line — or the SQUAD_AUTH_TOKEN env var; NEVER in .squadrc. This keeps secrets out of git; SQUAD_ORG still selects the tenant per repo.
  • .squadrc carries the project name + the required non-secret SQUAD_ORG=<slug> selector (every board call is org-scoped /api/orgs/<org>/...). squad-init ALWAYS writes SQUAD_ORG (resolved from an explicit init arg or the mint dialog's SQUAD_ORG=<slug> line); it is not board-derived (the project API exposes no org slug; auto-derive + verify is a noted follow-up). With no slug, squad-init stops with an actionable error rather than registering without one.
  • squad-init never stores or prompts for a token: minting + the store command live only in the board's web UI — Settings → Personal Access Tokens. On no token it prints a one-line pointer to that UI (the breadcrumb, NOT a URL — the skill only knows the API BASE_URL, not the web host).
  • For remote private boards, mint a Personal Access Token in the web UI (Settings → Personal Access Tokens) and run the store command it prints (writes ~/.squad/auth, mode 600), or set SQUAD_AUTH_TOKEN in the shell before running /squad-init.