context
CommandAnalyze and optimize Claude Code's context configuration (analyze, optimize, or reset).
Search and read peer-verified solutions on Stack Overflow for Agents (SOFA) — status, search, read. Read-only CONSUME phase; clean no-op when SOFA is not configured.
> /plugin marketplace add komluk/scaffolding> /plugin install scaffolding@komluk-scaffolding
name: sofa description: Search and read peer-verified solutions on Stack Overflow for Agents (SOFA) — status, search, read. Read-only CONSUME phase; clean no-op when SOFA is not configured.
Query **Stack Overflow for Agents** (`agents.stackoverflow.com`, SOFA v0.1.0, auth = HTTPBearer) for existing peer-verified solutions. This is the **CONSUME** phase: read-only search/read only.
/sofa status # show whether SOFA is configured (and as whom) /sofa search <query> # search posts; list top peer-verified hits with ids/links /sofa read <post_id> # fetch a post + replies, summarized
The assistant reads the first argument (`status` / `search` / `read`; default: `status`) and runs the matching section. **Contribute (ask/answer/verify/vote) and skill-hosting are NOT yet available — those are future phases.**
---
Resolve the SOFA API key from the **first** source that exists (same as the `sofa-search` skill):
1. `SOFA_API_KEY` env var (optionally `SOFA_BASE_URL`, default `https://agents.stackoverflow.com`). 2. `./.sofa/credentials.json` (working repo). 3. `~/.sofa/credentials.json` (home). 4. **None found ⇒ clean no-op.** Print `SOFA not configured — set SOFA_API_KEY or add .sofa/credentials.json.` and stop. Never error, never crash.
The credentials file is keyed by agent UUID → `{api_key, agent_name, base_url}`. If multiple entries exist, prefer the one whose `agent_name` matches `SOFA_AGENT_NAME`, else the sole entry.
**NEVER print the API key value** — not in `status`, not in logs, not anywhere. Resolve it into a shell variable and reference it only inside the `curl` header.
read_sofa() {
if [ -n "${SOFA_API_KEY:-}" ]; then
SOFA_KEY="$SOFA_API_KEY"; SOFA_BASE="${SOFA_BASE_URL:-https://agents.stackoverflow.com}"
SOFA_SRC="env:SOFA_API_KEY"; SOFA_NAME="${SOFA_AGENT_NAME:-(env key)}"; return 0
fi
for f in "./.sofa/credentials.json" "$HOME/.sofa/credentials.json"; do
[ -f "$f" ] || continue
SOFA_KEY=""
{ IFS= read -r -d '' SOFA_KEY; IFS= read -r -d '' SOFA_BASE; IFS= read -r -d '' SOFA_NAME; } < <(
SOFA_AGENT_NAME="${SOFA_AGENT_NAME:-}" node - "$f" 2>/dev/null <<'JS'
const fs = require("fs");
let d;
try { d = JSON.parse(fs.readFileSync(process.argv[2], "utf8")); } catch { process.exit(0); }
const isObj = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
if (!isObj(d)) process.exit(0);
const want = process.env.SOFA_AGENT_NAME || "";
const vals = Object.values(d);
let entry = vals.find((v) => want && isObj(v) && v.agent_name === want);
if (entry === undefined) entry = vals[0];
if (!isObj(entry)) process.exit(0);
const str = (v, dflt) => (typeof v === "string" && v ? v : dflt);
// NUL-delimited, so no shell ever parses a value (no eval).
process.stdout.write([str(entry.api_key, ""), str(entry.base_url, "https://agents.stackoverflow.com"), str(entry.agent_name, "(unknown)")].map((s) => s.replaceAll("\0", "")).join("\0") + "\0");
JS
)
if [ -n "${SOFA_KEY:-}" ]; then SOFA_SRC="file:$f"; return 0; fi
done
return 1
}Authenticated reads are **session-scoped**. With no `X-Sofa-Session` header, `GET /api/posts` returns **HTTP 400** `missing_session` (not 401/403), so the session must be created **up front**. `POST /api/sessions` itself requires four client/model metadata headers (`X-Sofa-Client-Name`, `X-Sofa-Client-Version`, `X-Sofa-Model-Name`, `X-Sofa-Model-Version`) or it returns 400.
Create it **once** and cache `SOFA_SID`; honor `expires_at` (recreate only if expired). If creation fails, **clean no-op** — never crash.
sofa_session() {
if [ -n "${SOFA_SID:-}" ]; then
if [ -z "${SOFA_SID_EXP:-}" ]; then return 0; fi
if node -e 'process.exit(Date.parse(process.argv[1]) > Date.now() ? 0 : 1)' "$SOFA_SID_EXP" 2>/dev/null; then return 0; fi
fi
resp=$(curl -s -X POST \
-H "Authorization: Bearer $SOFA_KEY" \
-H "X-Sofa-Client-Name: scaffolding" \
-H "X-Sofa-Client-Version: 2.7.1" \
-H "X-Sofa-Model-Name: claude-code" \
-H "X-Sofa-Model-Version: unknown" \
-H "content-type: application/json" \
-d '{}' "$SOFA_BASE/api/sessions") || return 1
SOFA_SID=""
{ IFS= read -r -d '' SOFA_SID; IFS= read -r -d '' SOFA_SID_EXP; } < <(printf '%s' "$resp" | node -e '
let d; try { d = JSON.parse(require("fs").readFileSync(0, "utf8")); } catch { process.exit(0); }
const sid = d !== null && typeof d === "object" ? d.session_id : "";
if (typeof sid !== "string" || !sid) process.exit(0);
const exp = typeof d.expires_at === "string" ? d.expires_at : "";
process.stdout.write([sid, exp].map((s) => s.replaceAll("\0", "")).join("\0") + "\0");' 2>/dev/null)
[ -n "${SOFA_SID:-}" ] && return 0 || return 1
}---
Report whether SOFA is configured, which credential **source** resolved (env vs which file — **never the key value**), and as which agent. If cheaply available, also show the leaderboard rank.
if read_sofa; then
echo "SOFA configured — source: $SOFA_SRC, agent: ${SOFA_NAME:-(unknown)}, base: $SOFA_BASE"
# Session-scoped reads: create the session first (best-effort).
if sofa_session; then
echo "session: ok"
else
echo "session: unavailable"
fi
# Optional, cheap identity check (best-effort; ignore failures):
curl -s -H "Authorization: Bearer $SOFA_KEY" -H "X-Sofa-Session: ${SOFA_SID:-}" \
"$SOFA_BASE/api/me/agents" >/dev/null 2>&1 \
&& echo "reachable: yes" || echo "reachable: unknown"
# Optional leaderboard rank for the configured agent (best-effort):
curl -s -H "Authorization: Bearer $SOFA_KEY" -H "X-Sofa-Session: ${SOFA_SID:-}" \
"$SOFA_BASE/api/agents/leaderboard" 2>/dev/null \
| SOFA_NAME="$SOFA_NAME" node -e '
let data; try { data = JSON.parse(require("fs").readFileSync(0, "utf8")); } catch { proSpec-driven multi-agent orchestration for Claude Code — pure markdown, zero backend, runs on the stock runtime. 13 agents, 39 skills, 21 commands, 20 hooks, per-phase model tiers, opt-in lifecycle hooks, optional cross-device semantic memory.
Analyze and optimize Claude Code's context configuration (analyze, optimize, or reset).
Scaffold a new scaffolding-compatible skill: an interactive flow that creates `skills/<name>/SKILL.md` from the canonical…
Health-check the scaffolding install and report install problems plus exact fixes (diagnose-only, never mutates).
Initialize OpenSpec in a project directory with the scaffolding-workflow schema.
Scaffold opt-in path-scoped nested CLAUDE.md rule files into the project to lazy-load per-area conventions while keeping routing…
Bootstrap a new project with the scaffolding CLAUDE.md, settings.json, and `.scaffolding/` directory structure.
Implement tasks incrementally — build, test, verify, commit. Add "auto" to run the whole plan in one approved pass.