Claude
Skills
Sign in
Back

swain-init

Included with Lifetime
$97 forever

Project onboarding and session entry point for swain. On first run, performs full onboarding: migrates CLAUDE.md to AGENTS.md, verifies vendored tk, configures pre-commit security hooks, and offers swain governance rules — then writes a .swain/init.json marker. On subsequent runs, detects the marker and runs the per-session fast path (greeting, focus lane, session state). Use as a single entry point — it routes automatically. Triggers also on: 'session', 'session info', 'focus on', 'tab name'.

Securityscripts

What this skill does

<!-- swain-model-hint: sonnet, effort: medium -->

# Project Onboarding

One-time setup for adopting swain in a project. This skill is **not idempotent** — it migrates files and installs tools. For per-session health checks, use swain-doctor.

## Preflight

Before any phase, run the preflight script to gather environment state. This single call replaces all inline check blocks — phases below read from the JSON output instead of running shell commands.

```bash
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
PREFLIGHT_SCRIPT="$(find "$REPO_ROOT" -path '*/swain-init/scripts/swain-init-preflight.sh' -print -quit 2>/dev/null)"
PREFLIGHT_JSON=$( bash "$PREFLIGHT_SCRIPT" --repo-root "$REPO_ROOT" 2>/dev/null )
echo "$PREFLIGHT_JSON"
```

Store `PREFLIGHT_JSON` for use in all phases below. Every decision references a field from this JSON — do not run additional check commands unless performing a mutation.

## Phase 0: Already-initialized detection

Read `marker.action` from the preflight JSON.

- **`"delegate"`** — same major version. Tell the user:
  > Project already initialized (swain `marker.release_version`, init v`marker.last_version`). Delegating to swain-session.

  Skip to **Phase 7 (Session Start)** below. Do not run Phases 1–6.

- **`"upgrade"`** — newer major version available. Tell the user:
  > Project was initialized with swain `marker.last_release_version` (init v`marker.last_version`). Current: `marker.release_version` (init v`marker.current_version`). Consider running `/swain update` to pick up new features.
  > Starting session.

  Skip to **Phase 7 (Session Start)** below. Do not re-run onboarding — upgrades are handled by swain-update, not swain-init.

- **`"onboard"`** — no marker found. Proceed with full onboarding (Phases 1–6).

## Phase 1: CLAUDE.md → AGENTS.md migration

Goal: establish the `@AGENTS.md` include pattern so project instructions live in AGENTS.md (which works across Claude Code, GitHub, and other tools that read AGENTS.md natively).

Read `migration.state` from the preflight JSON.

### If `"fresh"`

Create both files:

- **CLAUDE.md:** `@AGENTS.md`
- **AGENTS.md:** `# AGENTS.md` (empty — governance added in Phase 5)

### If `"migrated"`

Skip to Phase 2.

### If `"standard"`

1. Copy CLAUDE.md content to AGENTS.md (preserve everything).
2. If CLAUDE.md contains a `<!-- swain governance -->` block, strip it from the AGENTS.md copy — it will be re-added cleanly in Phase 5.
3. Replace CLAUDE.md with `@AGENTS.md`.

Tell the user:
> Migrated your CLAUDE.md content to AGENTS.md and replaced CLAUDE.md with `@AGENTS.md`. Your existing instructions are preserved — Claude Code reads AGENTS.md via the include directive.

### If `"split"`

Both files have content. Ask the user:

> Both CLAUDE.md and AGENTS.md have content. How should I proceed?
> 1. **Merge** — append CLAUDE.md content to the end of AGENTS.md, then replace CLAUDE.md with `@AGENTS.md`
> 2. **Keep AGENTS.md** — discard CLAUDE.md content, replace CLAUDE.md with `@AGENTS.md`
> 3. **Abort** — leave both files as-is, skip migration

If merge: append CLAUDE.md content (minus any `<!-- swain governance -->` block) to AGENTS.md, replace CLAUDE.md with `@AGENTS.md`.

## Phase 2: Verify dependencies

### Step 2.1 — uv

Read `uv.available` from the preflight JSON.

If `false`, install:

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```

If installation fails, tell the user:
> uv installation failed. You can install it manually (https://docs.astral.sh/uv/getting-started/installation/) — swain scripts require uv for Python execution.

Skip the rest of Phase 2 on failure (don't block init on uv, but warn that scripts will not function without it).

### Step 2.2 — Vendored tk

Read `tk.path` and `tk.healthy` from the preflight JSON.

If `tk.path` is null or `tk.healthy` is false, tell the user:
> The vendored tk script was not found or is broken. This usually means the swain-do skill was not fully installed. Try running `/swain update` to reinstall skills.

### Step 2.3 — Migrate from beads (if applicable)

Read `beads.exists` and `beads.has_backup` from the preflight JSON.

If `beads.exists` is true and `beads.has_backup` is true, offer migration:

> Found existing `.beads/` data. Migrate tasks to tk?
> This will convert `.beads/backup/issues.jsonl` to `.tickets/` markdown files.

If user agrees, run migration:
```bash
TK_BIN="$(cd "$(dirname "$(find . .claude .agents -path '*/swain-do/bin/tk' -print -quit 2>/dev/null)")" && pwd)"
export PATH="$TK_BIN:$PATH"
cp .beads/backup/issues.jsonl .beads/issues.jsonl 2>/dev/null
ticket-migrate-beads
ls .tickets/*.md 2>/dev/null | wc -l
```

Tell the user the results and that `.beads/` can be removed after verification.

If `beads.exists` is false, skip. tk creates `.tickets/` on first `tk create`.

### Step 2.4 — Operator bin/ symlinks (SPEC-214, ADR-019)

Read `bin_manifests` from the preflight JSON. For each entry, create `bin/` symlinks:

```bash
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
BIN_DIR="$REPO_ROOT/bin"
SKILLS_ROOT="$REPO_ROOT/.agents/skills"
for manifest_dir in "$SKILLS_ROOT"/*/usr/bin; do
  [ -d "$manifest_dir" ] || continue
  for entry in "$manifest_dir"/*; do
    [ -e "$entry" ] || [ -L "$entry" ] || continue
    cmd_name="$(basename "$entry")"
    script_path="$(cd "$manifest_dir" && readlink -f "$cmd_name" 2>/dev/null || true)"
    [ -z "$script_path" ] || [ ! -f "$script_path" ] && continue
    rel_path="$(python3 -c "import os,sys; print(os.path.relpath(sys.argv[1], sys.argv[2]))" "$script_path" "$BIN_DIR" 2>/dev/null || echo "")"
    [ -z "$rel_path" ] && continue
    if [ -L "$BIN_DIR/$cmd_name" ]; then
      echo "already linked: $cmd_name"
    elif [ -e "$BIN_DIR/$cmd_name" ]; then
      echo "conflict — bin/$cmd_name exists as a real file; skipping"
    else
      mkdir -p "$BIN_DIR"
      ln -sf "$rel_path" "$BIN_DIR/$cmd_name"
      echo "created bin/$cmd_name"
    fi
  done
done
```

Tell the user which operator commands are now available in `bin/`.

If `bin_manifests` is empty, skip silently.

## Phase 3: Pre-commit security hooks

Goal: configure pre-commit hooks for secret scanning so credentials are caught before they enter git history. Default scanner is gitleaks; additional scanners (TruffleHog, Trivy, OSV-Scanner) are opt-in.

### Step 3.1 — Check for existing config

Read `precommit.config_exists` from the preflight JSON.

**If true:** Present the current `.pre-commit-config.yaml` content and ask:

> Found existing `.pre-commit-config.yaml`. How should I proceed?
> 1. **Merge** — add swain's gitleaks hook alongside your existing hooks
> 2. **Skip** — leave pre-commit config unchanged
> 3. **Replace** — overwrite with swain's default config (your existing hooks will be lost)

If user chooses Skip, skip to Phase 4.

**If false:** Proceed to Step 3.2.

### Step 3.2 — Install pre-commit framework

Read `precommit.framework` from the preflight JSON.

If false, install:

```bash
uv tool install pre-commit
```

If uv is unavailable or installation fails, warn:
> pre-commit framework not available. You can install it manually (`uv tool install pre-commit` or `pip install pre-commit`). Skipping hook setup.

Skip to Phase 4 if pre-commit cannot be installed.

### Step 3.3 — Create or update `.pre-commit-config.yaml`

The default config enables gitleaks:

```yaml
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.21.2
    hooks:
      - id: gitleaks
```

If the user requested additional scanners (via `--scanner` flags or when asked), add their hooks:

**TruffleHog (opt-in):**
```yaml
  - repo: https://github.com/trufflesecurity/trufflehog
    rev: v3.88.1
    hooks:
      - id: trufflehog
        args: ['--results=verified,unknown']
```

**Trivy (opt-in):**
```yaml
  - repo: https://github.com/cebidhem/pre-commit-trivy
    rev: v1.0.0
    hooks:
      - id: trivy-fs
        args: ['--severity', 'HIGH,CRITICAL', '--scanners', 'vuln,license']
```

**OS
Files: 21
Size: 79.0 KB
Complexity: 81/100
Category: Security

Related in Security