Compare commits

..

1 Commits

Author SHA1 Message Date
Drew Ritter
529e9b287f docs: add README quickstart install links 2026-04-27 17:07:53 -07:00
11 changed files with 20 additions and 257 deletions

View File

@@ -1,23 +0,0 @@
const SUPERPOWERS_GUIDANCE = `## Superpowers
You have access to the Superpowers skill framework through OpenClaw's native skill system.
Before responding to software development work, check whether one of those skills applies.
If a Superpowers skill fits the task, invoke it before proceeding.
Start with \`using-superpowers\` when you need the overall workflow. Common follow-on
skills include \`brainstorming\`, \`writing-plans\`, \`test-driven-development\`,
\`systematic-debugging\`, \`dispatching-parallel-agents\`, and
\`verification-before-completion\`.
When Superpowers instructions mention generic tools, use the closest native OpenClaw
tool or workflow.`;
export default {
id: "superpowers-openclaw",
name: "Superpowers for OpenClaw",
description: "Expose the Superpowers skill pack through OpenClaw's native plugin skill discovery.",
register(api) {
api.on("before_prompt_build", async () => ({ prependSystemContext: SUPERPOWERS_GUIDANCE }));
},
};

View File

@@ -4,7 +4,6 @@
{ "path": ".claude-plugin/plugin.json", "field": "version" },
{ "path": ".cursor-plugin/plugin.json", "field": "version" },
{ "path": ".codex-plugin/plugin.json", "field": "version" },
{ "path": "openclaw.plugin.json", "field": "version" },
{ "path": ".claude-plugin/marketplace.json", "field": "plugins.0.version" },
{ "path": "gemini-extension.json", "field": "version" }
],

View File

@@ -127,33 +127,6 @@ already use it in another harness.
- Detailed docs: [docs/README.opencode.md](docs/README.opencode.md)
### OpenClaw
OpenClaw uses its native plugin system. Install Superpowers separately even if
you already use it in another harness.
- Clone and link the plugin:
```bash
git clone https://github.com/obra/superpowers.git ~/.openclaw/vendor/superpowers
openclaw plugins install --link ~/.openclaw/vendor/superpowers --dangerously-force-unsafe-install
openclaw plugins enable superpowers-openclaw
openclaw gateway restart
```
The override is required because OpenClaw scans the linked plugin directory
during native plugin install. It flags `skills/writing-skills/render-graphs.js`,
an existing Superpowers skill-authoring helper, because that script shells out
to Graphviz. The helper is not part of the OpenClaw runtime hook; review the
source before using the override.
- Verify the plugin and skills are available:
```bash
openclaw plugins info superpowers-openclaw --json
openclaw skills info using-superpowers --json
```
### Cursor
- In Cursor Agent chat, install from marketplace:

View File

@@ -3,7 +3,7 @@
"hooks": {
"sessionStart": [
{
"command": "./hooks/run-hook.cmd session-start"
"command": "./hooks/session-start"
}
]
}

View File

@@ -1,13 +0,0 @@
{
"id": "superpowers-openclaw",
"name": "Superpowers for OpenClaw",
"version": "5.0.7",
"description": "Expose the Superpowers skill pack through OpenClaw's native plugin skill discovery.",
"skills": [
"./skills"
],
"configSchema": {
"type": "object",
"additionalProperties": false
}
}

View File

@@ -2,10 +2,5 @@
"name": "superpowers",
"version": "5.0.7",
"type": "module",
"main": ".opencode/plugins/superpowers.js",
"openclaw": {
"extensions": [
"./.openclaw/index.js"
]
}
"main": ".opencode/plugins/superpowers.js"
}

View File

@@ -52,7 +52,6 @@ EXCLUDES=(
"/.gitattributes"
"/.github/"
"/.gitignore"
"/.openclaw/"
"/.opencode/"
"/.version-bump.json"
"/.worktrees/"
@@ -65,7 +64,6 @@ EXCLUDES=(
"/GEMINI.md"
"/RELEASE-NOTES.md"
"/gemini-extension.json"
"/openclaw.plugin.json"
"/package.json"
# Directories not shipped by canonical Codex plugins

View File

@@ -6,7 +6,7 @@ Skills use Claude Code tool names. When you encounter these in a skill, use your
|-----------------|------------------|
| `Task` tool (dispatch subagent) | `spawn_agent` (see [Named agent dispatch](#named-agent-dispatch)) |
| Multiple `Task` calls (parallel) | Multiple `spawn_agent` calls |
| Task returns result | `wait_agent` |
| Task returns result | `wait` |
| Task completes automatically | `close_agent` to free slot |
| `TodoWrite` (task tracking) | `update_plan` |
| `Skill` tool (invoke a skill) | Skills load natively — just follow the instructions |
@@ -22,12 +22,7 @@ Add to your Codex config (`~/.codex/config.toml`):
multi_agent = true
```
This enables `spawn_agent`, `wait_agent`, and `close_agent` for skills like `dispatching-parallel-agents` and `subagent-driven-development`.
Legacy note: Codex builds before `rust-v0.115.0` exposed spawned-agent
waiting as `wait`. Current Codex uses `wait_agent` for spawned agents. The
`wait` name now belongs to code-mode `exec/wait`, which resumes a yielded exec
cell by `cell_id`; it is not the spawned-agent result tool.
This enables `spawn_agent`, `wait`, and `close_agent` for skills like `dispatching-parallel-agents` and `subagent-driven-development`.
## Named agent dispatch

View File

@@ -14,29 +14,11 @@ Skills use Claude Code tool names. When you encounter these in a skill, use your
| `Skill` tool (invoke a skill) | `activate_skill` |
| `WebSearch` | `google_web_search` |
| `WebFetch` | `web_fetch` |
| `Task` tool (dispatch subagent) | `@agent-name` (see [Subagent support](#subagent-support)) |
| `Task` tool (dispatch subagent) | No equivalent — Gemini CLI does not support subagents |
## Subagent support
## No subagent support
Gemini CLI supports subagents natively via the `@` syntax. Use the built-in `@generalist` agent to dispatch any task — it has access to all tools and follows the prompt you provide.
When a skill says to dispatch a named agent type, use `@generalist` with the full prompt from the skill's prompt template:
| Skill instruction | Gemini CLI equivalent |
|-------------------|----------------------|
| `Task tool (superpowers:implementer)` | `@generalist` with the filled `implementer-prompt.md` template |
| `Task tool (superpowers:spec-reviewer)` | `@generalist` with the filled `spec-reviewer-prompt.md` template |
| `Task tool (superpowers:code-reviewer)` | `@code-reviewer` (bundled agent) or `@generalist` with the filled review prompt |
| `Task tool (superpowers:code-quality-reviewer)` | `@generalist` with the filled `code-quality-reviewer-prompt.md` template |
| `Task tool (general-purpose)` with inline prompt | `@generalist` with your inline prompt |
### Prompt filling
Skills provide prompt templates with placeholders like `{WHAT_WAS_IMPLEMENTED}` or `[FULL TEXT of task]`. Fill all placeholders and pass the complete prompt as the message to `@generalist`. The prompt template itself contains the agent's role, review criteria, and expected output format — `@generalist` will follow it.
### Parallel dispatch
Gemini CLI supports parallel subagent dispatch. When a skill asks you to dispatch multiple independent subagent tasks in parallel, request all of those `@generalist` or named subagent tasks together in the same prompt. Keep dependent tasks sequential, but do not serialize independent subagent tasks just to preserve a simpler history.
Gemini CLI has no equivalent to Claude Code's `Task` tool. Skills that rely on subagent dispatch (`subagent-driven-development`, `dispatching-parallel-agents`) will fall back to single-session execution via `executing-plans`.
## Additional Gemini CLI tools

View File

@@ -135,7 +135,8 @@ EOF
# Note: We use a longer timeout since this is integration testing
# Use --allowed-tools to enable tool usage in headless mode
PROMPT="Execute the implementation plan at docs/superpowers/plans/implementation-plan.md using the subagent-driven-development skill.
# IMPORTANT: Run from superpowers directory so local dev skills are available
PROMPT="Change to directory $TEST_PROJECT and then execute the implementation plan at docs/superpowers/plans/implementation-plan.md using the subagent-driven-development skill.
IMPORTANT: Follow the skill exactly. I will be verifying that you:
1. Read the plan once at the beginning
@@ -146,14 +147,9 @@ IMPORTANT: Follow the skill exactly. I will be verifying that you:
Begin now. Execute the plan."
PLUGIN_DIR=$(cd "$SCRIPT_DIR/../.." && pwd)
# Run claude from inside the test project so its session JSONL lands in a
# project-specific directory under ~/.claude/projects/, isolated from any
# other concurrent claude sessions.
echo "Running Claude (plugin-dir: $PLUGIN_DIR, cwd: $TEST_PROJECT)..."
echo "Running Claude (output will be shown below and saved to $OUTPUT_FILE)..."
echo "================================================================================"
cd "$TEST_PROJECT" && timeout 1800 claude -p "$PROMPT" --plugin-dir "$PLUGIN_DIR" --allowed-tools=all --permission-mode bypassPermissions 2>&1 | tee "$OUTPUT_FILE" || {
cd "$SCRIPT_DIR/../.." && timeout 1800 claude -p "$PROMPT" --allowed-tools=all --add-dir "$TEST_PROJECT" --permission-mode bypassPermissions 2>&1 | tee "$OUTPUT_FILE" || {
echo ""
echo "================================================================================"
echo "EXECUTION FAILED (exit code: $?)"
@@ -165,17 +161,13 @@ echo ""
echo "Execution complete. Analyzing results..."
echo ""
# Find the session transcript. Because we ran claude from $TEST_PROJECT (a
# unique tmp dir), its sessions live in their own ~/.claude/projects/ folder
# and we can pick the most-recent one without racing other concurrent sessions.
# Resolve the real path because macOS mktemp returns /var/... but claude
# normalizes it to /private/var/... when naming the project dir.
TEST_PROJECT_REAL=$(cd "$TEST_PROJECT" && pwd -P)
# Claude normalizes the cwd to a directory name by replacing every non-alphanumeric
# character with `-` (so `_`, `.`, `/` all become `-`).
SESSION_DIR="$HOME/.claude/projects/$(echo "$TEST_PROJECT_REAL" | sed 's|[^a-zA-Z0-9]|-|g')"
# `|| true` prevents pipefail killing the script if ls gets SIGPIPE'd by head.
SESSION_FILE=$(ls -t "$SESSION_DIR"/*.jsonl 2>/dev/null | head -1 || true)
# Find the session transcript
# Session files are in ~/.claude/projects/-<working-dir>/<session-id>.jsonl
WORKING_DIR_ESCAPED=$(echo "$SCRIPT_DIR/../.." | sed 's/\//-/g' | sed 's/^-//')
SESSION_DIR="$HOME/.claude/projects/$WORKING_DIR_ESCAPED"
# Find the most recent session file (created during this test run)
SESSION_FILE=$(find "$SESSION_DIR" -name "*.jsonl" -type f -mmin -60 2>/dev/null | sort -r | head -1)
if [ -z "$SESSION_FILE" ]; then
echo "ERROR: Could not find session transcript file"
@@ -202,9 +194,9 @@ else
fi
echo ""
# Test 2: Subagents were used (Agent / Task tool — name varies by harness version)
# Test 2: Subagents were used (Task tool)
echo "Test 2: Subagents dispatched..."
task_count=$(grep -cE '"name":"(Agent|Task)"' "$SESSION_FILE" || echo "0")
task_count=$(grep -c '"name":"Task"' "$SESSION_FILE" || echo "0")
if [ "$task_count" -ge 2 ]; then
echo " [PASS] $task_count subagents dispatched"
else

View File

@@ -1,135 +0,0 @@
#!/usr/bin/env bash
# Test: OpenClaw native plugin package
# Verifies the Superpowers repo exposes a native OpenClaw plugin contract.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
cd "$REPO_ROOT"
echo "=== Test: OpenClaw native plugin package ==="
echo "Test 1: Checking OpenClaw manifest..."
node <<'NODE'
import fs from "node:fs";
const manifestPath = "openclaw.plugin.json";
if (!fs.existsSync(manifestPath)) {
throw new Error(`${manifestPath} is missing`);
}
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
if (manifest.id !== "superpowers-openclaw") {
throw new Error(`unexpected manifest id: ${manifest.id}`);
}
if (manifest.version !== pkg.version) {
throw new Error(`manifest version ${manifest.version} must match package version ${pkg.version}`);
}
if (!Array.isArray(manifest.skills) || manifest.skills.length !== 1 || manifest.skills[0] !== "./skills") {
throw new Error(`unexpected skills declaration: ${JSON.stringify(manifest.skills)}`);
}
if (
!manifest.configSchema ||
manifest.configSchema.type !== "object" ||
manifest.configSchema.additionalProperties !== false ||
manifest.configSchema.properties !== undefined
) {
throw new Error(`manifest must declare an empty object configSchema: ${JSON.stringify(manifest.configSchema)}`);
}
if ("entrypoint" in manifest) {
throw new Error("OpenClaw entrypoints belong in package.json openclaw.extensions, not openclaw.plugin.json");
}
if ("hooks" in manifest) {
throw new Error("OpenClaw hook registration belongs in the runtime entrypoint, not openclaw.plugin.json");
}
NODE
echo " [PASS] Manifest declares plugin skills correctly"
echo "Test 2: Checking package OpenClaw extension metadata..."
node <<'NODE'
import fs from "node:fs";
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
if (pkg.name !== "superpowers") {
throw new Error(`package name changed unexpectedly: ${pkg.name}`);
}
if (pkg.type !== "module") {
throw new Error("OpenClaw runtime should preserve the repo's ESM package mode");
}
const extensions = pkg.openclaw?.extensions;
if (!Array.isArray(extensions) || extensions.length !== 1 || extensions[0] !== "./.openclaw/index.js") {
throw new Error(`unexpected openclaw.extensions: ${JSON.stringify(extensions)}`);
}
NODE
echo " [PASS] package.json points OpenClaw at the runtime entrypoint"
echo "Test 3: Checking runtime entrypoint syntax and hook behavior..."
node --check .openclaw/index.js
node <<'NODE'
const module = await import(new URL("./.openclaw/index.js", import.meta.url));
const plugin = module.default;
if (!plugin || plugin.id !== "superpowers-openclaw" || typeof plugin.register !== "function") {
throw new Error("OpenClaw runtime must default-export a plugin with register(api)");
}
const hooks = [];
const api = {
pluginConfig: {},
rootDir: process.cwd(),
logger: { warn(message) { throw new Error(`unexpected warning: ${message}`); } },
on(name, handler) {
hooks.push({ name, handler });
},
};
plugin.register(api);
if (hooks.length !== 1 || hooks[0].name !== "before_prompt_build") {
throw new Error(`unexpected hooks: ${JSON.stringify(hooks.map((hook) => hook.name))}`);
}
const result = await hooks[0].handler();
if (!result?.prependSystemContext?.includes("Superpowers")) {
throw new Error("before_prompt_build hook must inject Superpowers guidance");
}
if (result.prependSystemContext.includes("~/.openclaw/skills")) {
throw new Error("native plugin guidance must not advertise managed skill symlinks");
}
NODE
echo " [PASS] Runtime entrypoint registers the prompt hook"
echo "Test 4: Checking README install flow..."
if ! grep -q 'openclaw plugins install --link ~/.openclaw/vendor/superpowers' README.md; then
echo " [FAIL] README must document linked OpenClaw plugin install"
exit 1
fi
if ! grep -q -- '--dangerously-force-unsafe-install' README.md; then
echo " [FAIL] README must document OpenClaw scanner override required by existing helper scripts"
exit 1
fi
if ! grep -q 'skills/writing-skills/render-graphs.js' README.md; then
echo " [FAIL] README must explain the exact Superpowers helper that triggers OpenClaw's scanner"
exit 1
fi
if ! grep -q 'not part of the OpenClaw runtime hook' README.md; then
echo " [FAIL] README must explain that the flagged helper is not part of the OpenClaw runtime hook"
exit 1
fi
if ! grep -q 'openclaw plugins enable superpowers-openclaw' README.md; then
echo " [FAIL] README must document enabling the OpenClaw plugin"
exit 1
fi
if ! grep -q 'openclaw gateway restart' README.md; then
echo " [FAIL] README must document restarting the gateway"
exit 1
fi
if grep -q 'OPENCLAW_SKILLS_DIR\|ln -s\|AGENTS-snippet\|.openclaw/INSTALL.md' README.md; then
echo " [FAIL] README must not use the legacy symlink/snippet wrapper or extra install doc"
exit 1
fi
echo " [PASS] README documents native plugin commands"
echo ""
echo "=== OpenClaw native plugin tests passed ==="