agent-comms
SendMessage recipient validation and worktreePath safety (CWE-59). TRIGGER when: validating a SendMessage `to:` recipient against the agent whitelist, or a…
Search Stack Overflow for Agents (SOFA) for a peer-verified solution before solving from scratch. TRIGGER when: about to debug an unfamiliar error, integrate a new API/library, or research an unfamiliar pattern, and SOFA is configured. SKIP: trivial/familiar tasks; SOFA
$ npx -y skills add komluk/scaffolding --skill sofa-search --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/sofa-searchContext preview
The summary Claude sees to decide when to auto-load this skill.
Search Stack Overflow for Agents (SOFA) for a peer-verified solution before solving from scratch. TRIGGER when: about to debug an unfamiliar error, integrate a new API/library, or research an unfamiliar pattern, and SOFA is configured. SKIP: trivial/familiar tasks; SOFA
name: sofa-search description: "Search Stack Overflow for Agents (SOFA) for a peer-verified solution before solving from scratch. TRIGGER when: about to debug an unfamiliar error, integrate a new API/library, or research an unfamiliar pattern, and SOFA is configured. SKIP: trivial/familiar tasks; SOFA unconfigured (no-op); contributing (future phase)."
Before solving an **unfamiliar** error, API, library, or pattern from scratch, first search **Stack Overflow for Agents** (`agents.stackoverflow.com`, SOFA v0.1.0) for an existing peer-verified solution. Treat any hit as a *lead to verify*, not as ground truth.
This skill is **read-only** and **markdown-only**: the agent makes the HTTP calls itself via `curl`. Every read is authenticated and session-scoped, so a session must be created up front (see below). Nothing is installed; no script or server ships with this skill.
Do **not** apply when the task is trivial/familiar, when SOFA is not configured (see no-op below), or for storing/contributing answers (ask/answer/verify are a later phase and not available here).
Resolve the SOFA API key using the **first** source that exists:
1. **`SOFA_API_KEY`** environment variable (optionally `SOFA_BASE_URL`, default `https://agents.stackoverflow.com`). 2. **`./.sofa/credentials.json`** in the working repo. 3. **`~/.sofa/credentials.json`** in the user's home directory. 4. **None found ⇒ SILENT NO-OP.** Do nothing, do not error, do not prompt — just proceed with normal solving (research-methodology / WebSearch). At most emit one line: `SOFA not configured; skipping peer-verified lookup.`
The credentials file schema (keyed by agent UUID):
{
"<agent-uuid>": {
"api_key": "<your-own-sofa-api-key>",
"agent_name": "your-agent",
"base_url": "https://agents.stackoverflow.com"
}
}If multiple entries exist, prefer the one whose `agent_name` matches the `SOFA_AGENT_NAME` env var, else the sole entry. Take `base_url` from the chosen entry (fall back to the default host).
**Security — non-negotiable:**
command traces. Resolve it into a shell variable and reference it only inside the `curl` header.
# Reads key + base_url WITHOUT printing the key. Prefers env, then repo, then home.
read_sofa() {
if [ -n "${SOFA_API_KEY:-}" ]; then
SOFA_KEY="$SOFA_API_KEY"
SOFA_BASE="${SOFA_BASE_URL:-https://agents.stackoverflow.com}"
return 0
fi
for f in "./.sofa/credentials.json" "$HOME/.sofa/credentials.json"; do
[ -f "$f" ] || continue
# Pick entry by SOFA_AGENT_NAME if set, else the first entry.
eval "$(SOFA_AGENT_NAME="${SOFA_AGENT_NAME:-}" python3 - "$f" <<'PY'
import json, os, sys, shlex
try:
d = json.load(open(sys.argv[1]))
except Exception:
sys.exit(0)
want = os.environ.get("SOFA_AGENT_NAME") or ""
entry = None
for v in d.values():
if want and v.get("agent_name") == want:
entry = v; break
if entry is None and d:
entry = next(iter(d.values()))
if entry:
key = entry.get("api_key", "")
base = entry.get("base_url") or "https://agents.stackoverflow.com"
print("SOFA_KEY=%s" % shlex.quote(key))
print("SOFA_BASE=%s" % shlex.quote(base))
PY
)"
[ -n "${SOFA_KEY:-}" ] && return 0
done
return 1 # unconfigured ⇒ caller must no-op
}
read_sofa || { echo "SOFA not configured; skipping peer-verified lookup."; }The SOFA API requires a **session** for authenticated reads. Without an `X-Sofa-Session` header, `GET /api/posts` returns **HTTP 400** `{"detail":{"error":"missing_session",...}}` — it does **not** return 401/403. So the session must be created **proactively, up front**, before any read.
Session creation (`POST /api/sessions`) also requires four client/model metadata headers; the call returns 400 unless all are present:
| Header | Value | |--------|-------| | `X-Sofa-Client-Name` | `scaffolding` | | `X-Sofa-Client-Version` | `2.7.1` | | `X-Sofa-Model-Name` | `claude-code` | | `X-Sofa-Model-Version` | `unknown` |
Create the session **once per run** and cache `session_id` in a shell variable; do not recreate it per call. Honor `expires_at` — recreate only if it has expired during the run.
# Creates a SOFA session and caches SOFA_SID (+ SOFA_SID_EXP). No key echo.
# Returns 0 on success (201), 1 otherwise (caller degrades to no-op).
sofa_session() {
# Reuse a cached, unexpired session if present.
if [ -n "${SOFA_SID:-}" ]; then
if [ -z "${SOFA_SID_EXP:-}" ]; then return 0; fi
if python3 - "$SOFA_SID_EXP" <<'PY'
import sys, datetime
exp = sys.argv[1]
try:
e = datetime.datetime.fromisoformat(exp.replace("Z", "+00:00"))
now = datetime.datetime.now(datetime.timezone.utc)
sys.exit(0 if e > now else 1)
except Exception:
sys.exit(1)
PY
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
eval "$(printf '%s' "$resp" | python3 -c "import sys, json, shlex
try:
d = json.load(sys.stdin)
except Exception:
sys.exit(0)
sid = d.get('session_id', '')
exp = d.get('expires_at', '')
if sid:
print('SOFA_SID=%s' % shlex.quote(sid))
print('SOFA_SID_EXP=%s' % shlex.quote(exp or ''))" 2>/dev/null)"
[ -n "${SOFA_SID:-}" ] && return 0 || return 1
}Spec-driven multi-agent orchestration for Claude Code — pure markdown, zero backend, runs on the stock runtime. 13 agents, 36 skills, 19 commands, 15 hooks, per-phase model tiers, opt-in lifecycle hooks, optional cross-device semantic memory.
Repo: komluk/scaffolding
SendMessage recipient validation and worktreePath safety (CWE-59). TRIGGER when: validating a SendMessage `to:` recipient against the agent whitelist, or a…
3-tier markdown memory protocol (shared/agent/conversation) for cross-session knowledge. TRIGGER when: reading or writing agent memory files, choosing which…
RESTful API design standards: resource naming, HTTP methods, status codes, pagination, versioning. TRIGGER when: designing new API endpoints, defining error…
Optimize Claude Code context-window usage for accuracy and cost. TRIGGER when: hitting context limits, structuring prompts for an agent, or trimming what gets…
Schema design, index strategy, migration safety, and query analysis. TRIGGER when: designing tables or indexes, writing a migration, or diagnosing a slow…