feat: add Devin CLI support

Devin CLI's `devin plugins install obra/superpowers` fails today because the
repo has no `.devin-plugin/plugin.json` manifest. Add the manifest (skills are
auto-discovered from the co-located skills/ directory), a Devin tool mapping
linked from using-superpowers' Platform Adaptation section, a README install
section, version tracking in .version-bump.json, a Codex-sync exclude for the
new dotdir, and a CI-safe test mirroring the kimi/antigravity test style.

Bootstrap rides Devin's native skill surfacing: every installed skill's
name + description is injected into the system prompt at session start with a
standing instruction to invoke matching skills via the native skill tool.
Acceptance test ("Let's make a react todo list") passes in a clean session:
using-superpowers and brainstorming auto-trigger before any code is written.
This commit is contained in:
Caio Lopes
2026-08-07 12:47:29 -07:00
committed by Drew Ritter
parent d6a10aba55
commit 09a567b6f4
7 changed files with 144 additions and 1 deletions
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env bash
# Validate the Devin CLI integration. `devin plugins install obra/superpowers`
# reads `.devin-plugin/plugin.json` and auto-discovers the co-located `skills/`
# directory; Devin CLI surfaces every installed skill's name + description in
# the system prompt at session start and invokes them via its native `skill`
# tool, so there is no hook or injector scaffold to test. What IS Devin-specific
# is the manifest and the tool mapping — subagent dispatch via run_subagent
# profiles and task tracking via todo_write — and SKILL.md pointing at it.
#
# Mirrors tests/kimi/test-plugin-manifest.sh (manifest) and
# tests/antigravity/test-antigravity-tools.sh (mapping). CI-safe: does not
# require `devin` installed.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
MANIFEST="$REPO_ROOT/.devin-plugin/plugin.json"
MAPPING="$REPO_ROOT/skills/using-superpowers/references/devin-tools.md"
SKILL="$REPO_ROOT/skills/using-superpowers/SKILL.md"
fail() { echo "FAIL: $*" >&2; exit 1; }
echo "test-devin-plugin: checking Devin CLI manifest and tool mapping"
# --- Manifest is valid and matches the repo version -------------------------
[ -f "$MANIFEST" ] || fail "manifest missing at $MANIFEST"
python3 - "$MANIFEST" <<'PY'
import json
import sys
from pathlib import Path
manifest_path = Path(sys.argv[1])
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
repo_root = manifest_path.parents[1]
if manifest.get("name") != "superpowers":
raise AssertionError(f"plugin name: expected 'superpowers', got {manifest.get('name')!r}")
package = json.loads((repo_root / "package.json").read_text(encoding="utf-8"))
if manifest.get("version") != package.get("version"):
raise AssertionError(
f"manifest version {manifest.get('version')!r} != package.json version {package.get('version')!r}"
)
# Devin CLI plugins carry skills only (auto-discovered from ./skills/); the
# manifest supports metadata + dependency lists, nothing executable.
unsupported = ["skills", "hooks", "commands", "sessionStart", "contextFileName", "inject"]
present = sorted(field for field in unsupported if field in manifest)
if present:
raise AssertionError("unsupported Devin manifest fields present: " + ", ".join(present))
version_config = json.loads((repo_root / ".version-bump.json").read_text(encoding="utf-8"))
entries = version_config.get("files")
if not isinstance(entries, list) or not any(
entry.get("path") == ".devin-plugin/plugin.json" and entry.get("field") == "version"
for entry in entries
if isinstance(entry, dict)
):
raise AssertionError(".version-bump.json must update .devin-plugin/plugin.json version")
print("Devin plugin manifest looks good")
PY
# --- Mapping exists ----------------------------------------------------------
[ -f "$MAPPING" ] || fail "tool mapping missing at $MAPPING"
# --- Core action→tool mappings are documented --------------------------------
for tool in skill run_subagent todo_write ask_user_question; do
grep -q "$tool" "$MAPPING" \
|| fail "mapping does not document the '$tool' tool"
done
# --- Subagents use the built-in profiles --------------------------------------
grep -q 'subagent_general' "$MAPPING" \
|| fail "mapping does not document the 'subagent_general' profile"
grep -q 'subagent_explore' "$MAPPING" \
|| fail "mapping does not document the 'subagent_explore' profile"
# --- SKILL.md Platform Adaptation links the mapping ---------------------------
grep -q "devin-tools.md" "$SKILL" \
|| fail "SKILL.md Platform Adaptation does not reference devin-tools.md"
echo "PASS: Devin CLI plugin valid (manifest, tool mapping, SKILL.md link)"