mirror of
https://github.com/obra/superpowers.git
synced 2026-04-29 21:49:04 +08:00
Compare commits
1 Commits
codex/open
...
codex/pri-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68040f2cde |
@@ -36,9 +36,6 @@
|
||||
"I've got an idea for something I'd like to build.",
|
||||
"Let's add a feature to this project."
|
||||
],
|
||||
"websiteURL": "https://github.com/obra/superpowers",
|
||||
"privacyPolicyURL": "https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement",
|
||||
"termsOfServiceURL": "https://docs.github.com/en/site-policy/github-terms/github-terms-of-service",
|
||||
"brandColor": "#F59E0B",
|
||||
"composerIcon": "./assets/superpowers-small.svg",
|
||||
"logo": "./assets/app-icon.png",
|
||||
|
||||
@@ -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 }));
|
||||
},
|
||||
};
|
||||
@@ -14,14 +14,10 @@ Add superpowers to the `plugin` array in your `opencode.json` (global or project
|
||||
}
|
||||
```
|
||||
|
||||
Restart OpenCode. The plugin installs through OpenCode's plugin manager and
|
||||
registers all skills.
|
||||
Restart OpenCode. That's it — the plugin auto-installs and registers all skills.
|
||||
|
||||
Verify by asking: "Tell me about your superpowers"
|
||||
|
||||
OpenCode uses its own plugin install. If you also use Claude Code, Codex, or
|
||||
another harness, install Superpowers separately for each one.
|
||||
|
||||
## Migrating from the old symlink-based install
|
||||
|
||||
If you previously installed superpowers using `git clone` and symlinks, remove the old setup:
|
||||
@@ -50,10 +46,7 @@ use skill tool to load superpowers/brainstorming
|
||||
|
||||
## Updating
|
||||
|
||||
OpenCode installs Superpowers through a git-backed package spec. Some OpenCode
|
||||
and Bun versions pin that resolved git dependency in a lockfile or cache, so a
|
||||
restart may not pick up the newest Superpowers commit. If updates do not appear,
|
||||
clear OpenCode's package cache or reinstall the plugin.
|
||||
Superpowers updates automatically when you restart OpenCode.
|
||||
|
||||
To pin a specific version:
|
||||
|
||||
@@ -71,26 +64,6 @@ To pin a specific version:
|
||||
2. Verify the plugin line in your `opencode.json`
|
||||
3. Make sure you're running a recent version of OpenCode
|
||||
|
||||
### Windows install issues
|
||||
|
||||
Some Windows OpenCode builds have upstream installer issues with git-backed
|
||||
plugin specs, including cache paths for `git+https` URLs and Bun not finding
|
||||
`git.exe` even when it works in a normal terminal. If OpenCode cannot install
|
||||
the plugin, try installing with system npm and pointing OpenCode at the local
|
||||
package:
|
||||
|
||||
```powershell
|
||||
npm install superpowers@git+https://github.com/obra/superpowers.git --prefix "$HOME\.config\opencode"
|
||||
```
|
||||
|
||||
Then use the installed package path in `opencode.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugin": ["~/.config/opencode/node_modules/superpowers"]
|
||||
}
|
||||
```
|
||||
|
||||
### Skills not found
|
||||
|
||||
1. Use `skill` tool to list what's discovered
|
||||
|
||||
@@ -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" }
|
||||
],
|
||||
|
||||
164
README.md
164
README.md
@@ -2,10 +2,6 @@
|
||||
|
||||
Superpowers is a complete software development methodology for your coding agents, built on top of a set of composable skills and some initial instructions that make sure your agent uses them.
|
||||
|
||||
## Quickstart
|
||||
|
||||
Give your agent Superpowers: [Claude Code](#claude-code), [Codex CLI](#codex-cli), [Codex App](#codex-app), [Factory Droid](#factory-droid), [Gemini CLI](#gemini-cli), [OpenCode](#opencode), [Cursor](#cursor), [GitHub Copilot CLI](#github-copilot-cli).
|
||||
|
||||
## How it works
|
||||
|
||||
It starts from the moment you fire up your coding agent. As soon as it sees that you're building something, it *doesn't* just jump into trying to write code. Instead, it steps back and asks you what you're really trying to do.
|
||||
@@ -30,153 +26,95 @@ Thanks!
|
||||
|
||||
## Installation
|
||||
|
||||
Installation differs by harness. If you use more than one, install Superpowers separately for each one.
|
||||
**Note:** Installation differs by platform.
|
||||
|
||||
### Claude Code
|
||||
### Claude Code Official Marketplace
|
||||
|
||||
Superpowers is available via the [official Claude plugin marketplace](https://claude.com/plugins/superpowers)
|
||||
|
||||
#### Official Marketplace
|
||||
Install the plugin from Anthropic's official marketplace:
|
||||
|
||||
- Install the plugin from Anthropic's official marketplace:
|
||||
```bash
|
||||
/plugin install superpowers@claude-plugins-official
|
||||
```
|
||||
|
||||
```bash
|
||||
/plugin install superpowers@claude-plugins-official
|
||||
```
|
||||
|
||||
#### Superpowers Marketplace
|
||||
### Claude Code (Superpowers Marketplace)
|
||||
|
||||
The Superpowers marketplace provides Superpowers and some other related plugins for Claude Code.
|
||||
|
||||
- Register the marketplace:
|
||||
In Claude Code, register the marketplace first:
|
||||
|
||||
```bash
|
||||
/plugin marketplace add obra/superpowers-marketplace
|
||||
```
|
||||
```bash
|
||||
/plugin marketplace add obra/superpowers-marketplace
|
||||
```
|
||||
|
||||
- Install the plugin from this marketplace:
|
||||
Then install the plugin from this marketplace:
|
||||
|
||||
```bash
|
||||
/plugin install superpowers@superpowers-marketplace
|
||||
```
|
||||
```bash
|
||||
/plugin install superpowers@superpowers-marketplace
|
||||
```
|
||||
|
||||
### Codex CLI
|
||||
### OpenAI Codex CLI
|
||||
|
||||
Superpowers is available via the [official Codex plugin marketplace](https://github.com/openai/plugins).
|
||||
- Open plugin search interface
|
||||
|
||||
- Open the plugin search interface:
|
||||
```bash
|
||||
/plugins
|
||||
```
|
||||
|
||||
```bash
|
||||
/plugins
|
||||
```
|
||||
Search for Superpowers
|
||||
|
||||
- Search for Superpowers:
|
||||
```bash
|
||||
superpowers
|
||||
```
|
||||
|
||||
```bash
|
||||
superpowers
|
||||
```
|
||||
Select `Install Plugin`
|
||||
|
||||
- Select `Install Plugin`.
|
||||
|
||||
### Codex App
|
||||
|
||||
Superpowers is available via the [official Codex plugin marketplace](https://github.com/openai/plugins).
|
||||
### OpenAI Codex App
|
||||
|
||||
- In the Codex app, click on Plugins in the sidebar.
|
||||
- You should see `Superpowers` in the Coding section.
|
||||
- You should see `Superpowers` in the Coding section.
|
||||
- Click the `+` next to Superpowers and follow the prompts.
|
||||
|
||||
### Factory Droid
|
||||
|
||||
- Register the marketplace:
|
||||
### Cursor (via Plugin Marketplace)
|
||||
|
||||
```bash
|
||||
droid plugin marketplace add https://github.com/obra/superpowers
|
||||
```
|
||||
In Cursor Agent chat, install from marketplace:
|
||||
|
||||
- Install the plugin:
|
||||
```text
|
||||
/add-plugin superpowers
|
||||
```
|
||||
|
||||
```bash
|
||||
droid plugin install superpowers@superpowers
|
||||
```
|
||||
|
||||
### Gemini CLI
|
||||
|
||||
- Install the extension:
|
||||
|
||||
```bash
|
||||
gemini extensions install https://github.com/obra/superpowers
|
||||
```
|
||||
|
||||
- Update later:
|
||||
|
||||
```bash
|
||||
gemini extensions update superpowers
|
||||
```
|
||||
or search for "superpowers" in the plugin marketplace.
|
||||
|
||||
### OpenCode
|
||||
|
||||
OpenCode uses its own plugin install; install Superpowers separately even if you
|
||||
already use it in another harness.
|
||||
Tell OpenCode:
|
||||
|
||||
- Tell OpenCode:
|
||||
```
|
||||
Fetch and follow instructions from https://raw.githubusercontent.com/obra/superpowers/refs/heads/main/.opencode/INSTALL.md
|
||||
```
|
||||
|
||||
```
|
||||
Fetch and follow instructions from https://raw.githubusercontent.com/obra/superpowers/refs/heads/main/.opencode/INSTALL.md
|
||||
```
|
||||
|
||||
- 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:
|
||||
|
||||
```text
|
||||
/add-plugin superpowers
|
||||
```
|
||||
|
||||
- Or search for "superpowers" in the plugin marketplace.
|
||||
**Detailed docs:** [docs/README.opencode.md](docs/README.opencode.md)
|
||||
|
||||
### GitHub Copilot CLI
|
||||
|
||||
- Register the marketplace:
|
||||
```bash
|
||||
copilot plugin marketplace add obra/superpowers-marketplace
|
||||
copilot plugin install superpowers@superpowers-marketplace
|
||||
```
|
||||
|
||||
```bash
|
||||
copilot plugin marketplace add obra/superpowers-marketplace
|
||||
```
|
||||
### Gemini CLI
|
||||
|
||||
- Install the plugin:
|
||||
```bash
|
||||
gemini extensions install https://github.com/obra/superpowers
|
||||
```
|
||||
|
||||
```bash
|
||||
copilot plugin install superpowers@superpowers-marketplace
|
||||
```
|
||||
To update:
|
||||
|
||||
```bash
|
||||
gemini extensions update superpowers
|
||||
```
|
||||
|
||||
## The Basic Workflow
|
||||
|
||||
|
||||
@@ -12,14 +12,10 @@ Add superpowers to the `plugin` array in your `opencode.json` (global or project
|
||||
}
|
||||
```
|
||||
|
||||
Restart OpenCode. The plugin installs through OpenCode's plugin manager and
|
||||
registers all skills.
|
||||
Restart OpenCode. The plugin auto-installs via Bun and registers all skills automatically.
|
||||
|
||||
Verify by asking: "Tell me about your superpowers"
|
||||
|
||||
OpenCode uses its own plugin install. If you also use Claude Code, Codex, or
|
||||
another harness, install Superpowers separately for each one.
|
||||
|
||||
### Migrating from the old symlink-based install
|
||||
|
||||
If you previously installed superpowers using `git clone` and symlinks, remove the old setup:
|
||||
@@ -82,10 +78,7 @@ Create project-specific skills in `.opencode/skills/` within your project.
|
||||
|
||||
## Updating
|
||||
|
||||
OpenCode installs Superpowers through a git-backed package spec. Some OpenCode
|
||||
and Bun versions pin that resolved git dependency in a lockfile or cache, so a
|
||||
restart may not pick up the newest Superpowers commit. If updates do not appear,
|
||||
clear OpenCode's package cache or reinstall the plugin.
|
||||
Superpowers updates automatically when you restart OpenCode. The plugin is re-installed from the git repository on each launch.
|
||||
|
||||
To pin a specific version, use a branch or tag:
|
||||
|
||||
@@ -119,26 +112,6 @@ Skills written for Claude Code are automatically adapted for OpenCode:
|
||||
2. Verify the plugin line in your `opencode.json` is correct
|
||||
3. Make sure you're running a recent version of OpenCode
|
||||
|
||||
### Windows install issues
|
||||
|
||||
Some Windows OpenCode builds have upstream installer issues with git-backed
|
||||
plugin specs, including cache paths for `git+https` URLs and Bun not finding
|
||||
`git.exe` even when it works in a normal terminal. If OpenCode cannot install
|
||||
the plugin, try installing with system npm and pointing OpenCode at the local
|
||||
package:
|
||||
|
||||
```powershell
|
||||
npm install superpowers@git+https://github.com/obra/superpowers.git --prefix "$HOME\.config\opencode"
|
||||
```
|
||||
|
||||
Then use the installed package path in `opencode.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugin": ["~/.config/opencode/node_modules/superpowers"]
|
||||
}
|
||||
```
|
||||
|
||||
### Skills not found
|
||||
|
||||
1. Use OpenCode's `skill` tool to list available skills
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"hooks": {
|
||||
"sessionStart": [
|
||||
{
|
||||
"command": "./hooks/run-hook.cmd session-start"
|
||||
"command": "./hooks/session-start"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
#
|
||||
# Sync this superpowers checkout → prime-radiant-inc/openai-codex-plugins.
|
||||
# Clones the fork fresh into a temp dir, rsyncs tracked upstream plugin content
|
||||
# (including committed Codex files under .codex-plugin/ and assets/), preserves
|
||||
# OpenAI-owned marketplace metadata already in the destination plugin, commits,
|
||||
# (including committed Codex files under .codex-plugin/ and assets/), commits,
|
||||
# pushes a sync branch, and opens a PR.
|
||||
# Path/user agnostic — auto-detects upstream from script location.
|
||||
#
|
||||
@@ -52,7 +51,6 @@ EXCLUDES=(
|
||||
"/.gitattributes"
|
||||
"/.github/"
|
||||
"/.gitignore"
|
||||
"/.openclaw/"
|
||||
"/.opencode/"
|
||||
"/.version-bump.json"
|
||||
"/.worktrees/"
|
||||
@@ -65,7 +63,6 @@ EXCLUDES=(
|
||||
"/GEMINI.md"
|
||||
"/RELEASE-NOTES.md"
|
||||
"/gemini-extension.json"
|
||||
"/openclaw.plugin.json"
|
||||
"/package.json"
|
||||
|
||||
# Directories not shipped by canonical Codex plugins
|
||||
@@ -226,7 +223,6 @@ fi
|
||||
DEST="$DEST_REPO/$DEST_REL"
|
||||
PREVIEW_REPO="$DEST_REPO"
|
||||
PREVIEW_DEST="$DEST"
|
||||
SYNC_SOURCE=""
|
||||
|
||||
overlay_destination_paths() {
|
||||
local repo="$1"
|
||||
@@ -295,7 +291,7 @@ apply_to_preview_checkout() {
|
||||
mkdir -p "$PREVIEW_DEST"
|
||||
fi
|
||||
|
||||
rsync "${RSYNC_ARGS[@]}" "$SYNC_SOURCE/" "$PREVIEW_DEST/"
|
||||
rsync "${RSYNC_ARGS[@]}" "$UPSTREAM/" "$PREVIEW_DEST/"
|
||||
}
|
||||
|
||||
preview_checkout_has_changes() {
|
||||
@@ -320,36 +316,6 @@ for pat in "${EXCLUDES[@]}"; do RSYNC_ARGS+=(--exclude="$pat"); done
|
||||
append_git_ignored_directory_excludes
|
||||
append_git_ignored_file_excludes
|
||||
|
||||
copy_preserved_destination_metadata() {
|
||||
local destination="$1"
|
||||
local source="$2"
|
||||
local path
|
||||
local rel
|
||||
|
||||
[[ -d "$destination/skills" ]] || return 0
|
||||
|
||||
while IFS= read -r -d '' path; do
|
||||
rel="${path#"$destination"/}"
|
||||
mkdir -p "$source/$(dirname "$rel")"
|
||||
cp -p "$path" "$source/$rel"
|
||||
done < <(find "$destination/skills" -path '*/agents/openai.yaml' -type f -print0)
|
||||
}
|
||||
|
||||
prepare_sync_source() {
|
||||
local destination="$1"
|
||||
|
||||
[[ -n "$CLEANUP_DIR" ]] || CLEANUP_DIR="$(mktemp -d)"
|
||||
|
||||
SYNC_SOURCE="$CLEANUP_DIR/source-overlay"
|
||||
rm -rf "$SYNC_SOURCE"
|
||||
mkdir -p "$SYNC_SOURCE"
|
||||
|
||||
rsync "${RSYNC_ARGS[@]}" "$UPSTREAM/" "$SYNC_SOURCE/" >/dev/null
|
||||
copy_preserved_destination_metadata "$destination" "$SYNC_SOURCE"
|
||||
}
|
||||
|
||||
prepare_sync_source "$PREVIEW_DEST"
|
||||
|
||||
# =============================================================================
|
||||
# Dry run preview (always shown)
|
||||
# =============================================================================
|
||||
@@ -365,7 +331,7 @@ if [[ $BOOTSTRAP -eq 1 ]]; then
|
||||
fi
|
||||
echo ""
|
||||
echo "=== Preview (rsync --dry-run) ==="
|
||||
rsync "${RSYNC_ARGS[@]}" --dry-run --itemize-changes "$SYNC_SOURCE/" "$PREVIEW_DEST/"
|
||||
rsync "${RSYNC_ARGS[@]}" --dry-run --itemize-changes "$UPSTREAM/" "$PREVIEW_DEST/"
|
||||
echo "=== End preview ==="
|
||||
echo ""
|
||||
|
||||
@@ -402,7 +368,7 @@ echo "Syncing upstream content..."
|
||||
if [[ $BOOTSTRAP -eq 1 ]]; then
|
||||
mkdir -p "$DEST"
|
||||
fi
|
||||
rsync "${RSYNC_ARGS[@]}" "$SYNC_SOURCE/" "$DEST/"
|
||||
rsync "${RSYNC_ARGS[@]}" "$UPSTREAM/" "$DEST/"
|
||||
|
||||
# Bail early if nothing actually changed
|
||||
cd "$DEST_REPO"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -73,19 +73,6 @@ assert_matches() {
|
||||
fi
|
||||
}
|
||||
|
||||
assert_not_matches() {
|
||||
local haystack="$1"
|
||||
local pattern="$2"
|
||||
local description="$3"
|
||||
|
||||
if printf '%s' "$haystack" | grep -Eq -- "$pattern"; then
|
||||
fail "$description"
|
||||
echo " did not expect to match: $pattern"
|
||||
else
|
||||
pass "$description"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_path_absent() {
|
||||
local path="$1"
|
||||
local description="$2"
|
||||
@@ -257,22 +244,6 @@ EOF
|
||||
commit_fixture "$repo" "Initial destination fixture"
|
||||
}
|
||||
|
||||
add_openai_agent_metadata_fixture() {
|
||||
local repo="$1"
|
||||
|
||||
mkdir -p "$repo/plugins/superpowers/skills/example/agents"
|
||||
|
||||
cat > "$repo/plugins/superpowers/skills/example/agents/openai.yaml" <<'EOF'
|
||||
interface:
|
||||
display_name: "Example"
|
||||
short_description: "Destination-owned OpenAI metadata"
|
||||
EOF
|
||||
|
||||
git -C "$repo" add plugins/superpowers/skills/example/agents/openai.yaml
|
||||
|
||||
commit_fixture "$repo" "Add OpenAI agent metadata fixture"
|
||||
}
|
||||
|
||||
dirty_tracked_destination_skill() {
|
||||
local repo="$1"
|
||||
|
||||
@@ -290,7 +261,6 @@ write_synced_destination_fixture() {
|
||||
"$repo/plugins/superpowers/.codex-plugin" \
|
||||
"$repo/plugins/superpowers/.private-journal" \
|
||||
"$repo/plugins/superpowers/assets" \
|
||||
"$repo/plugins/superpowers/skills/example/agents" \
|
||||
"$repo/plugins/superpowers/skills/example"
|
||||
|
||||
cat > "$repo/plugins/superpowers/.codex-plugin/plugin.json" <<EOF
|
||||
@@ -312,19 +282,12 @@ EOF
|
||||
Fixture content.
|
||||
EOF
|
||||
|
||||
cat > "$repo/plugins/superpowers/skills/example/agents/openai.yaml" <<'EOF'
|
||||
interface:
|
||||
display_name: "Example"
|
||||
short_description: "Destination-owned OpenAI metadata"
|
||||
EOF
|
||||
|
||||
printf 'tracked keep\n' > "$repo/plugins/superpowers/.private-journal/keep.txt"
|
||||
|
||||
git -C "$repo" add \
|
||||
plugins/superpowers/.codex-plugin/plugin.json \
|
||||
plugins/superpowers/assets/app-icon.png \
|
||||
plugins/superpowers/assets/superpowers-small.svg \
|
||||
plugins/superpowers/skills/example/agents/openai.yaml \
|
||||
plugins/superpowers/skills/example/SKILL.md \
|
||||
plugins/superpowers/.private-journal/keep.txt
|
||||
|
||||
@@ -452,7 +415,6 @@ main() {
|
||||
local help_output
|
||||
local script_source
|
||||
local dirty_skill_path
|
||||
local noop_openai_metadata_path
|
||||
|
||||
echo "=== Test: sync-to-codex-plugin dry-run regression ==="
|
||||
|
||||
@@ -481,7 +443,6 @@ main() {
|
||||
|
||||
init_repo "$dest"
|
||||
write_destination_fixture "$dest"
|
||||
add_openai_agent_metadata_fixture "$dest"
|
||||
checkout_fixture_branch "$dest" "$dest_branch"
|
||||
dirty_tracked_destination_skill "$dest"
|
||||
|
||||
@@ -529,7 +490,6 @@ main() {
|
||||
preview_section="$(printf '%s\n' "$preview_output" | sed -n '/^=== Preview (rsync --dry-run) ===$/,/^=== End preview ===$/p')"
|
||||
stale_preview_section="$(printf '%s\n' "$stale_preview_output" | sed -n '/^=== Preview (rsync --dry-run) ===$/,/^=== End preview ===$/p')"
|
||||
dirty_skill_path="$dirty_apply_dest/plugins/superpowers/skills/example/SKILL.md"
|
||||
noop_openai_metadata_path="$noop_apply_dest/plugins/superpowers/skills/example/agents/openai.yaml"
|
||||
|
||||
echo ""
|
||||
echo "Preview assertions..."
|
||||
@@ -545,7 +505,6 @@ main() {
|
||||
assert_not_contains "$preview_output" "Overlay file (.codex-plugin/plugin.json) will be regenerated" "Preview omits overlay regeneration note"
|
||||
assert_not_contains "$preview_output" "Assets (superpowers-small.svg, app-icon.png) will be seeded from" "Preview omits assets seeding note"
|
||||
assert_contains "$preview_section" "skills/example/SKILL.md" "Preview reflects dirty tracked destination file"
|
||||
assert_not_matches "$preview_section" "\\*deleting +skills/example/agents/openai\\.yaml" "Preview preserves destination-owned OpenAI agent metadata"
|
||||
assert_current_branch "$dest" "$dest_branch" "Preview leaves destination checkout on its original branch"
|
||||
assert_branch_absent "$dest" "sync/superpowers-*" "Preview does not create sync branch in destination checkout"
|
||||
|
||||
@@ -583,9 +542,6 @@ Locally modified fixture content." "Dirty local apply preserves tracked working-
|
||||
assert_contains "$noop_apply_output" "No changes — embedded plugin was already in sync with upstream" "Clean no-op local apply reports no changes"
|
||||
assert_current_branch "$noop_apply_dest" "$noop_apply_dest_branch" "Clean no-op local apply leaves destination checkout on its original branch"
|
||||
assert_branch_absent "$noop_apply_dest" "sync/superpowers-*" "Clean no-op local apply does not create sync branch in destination checkout"
|
||||
assert_file_equals "$noop_openai_metadata_path" "interface:
|
||||
display_name: \"Example\"
|
||||
short_description: \"Destination-owned OpenAI metadata\"" "Clean no-op local apply preserves OpenAI agent metadata"
|
||||
|
||||
echo ""
|
||||
echo "Missing manifest assertions..."
|
||||
|
||||
@@ -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 ==="
|
||||
Reference in New Issue
Block a user