mirror of
https://github.com/certd/certd.git
synced 2026-04-24 12:27:25 +08:00
perf: 阿里云dcdn支持根据证书域名匹配模式
This commit is contained in:
@@ -0,0 +1,115 @@
|
|||||||
|
---
|
||||||
|
name: using-superpowers
|
||||||
|
description: Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions
|
||||||
|
---
|
||||||
|
|
||||||
|
<SUBAGENT-STOP>
|
||||||
|
If you were dispatched as a subagent to execute a specific task, skip this skill.
|
||||||
|
</SUBAGENT-STOP>
|
||||||
|
|
||||||
|
<EXTREMELY-IMPORTANT>
|
||||||
|
If you think there is even a 1% chance a skill might apply to what you are doing, you ABSOLUTELY MUST invoke the skill.
|
||||||
|
|
||||||
|
IF A SKILL APPLIES TO YOUR TASK, YOU DO NOT HAVE A CHOICE. YOU MUST USE IT.
|
||||||
|
|
||||||
|
This is not negotiable. This is not optional. You cannot rationalize your way out of this.
|
||||||
|
</EXTREMELY-IMPORTANT>
|
||||||
|
|
||||||
|
## Instruction Priority
|
||||||
|
|
||||||
|
Superpowers skills override default system prompt behavior, but **user instructions always take precedence**:
|
||||||
|
|
||||||
|
1. **User's explicit instructions** (CLAUDE.md, GEMINI.md, AGENTS.md, direct requests) — highest priority
|
||||||
|
2. **Superpowers skills** — override default system behavior where they conflict
|
||||||
|
3. **Default system prompt** — lowest priority
|
||||||
|
|
||||||
|
If CLAUDE.md, GEMINI.md, or AGENTS.md says "don't use TDD" and a skill says "always use TDD," follow the user's instructions. The user is in control.
|
||||||
|
|
||||||
|
## How to Access Skills
|
||||||
|
|
||||||
|
**In Claude Code:** Use the `Skill` tool. When you invoke a skill, its content is loaded and presented to you—follow it directly. Never use the Read tool on skill files.
|
||||||
|
|
||||||
|
**In Gemini CLI:** Skills activate via the `activate_skill` tool. Gemini loads skill metadata at session start and activates the full content on demand.
|
||||||
|
|
||||||
|
**In other environments:** Check your platform's documentation for how skills are loaded.
|
||||||
|
|
||||||
|
## Platform Adaptation
|
||||||
|
|
||||||
|
Skills use Claude Code tool names. Non-CC platforms: see `references/codex-tools.md` (Codex) for tool equivalents. Gemini CLI users get the tool mapping loaded automatically via GEMINI.md.
|
||||||
|
|
||||||
|
# Using Skills
|
||||||
|
|
||||||
|
## The Rule
|
||||||
|
|
||||||
|
**Invoke relevant or requested skills BEFORE any response or action.** Even a 1% chance a skill might apply means that you should invoke the skill to check. If an invoked skill turns out to be wrong for the situation, you don't need to use it.
|
||||||
|
|
||||||
|
```dot
|
||||||
|
digraph skill_flow {
|
||||||
|
"User message received" [shape=doublecircle];
|
||||||
|
"About to EnterPlanMode?" [shape=doublecircle];
|
||||||
|
"Already brainstormed?" [shape=diamond];
|
||||||
|
"Invoke brainstorming skill" [shape=box];
|
||||||
|
"Might any skill apply?" [shape=diamond];
|
||||||
|
"Invoke Skill tool" [shape=box];
|
||||||
|
"Announce: 'Using [skill] to [purpose]'" [shape=box];
|
||||||
|
"Has checklist?" [shape=diamond];
|
||||||
|
"Create TodoWrite todo per item" [shape=box];
|
||||||
|
"Follow skill exactly" [shape=box];
|
||||||
|
"Respond (including clarifications)" [shape=doublecircle];
|
||||||
|
|
||||||
|
"About to EnterPlanMode?" -> "Already brainstormed?";
|
||||||
|
"Already brainstormed?" -> "Invoke brainstorming skill" [label="no"];
|
||||||
|
"Already brainstormed?" -> "Might any skill apply?" [label="yes"];
|
||||||
|
"Invoke brainstorming skill" -> "Might any skill apply?";
|
||||||
|
|
||||||
|
"User message received" -> "Might any skill apply?";
|
||||||
|
"Might any skill apply?" -> "Invoke Skill tool" [label="yes, even 1%"];
|
||||||
|
"Might any skill apply?" -> "Respond (including clarifications)" [label="definitely not"];
|
||||||
|
"Invoke Skill tool" -> "Announce: 'Using [skill] to [purpose]'";
|
||||||
|
"Announce: 'Using [skill] to [purpose]'" -> "Has checklist?";
|
||||||
|
"Has checklist?" -> "Create TodoWrite todo per item" [label="yes"];
|
||||||
|
"Has checklist?" -> "Follow skill exactly" [label="no"];
|
||||||
|
"Create TodoWrite todo per item" -> "Follow skill exactly";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Red Flags
|
||||||
|
|
||||||
|
These thoughts mean STOP—you're rationalizing:
|
||||||
|
|
||||||
|
| Thought | Reality |
|
||||||
|
|---------|---------|
|
||||||
|
| "This is just a simple question" | Questions are tasks. Check for skills. |
|
||||||
|
| "I need more context first" | Skill check comes BEFORE clarifying questions. |
|
||||||
|
| "Let me explore the codebase first" | Skills tell you HOW to explore. Check first. |
|
||||||
|
| "I can check git/files quickly" | Files lack conversation context. Check for skills. |
|
||||||
|
| "Let me gather information first" | Skills tell you HOW to gather information. |
|
||||||
|
| "This doesn't need a formal skill" | If a skill exists, use it. |
|
||||||
|
| "I remember this skill" | Skills evolve. Read current version. |
|
||||||
|
| "This doesn't count as a task" | Action = task. Check for skills. |
|
||||||
|
| "The skill is overkill" | Simple things become complex. Use it. |
|
||||||
|
| "I'll just do this one thing first" | Check BEFORE doing anything. |
|
||||||
|
| "This feels productive" | Undisciplined action wastes time. Skills prevent this. |
|
||||||
|
| "I know what that means" | Knowing the concept ≠ using the skill. Invoke it. |
|
||||||
|
|
||||||
|
## Skill Priority
|
||||||
|
|
||||||
|
When multiple skills could apply, use this order:
|
||||||
|
|
||||||
|
1. **Process skills first** (brainstorming, debugging) - these determine HOW to approach the task
|
||||||
|
2. **Implementation skills second** (frontend-design, mcp-builder) - these guide execution
|
||||||
|
|
||||||
|
"Let's build X" → brainstorming first, then implementation skills.
|
||||||
|
"Fix this bug" → debugging first, then domain-specific skills.
|
||||||
|
|
||||||
|
## Skill Types
|
||||||
|
|
||||||
|
**Rigid** (TDD, debugging): Follow exactly. Don't adapt away discipline.
|
||||||
|
|
||||||
|
**Flexible** (patterns): Adapt principles to context.
|
||||||
|
|
||||||
|
The skill itself tells you which.
|
||||||
|
|
||||||
|
## User Instructions
|
||||||
|
|
||||||
|
Instructions say WHAT, not HOW. "Add X" or "Fix Y" doesn't mean skip workflows.
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
# Codex Tool Mapping
|
||||||
|
|
||||||
|
Skills use Claude Code tool names. When you encounter these in a skill, use your platform equivalent:
|
||||||
|
|
||||||
|
| Skill references | Codex equivalent |
|
||||||
|
|-----------------|------------------|
|
||||||
|
| `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` |
|
||||||
|
| 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 |
|
||||||
|
| `Read`, `Write`, `Edit` (files) | Use your native file tools |
|
||||||
|
| `Bash` (run commands) | Use your native shell tools |
|
||||||
|
|
||||||
|
## Subagent dispatch requires multi-agent support
|
||||||
|
|
||||||
|
Add to your Codex config (`~/.codex/config.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[features]
|
||||||
|
multi_agent = true
|
||||||
|
```
|
||||||
|
|
||||||
|
This enables `spawn_agent`, `wait`, and `close_agent` for skills like `dispatching-parallel-agents` and `subagent-driven-development`.
|
||||||
|
|
||||||
|
## Named agent dispatch
|
||||||
|
|
||||||
|
Claude Code skills reference named agent types like `superpowers:code-reviewer`.
|
||||||
|
Codex does not have a named agent registry — `spawn_agent` creates generic agents
|
||||||
|
from built-in roles (`default`, `explorer`, `worker`).
|
||||||
|
|
||||||
|
When a skill says to dispatch a named agent type:
|
||||||
|
|
||||||
|
1. Find the agent's prompt file (e.g., `agents/code-reviewer.md` or the skill's
|
||||||
|
local prompt template like `code-quality-reviewer-prompt.md`)
|
||||||
|
2. Read the prompt content
|
||||||
|
3. Fill any template placeholders (`{BASE_SHA}`, `{WHAT_WAS_IMPLEMENTED}`, etc.)
|
||||||
|
4. Spawn a `worker` agent with the filled content as the `message`
|
||||||
|
|
||||||
|
| Skill instruction | Codex equivalent |
|
||||||
|
|-------------------|------------------|
|
||||||
|
| `Task tool (superpowers:code-reviewer)` | `spawn_agent(agent_type="worker", message=...)` with `code-reviewer.md` content |
|
||||||
|
| `Task tool (general-purpose)` with inline prompt | `spawn_agent(message=...)` with the same prompt |
|
||||||
|
|
||||||
|
### Message framing
|
||||||
|
|
||||||
|
The `message` parameter is user-level input, not a system prompt. Structure it
|
||||||
|
for maximum instruction adherence:
|
||||||
|
|
||||||
|
```
|
||||||
|
Your task is to perform the following. Follow the instructions below exactly.
|
||||||
|
|
||||||
|
<agent-instructions>
|
||||||
|
[filled prompt content from the agent's .md file]
|
||||||
|
</agent-instructions>
|
||||||
|
|
||||||
|
Execute this now. Output ONLY the structured response following the format
|
||||||
|
specified in the instructions above.
|
||||||
|
```
|
||||||
|
|
||||||
|
- Use task-delegation framing ("Your task is...") rather than persona framing ("You are...")
|
||||||
|
- Wrap instructions in XML tags — the model treats tagged blocks as authoritative
|
||||||
|
- End with an explicit execution directive to prevent summarization of the instructions
|
||||||
|
|
||||||
|
### When this workaround can be removed
|
||||||
|
|
||||||
|
This approach compensates for Codex's plugin system not yet supporting an `agents`
|
||||||
|
field in `plugin.json`. When `RawPluginManifest` gains an `agents` field, the
|
||||||
|
plugin can symlink to `agents/` (mirroring the existing `skills/` symlink) and
|
||||||
|
skills can dispatch named agent types directly.
|
||||||
|
|
||||||
|
## Environment Detection
|
||||||
|
|
||||||
|
Skills that create worktrees or finish branches should detect their
|
||||||
|
environment with read-only git commands before proceeding:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
|
||||||
|
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
|
||||||
|
BRANCH=$(git branch --show-current)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `GIT_DIR != GIT_COMMON` → already in a linked worktree (skip creation)
|
||||||
|
- `BRANCH` empty → detached HEAD (cannot branch/push/PR from sandbox)
|
||||||
|
|
||||||
|
See `using-git-worktrees` Step 0 and `finishing-a-development-branch`
|
||||||
|
Step 1 for how each skill uses these signals.
|
||||||
|
|
||||||
|
## Codex App Finishing
|
||||||
|
|
||||||
|
When the sandbox blocks branch/push operations (detached HEAD in an
|
||||||
|
externally managed worktree), the agent commits all work and informs
|
||||||
|
the user to use the App's native controls:
|
||||||
|
|
||||||
|
- **"Create branch"** — names the branch, then commit/push/PR via App UI
|
||||||
|
- **"Hand off to local"** — transfers work to the user's local checkout
|
||||||
|
|
||||||
|
The agent can still run tests, stage files, and output suggested branch
|
||||||
|
names, commit messages, and PR descriptions for the user to copy.
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Gemini CLI Tool Mapping
|
||||||
|
|
||||||
|
Skills use Claude Code tool names. When you encounter these in a skill, use your platform equivalent:
|
||||||
|
|
||||||
|
| Skill references | Gemini CLI equivalent |
|
||||||
|
|-----------------|----------------------|
|
||||||
|
| `Read` (file reading) | `read_file` |
|
||||||
|
| `Write` (file creation) | `write_file` |
|
||||||
|
| `Edit` (file editing) | `replace` |
|
||||||
|
| `Bash` (run commands) | `run_shell_command` |
|
||||||
|
| `Grep` (search file content) | `grep_search` |
|
||||||
|
| `Glob` (search files by name) | `glob` |
|
||||||
|
| `TodoWrite` (task tracking) | `write_todos` |
|
||||||
|
| `Skill` tool (invoke a skill) | `activate_skill` |
|
||||||
|
| `WebSearch` | `google_web_search` |
|
||||||
|
| `WebFetch` | `web_fetch` |
|
||||||
|
| `Task` tool (dispatch subagent) | No equivalent — Gemini CLI does not support subagents |
|
||||||
|
|
||||||
|
## No subagent support
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
These tools are available in Gemini CLI but have no Claude Code equivalent:
|
||||||
|
|
||||||
|
| Tool | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `list_directory` | List files and subdirectories |
|
||||||
|
| `save_memory` | Persist facts to GEMINI.md across sessions |
|
||||||
|
| `ask_user` | Request structured input from the user |
|
||||||
|
| `tracker_create_task` | Rich task management (create, update, list, visualize) |
|
||||||
|
| `enter_plan_mode` / `exit_plan_mode` | Switch to read-only research mode before making changes |
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
---
|
||||||
|
name: using-superpowers
|
||||||
|
description: Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions
|
||||||
|
---
|
||||||
|
|
||||||
|
<SUBAGENT-STOP>
|
||||||
|
If you were dispatched as a subagent to execute a specific task, skip this skill.
|
||||||
|
</SUBAGENT-STOP>
|
||||||
|
|
||||||
|
<EXTREMELY-IMPORTANT>
|
||||||
|
If you think there is even a 1% chance a skill might apply to what you are doing, you ABSOLUTELY MUST invoke the skill.
|
||||||
|
|
||||||
|
IF A SKILL APPLIES TO YOUR TASK, YOU DO NOT HAVE A CHOICE. YOU MUST USE IT.
|
||||||
|
|
||||||
|
This is not negotiable. This is not optional. You cannot rationalize your way out of this.
|
||||||
|
</EXTREMELY-IMPORTANT>
|
||||||
|
|
||||||
|
## Instruction Priority
|
||||||
|
|
||||||
|
Superpowers skills override default system prompt behavior, but **user instructions always take precedence**:
|
||||||
|
|
||||||
|
1. **User's explicit instructions** (CLAUDE.md, GEMINI.md, AGENTS.md, direct requests) — highest priority
|
||||||
|
2. **Superpowers skills** — override default system behavior where they conflict
|
||||||
|
3. **Default system prompt** — lowest priority
|
||||||
|
|
||||||
|
If CLAUDE.md, GEMINI.md, or AGENTS.md says "don't use TDD" and a skill says "always use TDD," follow the user's instructions. The user is in control.
|
||||||
|
|
||||||
|
## How to Access Skills
|
||||||
|
|
||||||
|
**In Claude Code:** Use the `Skill` tool. When you invoke a skill, its content is loaded and presented to you—follow it directly. Never use the Read tool on skill files.
|
||||||
|
|
||||||
|
**In Gemini CLI:** Skills activate via the `activate_skill` tool. Gemini loads skill metadata at session start and activates the full content on demand.
|
||||||
|
|
||||||
|
**In other environments:** Check your platform's documentation for how skills are loaded.
|
||||||
|
|
||||||
|
## Platform Adaptation
|
||||||
|
|
||||||
|
Skills use Claude Code tool names. Non-CC platforms: see `references/codex-tools.md` (Codex) for tool equivalents. Gemini CLI users get the tool mapping loaded automatically via GEMINI.md.
|
||||||
|
|
||||||
|
# Using Skills
|
||||||
|
|
||||||
|
## The Rule
|
||||||
|
|
||||||
|
**Invoke relevant or requested skills BEFORE any response or action.** Even a 1% chance a skill might apply means that you should invoke the skill to check. If an invoked skill turns out to be wrong for the situation, you don't need to use it.
|
||||||
|
|
||||||
|
```dot
|
||||||
|
digraph skill_flow {
|
||||||
|
"User message received" [shape=doublecircle];
|
||||||
|
"About to EnterPlanMode?" [shape=doublecircle];
|
||||||
|
"Already brainstormed?" [shape=diamond];
|
||||||
|
"Invoke brainstorming skill" [shape=box];
|
||||||
|
"Might any skill apply?" [shape=diamond];
|
||||||
|
"Invoke Skill tool" [shape=box];
|
||||||
|
"Announce: 'Using [skill] to [purpose]'" [shape=box];
|
||||||
|
"Has checklist?" [shape=diamond];
|
||||||
|
"Create TodoWrite todo per item" [shape=box];
|
||||||
|
"Follow skill exactly" [shape=box];
|
||||||
|
"Respond (including clarifications)" [shape=doublecircle];
|
||||||
|
|
||||||
|
"About to EnterPlanMode?" -> "Already brainstormed?";
|
||||||
|
"Already brainstormed?" -> "Invoke brainstorming skill" [label="no"];
|
||||||
|
"Already brainstormed?" -> "Might any skill apply?" [label="yes"];
|
||||||
|
"Invoke brainstorming skill" -> "Might any skill apply?";
|
||||||
|
|
||||||
|
"User message received" -> "Might any skill apply?";
|
||||||
|
"Might any skill apply?" -> "Invoke Skill tool" [label="yes, even 1%"];
|
||||||
|
"Might any skill apply?" -> "Respond (including clarifications)" [label="definitely not"];
|
||||||
|
"Invoke Skill tool" -> "Announce: 'Using [skill] to [purpose]'";
|
||||||
|
"Announce: 'Using [skill] to [purpose]'" -> "Has checklist?";
|
||||||
|
"Has checklist?" -> "Create TodoWrite todo per item" [label="yes"];
|
||||||
|
"Has checklist?" -> "Follow skill exactly" [label="no"];
|
||||||
|
"Create TodoWrite todo per item" -> "Follow skill exactly";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Red Flags
|
||||||
|
|
||||||
|
These thoughts mean STOP—you're rationalizing:
|
||||||
|
|
||||||
|
| Thought | Reality |
|
||||||
|
|---------|---------|
|
||||||
|
| "This is just a simple question" | Questions are tasks. Check for skills. |
|
||||||
|
| "I need more context first" | Skill check comes BEFORE clarifying questions. |
|
||||||
|
| "Let me explore the codebase first" | Skills tell you HOW to explore. Check first. |
|
||||||
|
| "I can check git/files quickly" | Files lack conversation context. Check for skills. |
|
||||||
|
| "Let me gather information first" | Skills tell you HOW to gather information. |
|
||||||
|
| "This doesn't need a formal skill" | If a skill exists, use it. |
|
||||||
|
| "I remember this skill" | Skills evolve. Read current version. |
|
||||||
|
| "This doesn't count as a task" | Action = task. Check for skills. |
|
||||||
|
| "The skill is overkill" | Simple things become complex. Use it. |
|
||||||
|
| "I'll just do this one thing first" | Check BEFORE doing anything. |
|
||||||
|
| "This feels productive" | Undisciplined action wastes time. Skills prevent this. |
|
||||||
|
| "I know what that means" | Knowing the concept ≠ using the skill. Invoke it. |
|
||||||
|
|
||||||
|
## Skill Priority
|
||||||
|
|
||||||
|
When multiple skills could apply, use this order:
|
||||||
|
|
||||||
|
1. **Process skills first** (brainstorming, debugging) - these determine HOW to approach the task
|
||||||
|
2. **Implementation skills second** (frontend-design, mcp-builder) - these guide execution
|
||||||
|
|
||||||
|
"Let's build X" → brainstorming first, then implementation skills.
|
||||||
|
"Fix this bug" → debugging first, then domain-specific skills.
|
||||||
|
|
||||||
|
## Skill Types
|
||||||
|
|
||||||
|
**Rigid** (TDD, debugging): Follow exactly. Don't adapt away discipline.
|
||||||
|
|
||||||
|
**Flexible** (patterns): Adapt principles to context.
|
||||||
|
|
||||||
|
The skill itself tells you which.
|
||||||
|
|
||||||
|
## User Instructions
|
||||||
|
|
||||||
|
Instructions say WHAT, not HOW. "Add X" or "Fix Y" doesn't mean skip workflows.
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
# Codex Tool Mapping
|
||||||
|
|
||||||
|
Skills use Claude Code tool names. When you encounter these in a skill, use your platform equivalent:
|
||||||
|
|
||||||
|
| Skill references | Codex equivalent |
|
||||||
|
|-----------------|------------------|
|
||||||
|
| `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` |
|
||||||
|
| 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 |
|
||||||
|
| `Read`, `Write`, `Edit` (files) | Use your native file tools |
|
||||||
|
| `Bash` (run commands) | Use your native shell tools |
|
||||||
|
|
||||||
|
## Subagent dispatch requires multi-agent support
|
||||||
|
|
||||||
|
Add to your Codex config (`~/.codex/config.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[features]
|
||||||
|
multi_agent = true
|
||||||
|
```
|
||||||
|
|
||||||
|
This enables `spawn_agent`, `wait`, and `close_agent` for skills like `dispatching-parallel-agents` and `subagent-driven-development`.
|
||||||
|
|
||||||
|
## Named agent dispatch
|
||||||
|
|
||||||
|
Claude Code skills reference named agent types like `superpowers:code-reviewer`.
|
||||||
|
Codex does not have a named agent registry — `spawn_agent` creates generic agents
|
||||||
|
from built-in roles (`default`, `explorer`, `worker`).
|
||||||
|
|
||||||
|
When a skill says to dispatch a named agent type:
|
||||||
|
|
||||||
|
1. Find the agent's prompt file (e.g., `agents/code-reviewer.md` or the skill's
|
||||||
|
local prompt template like `code-quality-reviewer-prompt.md`)
|
||||||
|
2. Read the prompt content
|
||||||
|
3. Fill any template placeholders (`{BASE_SHA}`, `{WHAT_WAS_IMPLEMENTED}`, etc.)
|
||||||
|
4. Spawn a `worker` agent with the filled content as the `message`
|
||||||
|
|
||||||
|
| Skill instruction | Codex equivalent |
|
||||||
|
|-------------------|------------------|
|
||||||
|
| `Task tool (superpowers:code-reviewer)` | `spawn_agent(agent_type="worker", message=...)` with `code-reviewer.md` content |
|
||||||
|
| `Task tool (general-purpose)` with inline prompt | `spawn_agent(message=...)` with the same prompt |
|
||||||
|
|
||||||
|
### Message framing
|
||||||
|
|
||||||
|
The `message` parameter is user-level input, not a system prompt. Structure it
|
||||||
|
for maximum instruction adherence:
|
||||||
|
|
||||||
|
```
|
||||||
|
Your task is to perform the following. Follow the instructions below exactly.
|
||||||
|
|
||||||
|
<agent-instructions>
|
||||||
|
[filled prompt content from the agent's .md file]
|
||||||
|
</agent-instructions>
|
||||||
|
|
||||||
|
Execute this now. Output ONLY the structured response following the format
|
||||||
|
specified in the instructions above.
|
||||||
|
```
|
||||||
|
|
||||||
|
- Use task-delegation framing ("Your task is...") rather than persona framing ("You are...")
|
||||||
|
- Wrap instructions in XML tags — the model treats tagged blocks as authoritative
|
||||||
|
- End with an explicit execution directive to prevent summarization of the instructions
|
||||||
|
|
||||||
|
### When this workaround can be removed
|
||||||
|
|
||||||
|
This approach compensates for Codex's plugin system not yet supporting an `agents`
|
||||||
|
field in `plugin.json`. When `RawPluginManifest` gains an `agents` field, the
|
||||||
|
plugin can symlink to `agents/` (mirroring the existing `skills/` symlink) and
|
||||||
|
skills can dispatch named agent types directly.
|
||||||
|
|
||||||
|
## Environment Detection
|
||||||
|
|
||||||
|
Skills that create worktrees or finish branches should detect their
|
||||||
|
environment with read-only git commands before proceeding:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
|
||||||
|
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
|
||||||
|
BRANCH=$(git branch --show-current)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `GIT_DIR != GIT_COMMON` → already in a linked worktree (skip creation)
|
||||||
|
- `BRANCH` empty → detached HEAD (cannot branch/push/PR from sandbox)
|
||||||
|
|
||||||
|
See `using-git-worktrees` Step 0 and `finishing-a-development-branch`
|
||||||
|
Step 1 for how each skill uses these signals.
|
||||||
|
|
||||||
|
## Codex App Finishing
|
||||||
|
|
||||||
|
When the sandbox blocks branch/push operations (detached HEAD in an
|
||||||
|
externally managed worktree), the agent commits all work and informs
|
||||||
|
the user to use the App's native controls:
|
||||||
|
|
||||||
|
- **"Create branch"** — names the branch, then commit/push/PR via App UI
|
||||||
|
- **"Hand off to local"** — transfers work to the user's local checkout
|
||||||
|
|
||||||
|
The agent can still run tests, stage files, and output suggested branch
|
||||||
|
names, commit messages, and PR descriptions for the user to copy.
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Gemini CLI Tool Mapping
|
||||||
|
|
||||||
|
Skills use Claude Code tool names. When you encounter these in a skill, use your platform equivalent:
|
||||||
|
|
||||||
|
| Skill references | Gemini CLI equivalent |
|
||||||
|
|-----------------|----------------------|
|
||||||
|
| `Read` (file reading) | `read_file` |
|
||||||
|
| `Write` (file creation) | `write_file` |
|
||||||
|
| `Edit` (file editing) | `replace` |
|
||||||
|
| `Bash` (run commands) | `run_shell_command` |
|
||||||
|
| `Grep` (search file content) | `grep_search` |
|
||||||
|
| `Glob` (search files by name) | `glob` |
|
||||||
|
| `TodoWrite` (task tracking) | `write_todos` |
|
||||||
|
| `Skill` tool (invoke a skill) | `activate_skill` |
|
||||||
|
| `WebSearch` | `google_web_search` |
|
||||||
|
| `WebFetch` | `web_fetch` |
|
||||||
|
| `Task` tool (dispatch subagent) | No equivalent — Gemini CLI does not support subagents |
|
||||||
|
|
||||||
|
## No subagent support
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
These tools are available in Gemini CLI but have no Claude Code equivalent:
|
||||||
|
|
||||||
|
| Tool | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `list_directory` | List files and subdirectories |
|
||||||
|
| `save_memory` | Persist facts to GEMINI.md across sessions |
|
||||||
|
| `ask_user` | Request structured input from the user |
|
||||||
|
| `tracker_create_task` | Rich task management (create, update, list, visualize) |
|
||||||
|
| `enter_plan_mode` / `exit_plan_mode` | Switch to read-only research mode before making changes |
|
||||||
@@ -89,16 +89,55 @@ certDomains!: string[];
|
|||||||
accessId!: string;
|
accessId!: string;
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. 实现插件方法
|
### 4. 动态显隐配置(mergeScript)
|
||||||
|
|
||||||
#### 4.1 插件实例化时执行的方法
|
使用 `mergeScript` 可以实现根据其他输入值动态控制当前输入项的显隐状态。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@TaskInput({
|
||||||
|
title: '匹配模式',
|
||||||
|
component: {
|
||||||
|
name: 'select',
|
||||||
|
options: [
|
||||||
|
{ label: '手动选择', value: 'manual' },
|
||||||
|
{ label: '根据证书匹配', value: 'auto' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
default: 'manual',
|
||||||
|
})
|
||||||
|
domainMatchMode!: 'manual' | 'auto';
|
||||||
|
|
||||||
|
@TaskInput(
|
||||||
|
createRemoteSelectInputDefine({
|
||||||
|
title: 'DCDN加速域名',
|
||||||
|
helper: '你在阿里云上配置的DCDN加速域名',
|
||||||
|
action: DeployCertToAliyunDCDN.prototype.onGetDomainList.name,
|
||||||
|
watches: ['certDomains', 'accessId'],
|
||||||
|
required: true,
|
||||||
|
mergeScript: `
|
||||||
|
return {
|
||||||
|
show: ctx.compute(({form})=>{
|
||||||
|
return domainMatchMode === "manual"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
domainName!: string | string[];
|
||||||
|
```
|
||||||
|
|
||||||
|
`mergeScript` 中的 `ctx.compute` 函数接收一个回调函数,通过 `form` 参数可以访问表单中的其他字段值。
|
||||||
|
|
||||||
|
### 5. 实现插件方法
|
||||||
|
|
||||||
|
#### 5.1 插件实例化时执行的方法
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// 插件实例化时执行的方法
|
// 插件实例化时执行的方法
|
||||||
async onInstance() {}
|
async onInstance() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 4.2 插件执行方法
|
#### 5.2 插件执行方法
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// 插件执行方法
|
// 插件执行方法
|
||||||
@@ -130,7 +169,9 @@ async execute(): Promise<void> {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 4.3 后端获取选项方法
|
#### 5.3 后端获取选项方法
|
||||||
|
|
||||||
|
使用 `createRemoteSelectInputDefine` 创建远程选择输入项,`action` 指向的方法接收 `PageSearch` 参数并返回 `{ list, total }` 格式。
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
@TaskInput(
|
@TaskInput(
|
||||||
@@ -145,8 +186,8 @@ async execute(): Promise<void> {
|
|||||||
)
|
)
|
||||||
siteName!: string | string[];
|
siteName!: string | string[];
|
||||||
|
|
||||||
// 从后端获取选项的方法
|
// 从后端获取选项的方法,接收PageSearch参数
|
||||||
async onGetSiteList(req: PageSearch) {
|
async onGetSiteList(data: PageSearch) {
|
||||||
if (!this.accessId) {
|
if (!this.accessId) {
|
||||||
throw new Error('请选择Access授权');
|
throw new Error('请选择Access授权');
|
||||||
}
|
}
|
||||||
@@ -154,7 +195,7 @@ async onGetSiteList(req: PageSearch) {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const access = await this.getAccess(this.accessId);
|
const access = await this.getAccess(this.accessId);
|
||||||
|
|
||||||
// const siteRes = await access.GetDomainList(req);
|
// const siteRes = await access.GetDomainList(data);
|
||||||
// 以下是模拟数据
|
// 以下是模拟数据
|
||||||
const siteRes = [
|
const siteRes = [
|
||||||
{ id: 1, siteName: 'site1.com' },
|
{ id: 1, siteName: 'site1.com' },
|
||||||
@@ -169,8 +210,12 @@ async onGetSiteList(req: PageSearch) {
|
|||||||
domain: item.siteName,
|
domain: item.siteName,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
// 将站点域名名称根据证书域名进行匹配分组,分成匹配的和不匹配的两组选项,返回给前端,供用户选择
|
|
||||||
return optionsUtils.buildGroupOptions(options, this.certDomains);
|
// 返回{list, total}格式
|
||||||
|
return {
|
||||||
|
list: optionsUtils.buildGroupOptions(options, this.certDomains),
|
||||||
|
total: siteRes.length,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -383,7 +428,10 @@ export class DemoTest extends AbstractTaskPlugin {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
//将站点域名名称根据证书域名进行匹配分组,分成匹配的和不匹配的两组选项,返回给前端,供用户选择
|
//将站点域名名称根据证书域名进行匹配分组,分成匹配的和不匹配的两组选项,返回给前端,供用户选择
|
||||||
return optionsUtils.buildGroupOptions(options, this.certDomains);
|
return {
|
||||||
|
list: optionsUtils.buildGroupOptions(options, this.certDomains),
|
||||||
|
total: siteRes.length,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
---
|
||||||
|
name: using-superpowers
|
||||||
|
description: Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions
|
||||||
|
---
|
||||||
|
|
||||||
|
<SUBAGENT-STOP>
|
||||||
|
If you were dispatched as a subagent to execute a specific task, skip this skill.
|
||||||
|
</SUBAGENT-STOP>
|
||||||
|
|
||||||
|
<EXTREMELY-IMPORTANT>
|
||||||
|
If you think there is even a 1% chance a skill might apply to what you are doing, you ABSOLUTELY MUST invoke the skill.
|
||||||
|
|
||||||
|
IF A SKILL APPLIES TO YOUR TASK, YOU DO NOT HAVE A CHOICE. YOU MUST USE IT.
|
||||||
|
|
||||||
|
This is not negotiable. This is not optional. You cannot rationalize your way out of this.
|
||||||
|
</EXTREMELY-IMPORTANT>
|
||||||
|
|
||||||
|
## Instruction Priority
|
||||||
|
|
||||||
|
Superpowers skills override default system prompt behavior, but **user instructions always take precedence**:
|
||||||
|
|
||||||
|
1. **User's explicit instructions** (CLAUDE.md, GEMINI.md, AGENTS.md, direct requests) — highest priority
|
||||||
|
2. **Superpowers skills** — override default system behavior where they conflict
|
||||||
|
3. **Default system prompt** — lowest priority
|
||||||
|
|
||||||
|
If CLAUDE.md, GEMINI.md, or AGENTS.md says "don't use TDD" and a skill says "always use TDD," follow the user's instructions. The user is in control.
|
||||||
|
|
||||||
|
## How to Access Skills
|
||||||
|
|
||||||
|
**In Claude Code:** Use the `Skill` tool. When you invoke a skill, its content is loaded and presented to you—follow it directly. Never use the Read tool on skill files.
|
||||||
|
|
||||||
|
**In Gemini CLI:** Skills activate via the `activate_skill` tool. Gemini loads skill metadata at session start and activates the full content on demand.
|
||||||
|
|
||||||
|
**In other environments:** Check your platform's documentation for how skills are loaded.
|
||||||
|
|
||||||
|
## Platform Adaptation
|
||||||
|
|
||||||
|
Skills use Claude Code tool names. Non-CC platforms: see `references/codex-tools.md` (Codex) for tool equivalents. Gemini CLI users get the tool mapping loaded automatically via GEMINI.md.
|
||||||
|
|
||||||
|
# Using Skills
|
||||||
|
|
||||||
|
## The Rule
|
||||||
|
|
||||||
|
**Invoke relevant or requested skills BEFORE any response or action.** Even a 1% chance a skill might apply means that you should invoke the skill to check. If an invoked skill turns out to be wrong for the situation, you don't need to use it.
|
||||||
|
|
||||||
|
```dot
|
||||||
|
digraph skill_flow {
|
||||||
|
"User message received" [shape=doublecircle];
|
||||||
|
"About to EnterPlanMode?" [shape=doublecircle];
|
||||||
|
"Already brainstormed?" [shape=diamond];
|
||||||
|
"Invoke brainstorming skill" [shape=box];
|
||||||
|
"Might any skill apply?" [shape=diamond];
|
||||||
|
"Invoke Skill tool" [shape=box];
|
||||||
|
"Announce: 'Using [skill] to [purpose]'" [shape=box];
|
||||||
|
"Has checklist?" [shape=diamond];
|
||||||
|
"Create TodoWrite todo per item" [shape=box];
|
||||||
|
"Follow skill exactly" [shape=box];
|
||||||
|
"Respond (including clarifications)" [shape=doublecircle];
|
||||||
|
|
||||||
|
"About to EnterPlanMode?" -> "Already brainstormed?";
|
||||||
|
"Already brainstormed?" -> "Invoke brainstorming skill" [label="no"];
|
||||||
|
"Already brainstormed?" -> "Might any skill apply?" [label="yes"];
|
||||||
|
"Invoke brainstorming skill" -> "Might any skill apply?";
|
||||||
|
|
||||||
|
"User message received" -> "Might any skill apply?";
|
||||||
|
"Might any skill apply?" -> "Invoke Skill tool" [label="yes, even 1%"];
|
||||||
|
"Might any skill apply?" -> "Respond (including clarifications)" [label="definitely not"];
|
||||||
|
"Invoke Skill tool" -> "Announce: 'Using [skill] to [purpose]'";
|
||||||
|
"Announce: 'Using [skill] to [purpose]'" -> "Has checklist?";
|
||||||
|
"Has checklist?" -> "Create TodoWrite todo per item" [label="yes"];
|
||||||
|
"Has checklist?" -> "Follow skill exactly" [label="no"];
|
||||||
|
"Create TodoWrite todo per item" -> "Follow skill exactly";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Red Flags
|
||||||
|
|
||||||
|
These thoughts mean STOP—you're rationalizing:
|
||||||
|
|
||||||
|
| Thought | Reality |
|
||||||
|
|---------|---------|
|
||||||
|
| "This is just a simple question" | Questions are tasks. Check for skills. |
|
||||||
|
| "I need more context first" | Skill check comes BEFORE clarifying questions. |
|
||||||
|
| "Let me explore the codebase first" | Skills tell you HOW to explore. Check first. |
|
||||||
|
| "I can check git/files quickly" | Files lack conversation context. Check for skills. |
|
||||||
|
| "Let me gather information first" | Skills tell you HOW to gather information. |
|
||||||
|
| "This doesn't need a formal skill" | If a skill exists, use it. |
|
||||||
|
| "I remember this skill" | Skills evolve. Read current version. |
|
||||||
|
| "This doesn't count as a task" | Action = task. Check for skills. |
|
||||||
|
| "The skill is overkill" | Simple things become complex. Use it. |
|
||||||
|
| "I'll just do this one thing first" | Check BEFORE doing anything. |
|
||||||
|
| "This feels productive" | Undisciplined action wastes time. Skills prevent this. |
|
||||||
|
| "I know what that means" | Knowing the concept ≠ using the skill. Invoke it. |
|
||||||
|
|
||||||
|
## Skill Priority
|
||||||
|
|
||||||
|
When multiple skills could apply, use this order:
|
||||||
|
|
||||||
|
1. **Process skills first** (brainstorming, debugging) - these determine HOW to approach the task
|
||||||
|
2. **Implementation skills second** (frontend-design, mcp-builder) - these guide execution
|
||||||
|
|
||||||
|
"Let's build X" → brainstorming first, then implementation skills.
|
||||||
|
"Fix this bug" → debugging first, then domain-specific skills.
|
||||||
|
|
||||||
|
## Skill Types
|
||||||
|
|
||||||
|
**Rigid** (TDD, debugging): Follow exactly. Don't adapt away discipline.
|
||||||
|
|
||||||
|
**Flexible** (patterns): Adapt principles to context.
|
||||||
|
|
||||||
|
The skill itself tells you which.
|
||||||
|
|
||||||
|
## User Instructions
|
||||||
|
|
||||||
|
Instructions say WHAT, not HOW. "Add X" or "Fix Y" doesn't mean skip workflows.
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
# Codex Tool Mapping
|
||||||
|
|
||||||
|
Skills use Claude Code tool names. When you encounter these in a skill, use your platform equivalent:
|
||||||
|
|
||||||
|
| Skill references | Codex equivalent |
|
||||||
|
|-----------------|------------------|
|
||||||
|
| `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` |
|
||||||
|
| 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 |
|
||||||
|
| `Read`, `Write`, `Edit` (files) | Use your native file tools |
|
||||||
|
| `Bash` (run commands) | Use your native shell tools |
|
||||||
|
|
||||||
|
## Subagent dispatch requires multi-agent support
|
||||||
|
|
||||||
|
Add to your Codex config (`~/.codex/config.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[features]
|
||||||
|
multi_agent = true
|
||||||
|
```
|
||||||
|
|
||||||
|
This enables `spawn_agent`, `wait`, and `close_agent` for skills like `dispatching-parallel-agents` and `subagent-driven-development`.
|
||||||
|
|
||||||
|
## Named agent dispatch
|
||||||
|
|
||||||
|
Claude Code skills reference named agent types like `superpowers:code-reviewer`.
|
||||||
|
Codex does not have a named agent registry — `spawn_agent` creates generic agents
|
||||||
|
from built-in roles (`default`, `explorer`, `worker`).
|
||||||
|
|
||||||
|
When a skill says to dispatch a named agent type:
|
||||||
|
|
||||||
|
1. Find the agent's prompt file (e.g., `agents/code-reviewer.md` or the skill's
|
||||||
|
local prompt template like `code-quality-reviewer-prompt.md`)
|
||||||
|
2. Read the prompt content
|
||||||
|
3. Fill any template placeholders (`{BASE_SHA}`, `{WHAT_WAS_IMPLEMENTED}`, etc.)
|
||||||
|
4. Spawn a `worker` agent with the filled content as the `message`
|
||||||
|
|
||||||
|
| Skill instruction | Codex equivalent |
|
||||||
|
|-------------------|------------------|
|
||||||
|
| `Task tool (superpowers:code-reviewer)` | `spawn_agent(agent_type="worker", message=...)` with `code-reviewer.md` content |
|
||||||
|
| `Task tool (general-purpose)` with inline prompt | `spawn_agent(message=...)` with the same prompt |
|
||||||
|
|
||||||
|
### Message framing
|
||||||
|
|
||||||
|
The `message` parameter is user-level input, not a system prompt. Structure it
|
||||||
|
for maximum instruction adherence:
|
||||||
|
|
||||||
|
```
|
||||||
|
Your task is to perform the following. Follow the instructions below exactly.
|
||||||
|
|
||||||
|
<agent-instructions>
|
||||||
|
[filled prompt content from the agent's .md file]
|
||||||
|
</agent-instructions>
|
||||||
|
|
||||||
|
Execute this now. Output ONLY the structured response following the format
|
||||||
|
specified in the instructions above.
|
||||||
|
```
|
||||||
|
|
||||||
|
- Use task-delegation framing ("Your task is...") rather than persona framing ("You are...")
|
||||||
|
- Wrap instructions in XML tags — the model treats tagged blocks as authoritative
|
||||||
|
- End with an explicit execution directive to prevent summarization of the instructions
|
||||||
|
|
||||||
|
### When this workaround can be removed
|
||||||
|
|
||||||
|
This approach compensates for Codex's plugin system not yet supporting an `agents`
|
||||||
|
field in `plugin.json`. When `RawPluginManifest` gains an `agents` field, the
|
||||||
|
plugin can symlink to `agents/` (mirroring the existing `skills/` symlink) and
|
||||||
|
skills can dispatch named agent types directly.
|
||||||
|
|
||||||
|
## Environment Detection
|
||||||
|
|
||||||
|
Skills that create worktrees or finish branches should detect their
|
||||||
|
environment with read-only git commands before proceeding:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
|
||||||
|
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
|
||||||
|
BRANCH=$(git branch --show-current)
|
||||||
|
```
|
||||||
|
|
||||||
|
- `GIT_DIR != GIT_COMMON` → already in a linked worktree (skip creation)
|
||||||
|
- `BRANCH` empty → detached HEAD (cannot branch/push/PR from sandbox)
|
||||||
|
|
||||||
|
See `using-git-worktrees` Step 0 and `finishing-a-development-branch`
|
||||||
|
Step 1 for how each skill uses these signals.
|
||||||
|
|
||||||
|
## Codex App Finishing
|
||||||
|
|
||||||
|
When the sandbox blocks branch/push operations (detached HEAD in an
|
||||||
|
externally managed worktree), the agent commits all work and informs
|
||||||
|
the user to use the App's native controls:
|
||||||
|
|
||||||
|
- **"Create branch"** — names the branch, then commit/push/PR via App UI
|
||||||
|
- **"Hand off to local"** — transfers work to the user's local checkout
|
||||||
|
|
||||||
|
The agent can still run tests, stage files, and output suggested branch
|
||||||
|
names, commit messages, and PR descriptions for the user to copy.
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Gemini CLI Tool Mapping
|
||||||
|
|
||||||
|
Skills use Claude Code tool names. When you encounter these in a skill, use your platform equivalent:
|
||||||
|
|
||||||
|
| Skill references | Gemini CLI equivalent |
|
||||||
|
|-----------------|----------------------|
|
||||||
|
| `Read` (file reading) | `read_file` |
|
||||||
|
| `Write` (file creation) | `write_file` |
|
||||||
|
| `Edit` (file editing) | `replace` |
|
||||||
|
| `Bash` (run commands) | `run_shell_command` |
|
||||||
|
| `Grep` (search file content) | `grep_search` |
|
||||||
|
| `Glob` (search files by name) | `glob` |
|
||||||
|
| `TodoWrite` (task tracking) | `write_todos` |
|
||||||
|
| `Skill` tool (invoke a skill) | `activate_skill` |
|
||||||
|
| `WebSearch` | `google_web_search` |
|
||||||
|
| `WebFetch` | `web_fetch` |
|
||||||
|
| `Task` tool (dispatch subagent) | No equivalent — Gemini CLI does not support subagents |
|
||||||
|
|
||||||
|
## No subagent support
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
These tools are available in Gemini CLI but have no Claude Code equivalent:
|
||||||
|
|
||||||
|
| Tool | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `list_directory` | List files and subdirectories |
|
||||||
|
| `save_memory` | Persist facts to GEMINI.md across sessions |
|
||||||
|
| `ask_user` | Request structured input from the user |
|
||||||
|
| `tracker_create_task` | Rich task management (create, update, list, visualize) |
|
||||||
|
| `enter_plan_mode` / `exit_plan_mode` | Switch to read-only research mode before making changes |
|
||||||
@@ -4,7 +4,7 @@ import { FileStore } from "../core/file-store.js";
|
|||||||
import { accessRegistry, IAccessService } from "../access/index.js";
|
import { accessRegistry, IAccessService } from "../access/index.js";
|
||||||
import { ICnameProxyService, IEmailService, IServiceGetter, IUrlService } from "../service/index.js";
|
import { ICnameProxyService, IEmailService, IServiceGetter, IUrlService } from "../service/index.js";
|
||||||
import { CancelError, IContext, RunHistory, RunnableCollection } from "../core/index.js";
|
import { CancelError, IContext, RunHistory, RunnableCollection } from "../core/index.js";
|
||||||
import { HttpRequestConfig, ILogger, logger, utils } from "@certd/basic";
|
import { HttpRequestConfig, ILogger, logger, optionsUtils, utils } from "@certd/basic";
|
||||||
import { HttpClient } from "@certd/basic";
|
import { HttpClient } from "@certd/basic";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { IPluginConfigService } from "../service/config.js";
|
import { IPluginConfigService } from "../service/config.js";
|
||||||
@@ -315,6 +315,11 @@ export abstract class AbstractTaskPlugin implements ITaskPlugin {
|
|||||||
getLastOutput(key: string) {
|
getLastOutput(key: string) {
|
||||||
return this.getLastStatus().status?.output?.[key];
|
return this.getLastStatus().status?.output?.[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getMatchedDomains(domainList: string[], certDomains: string[]): string[] {
|
||||||
|
const { matched } = optionsUtils.groupByDomain(domainList, certDomains);
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type OutputVO = {
|
export type OutputVO = {
|
||||||
|
|||||||
@@ -589,11 +589,11 @@ export default {
|
|||||||
userValidityPeriodHelper: "有效期内用户可正常使用,失效后用户的流水线将被停用",
|
userValidityPeriodHelper: "有效期内用户可正常使用,失效后用户的流水线将被停用",
|
||||||
enableUsernameRegistration: "开启用户名注册",
|
enableUsernameRegistration: "开启用户名注册",
|
||||||
enableEmailRegistration: "开启邮箱注册",
|
enableEmailRegistration: "开启邮箱注册",
|
||||||
proFeature: "专业版功能",
|
proFeature: "Certd专业版功能",
|
||||||
emailServerSetup: "设置邮箱服务器",
|
emailServerSetup: "设置邮箱服务器",
|
||||||
enableSmsLoginRegister: "开启手机号登录、注册",
|
enableSmsLoginRegister: "开启手机号登录、注册",
|
||||||
defaultLoginType: "默认登录方式",
|
defaultLoginType: "默认登录方式",
|
||||||
commFeature: "商业版功能",
|
commFeature: "Certd商业版功能",
|
||||||
smsProvider: "短信提供商",
|
smsProvider: "短信提供商",
|
||||||
aliyunSms: "阿里云短信",
|
aliyunSms: "阿里云短信",
|
||||||
tencentSms: "腾讯云短信",
|
tencentSms: "腾讯云短信",
|
||||||
|
|||||||
@@ -88,13 +88,13 @@ export default {
|
|||||||
activation_code_one_use: "激活码使用过一次之后,不可再次使用,如果要更换站点,请",
|
activation_code_one_use: "激活码使用过一次之后,不可再次使用,如果要更换站点,请",
|
||||||
bind_account: "绑定账号",
|
bind_account: "绑定账号",
|
||||||
transfer_vip: '然后"转移VIP"即可',
|
transfer_vip: '然后"转移VIP"即可',
|
||||||
needVipTip: "此为专业版功能,请先开通专业版",
|
needVipTip: "此为Certd专业版功能,请先开通Certd专业版",
|
||||||
manual_activation: "激活码手动激活",
|
manual_activation: "激活码手动激活",
|
||||||
close: "关闭",
|
close: "关闭",
|
||||||
have_activation_code: "已经有激活码了?",
|
have_activation_code: "已经有激活码了?",
|
||||||
buy: "立即购买",
|
buy: "立即购买",
|
||||||
already_plus: "已经是专业版了,是否升级为商业版?注意:专业版时长将被覆盖",
|
already_plus: "已经是Certd专业版了,是否升级为商业版?注意:Certd专业版时长将被覆盖",
|
||||||
already_comm: "已经是商业版了,不能降级为专业版",
|
already_comm: "已经是Certd商业版了,不能降级为专业版",
|
||||||
already_perpetual_plus: "您已经是永久专业版了,无法继续升级",
|
already_perpetual_plus: "您已经是永久专业版了,无法继续升级",
|
||||||
confirm: "确认",
|
confirm: "确认",
|
||||||
not_effective: "VIP没有生效/时长未同步?",
|
not_effective: "VIP没有生效/时长未同步?",
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ onMounted(() => {
|
|||||||
await settingStore.doBindUrl();
|
await settingStore.doBindUrl();
|
||||||
notification.success({
|
notification.success({
|
||||||
message: "更新成功",
|
message: "更新成功",
|
||||||
description: "专业版/商业版已激活",
|
description: "Certd专业版/商业版已激活",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export class UserTwoFactorSettingController extends BaseController {
|
|||||||
@Post("/save", { description: Constants.per.authOnly, summary: "保存双因子认证设置" })
|
@Post("/save", { description: Constants.per.authOnly, summary: "保存双因子认证设置" })
|
||||||
async save(@Body(ALL) bean: any) {
|
async save(@Body(ALL) bean: any) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new Error('本功能需要开通专业版')
|
throw new Error('本功能需要开通Certd专业版')
|
||||||
}
|
}
|
||||||
const userId = this.getUserId();
|
const userId = this.getUserId();
|
||||||
const setting = new UserTwoFactorSetting();
|
const setting = new UserTwoFactorSetting();
|
||||||
@@ -57,7 +57,7 @@ export class UserTwoFactorSettingController extends BaseController {
|
|||||||
@Post("/authenticator/save", { description: Constants.per.authOnly, summary: "保存验证器设置" })
|
@Post("/authenticator/save", { description: Constants.per.authOnly, summary: "保存验证器设置" })
|
||||||
async authenticatorSave(@Body(ALL) bean: any) {
|
async authenticatorSave(@Body(ALL) bean: any) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new Error('本功能需要开通专业版')
|
throw new Error('本功能需要开通Certd专业版')
|
||||||
}
|
}
|
||||||
const userId = this.getUserId();
|
const userId = this.getUserId();
|
||||||
await this.twoFactorService.saveAuthenticator({
|
await this.twoFactorService.saveAuthenticator({
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ export class UserSettingsController extends CrudController<UserSettingsService>
|
|||||||
@Post("/grant/save", { description: Constants.per.authOnly, summary: "保存授权设置" })
|
@Post("/grant/save", { description: Constants.per.authOnly, summary: "保存授权设置" })
|
||||||
async grantSettingsSave(@Body(ALL) bean: UserGrantSetting) {
|
async grantSettingsSave(@Body(ALL) bean: UserGrantSetting) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new Error('本功能需要开通专业版')
|
throw new Error('本功能需要开通Certd专业版')
|
||||||
}
|
}
|
||||||
const userId = this.getUserId();
|
const userId = this.getUserId();
|
||||||
const setting = new UserGrantSetting();
|
const setting = new UserGrantSetting();
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ export class LoginService {
|
|||||||
async loginByTwoFactor(req: { loginId: string; verifyCode: string }) {
|
async loginByTwoFactor(req: { loginId: string; verifyCode: string }) {
|
||||||
//检查是否开启多重认证
|
//检查是否开启多重认证
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new Error('本功能需要开通专业版')
|
throw new Error('本功能需要开通Certd专业版')
|
||||||
}
|
}
|
||||||
const userId = cache.get(`login_2fa_code:${req.loginId}`)
|
const userId = cache.get(`login_2fa_code:${req.loginId}`)
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ export class NotificationService extends BaseService<NotificationEntity> {
|
|||||||
const define = this.getDefineByType(type)
|
const define = this.getDefineByType(type)
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
if (define.needPlus && !isPlus()) {
|
if (define.needPlus && !isPlus()) {
|
||||||
throw new NeedVIPException("此通知类型为专业版功能,请升级到专业版或以上级别");
|
throw new NeedVIPException("此通知类型为Certd专业版功能,请升级到专业版或以上级别");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -941,7 +941,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
|
|
||||||
async batchDelete(ids: number[], userId?: number, projectId?: number) {
|
async batchDelete(ids: number[], userId?: number, projectId?: number) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级Certd专业版");
|
||||||
}
|
}
|
||||||
for (const id of ids) {
|
for (const id of ids) {
|
||||||
if (userId && userId > 0) {
|
if (userId && userId > 0) {
|
||||||
@@ -956,7 +956,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
|
|
||||||
async batchUpdateGroup(ids: number[], groupId: number, userId: any, projectId?: number) {
|
async batchUpdateGroup(ids: number[], groupId: number, userId: any, projectId?: number) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级Certd专业版");
|
||||||
}
|
}
|
||||||
const query: any = {}
|
const query: any = {}
|
||||||
if (userId && userId > 0) {
|
if (userId && userId > 0) {
|
||||||
@@ -982,7 +982,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
*/
|
*/
|
||||||
async batchTransfer(ids: number[], projectId: number) {
|
async batchTransfer(ids: number[], projectId: number) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级Certd专业版");
|
||||||
}
|
}
|
||||||
if (!isEnterprise()) {
|
if (!isEnterprise()) {
|
||||||
throw new Error("当前为非企业模式,不允许转移到其他项目");
|
throw new Error("当前为非企业模式,不允许转移到其他项目");
|
||||||
@@ -1075,7 +1075,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
|
|
||||||
async batchUpdateTrigger(ids: number[], trigger: any, userId: any, projectId?: number) {
|
async batchUpdateTrigger(ids: number[], trigger: any, userId: any, projectId?: number) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级Certd专业版");
|
||||||
}
|
}
|
||||||
//允许管理员修改,userId=null
|
//允许管理员修改,userId=null
|
||||||
const query: any = {}
|
const query: any = {}
|
||||||
@@ -1128,7 +1128,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
|
|
||||||
async batchUpdateNotifications(ids: number[], notification: Notification, userId: any, projectId?: number) {
|
async batchUpdateNotifications(ids: number[], notification: Notification, userId: any, projectId?: number) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级Certd专业版");
|
||||||
}
|
}
|
||||||
//允许管理员修改,userId=null
|
//允许管理员修改,userId=null
|
||||||
const query: any = {}
|
const query: any = {}
|
||||||
@@ -1167,7 +1167,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
|
|
||||||
async batchRerun(ids: number[], force: boolean, userId: any, projectId?: number) {
|
async batchRerun(ids: number[], force: boolean, userId: any, projectId?: number) {
|
||||||
if (!isPlus()) {
|
if (!isPlus()) {
|
||||||
throw new NeedVIPException("此功能需要升级专业版");
|
throw new NeedVIPException("此功能需要升级Certd专业版");
|
||||||
}
|
}
|
||||||
//允许userId为空,为空则为管理员触发
|
//允许userId为空,为空则为管理员触发
|
||||||
if (ids.length === 0) {
|
if (ids.length === 0) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
|
import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import {
|
import {
|
||||||
createCertDomainGetterInputDefine,
|
createCertDomainGetterInputDefine,
|
||||||
@@ -55,6 +55,19 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin {
|
|||||||
})
|
})
|
||||||
certName!: string;
|
certName!: string;
|
||||||
|
|
||||||
|
@TaskInput({
|
||||||
|
title: '域名匹配模式',
|
||||||
|
helper: '选择域名匹配方式',
|
||||||
|
component: {
|
||||||
|
name: 'select',
|
||||||
|
options: [
|
||||||
|
{ label: '手动选择', value: 'manual' },
|
||||||
|
{ label: '根据证书匹配', value: 'auto' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
default: 'manual',
|
||||||
|
})
|
||||||
|
domainMatchMode!: 'manual' | 'auto';
|
||||||
|
|
||||||
@TaskInput(
|
@TaskInput(
|
||||||
createRemoteSelectInputDefine({
|
createRemoteSelectInputDefine({
|
||||||
@@ -63,6 +76,13 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin {
|
|||||||
action: DeployCertToAliyunDCDN.prototype.onGetDomainList.name,
|
action: DeployCertToAliyunDCDN.prototype.onGetDomainList.name,
|
||||||
watches: ['certDomains', 'accessId'],
|
watches: ['certDomains', 'accessId'],
|
||||||
required: true,
|
required: true,
|
||||||
|
mergeScript: `
|
||||||
|
return {
|
||||||
|
show: ctx.compute(({form})=>{
|
||||||
|
return domainMatchMode === "manual"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
`,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
domainName!: string | string[];
|
domainName!: string | string[];
|
||||||
@@ -71,15 +91,30 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin {
|
|||||||
async onInstance() { }
|
async onInstance() { }
|
||||||
async execute(): Promise<void> {
|
async execute(): Promise<void> {
|
||||||
this.logger.info('开始部署证书到阿里云DCDN');
|
this.logger.info('开始部署证书到阿里云DCDN');
|
||||||
if (!this.domainName) {
|
|
||||||
throw new Error('您还未选择DCDN域名');
|
|
||||||
}
|
|
||||||
const access = (await this.getAccess(this.accessId)) as AliyunAccess;
|
const access = (await this.getAccess(this.accessId)) as AliyunAccess;
|
||||||
const client = await this.getClient(access);
|
const client = await this.getClient(access);
|
||||||
if (typeof this.domainName === 'string') {
|
|
||||||
this.domainName = [this.domainName];
|
let domains: string[] = [];
|
||||||
|
|
||||||
|
if (this.domainMatchMode === 'auto') {
|
||||||
|
this.logger.info('使用根据证书匹配模式');
|
||||||
|
if (!this.certDomains || this.certDomains.length === 0) {
|
||||||
|
throw new Error('未获取到证书域名信息');
|
||||||
|
}
|
||||||
|
domains = await this.getAutoMatchedDomains(this.certDomains);
|
||||||
|
if (domains.length === 0) {
|
||||||
|
this.logger.warn('未找到匹配的DCDN域名');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.logger.info(`找到 ${domains.length} 个匹配的DCDN域名`);
|
||||||
|
} else {
|
||||||
|
if (!this.domainName) {
|
||||||
|
throw new Error('您还未选择DCDN域名');
|
||||||
|
}
|
||||||
|
domains = typeof this.domainName === 'string' ? [this.domainName] : this.domainName;
|
||||||
}
|
}
|
||||||
for (const domainName of this.domainName) {
|
|
||||||
|
for (const domainName of domains) {
|
||||||
this.logger.info(`[${domainName}]开始部署`)
|
this.logger.info(`[${domainName}]开始部署`)
|
||||||
const params = await this.buildParams(domainName);
|
const params = await this.buildParams(domainName);
|
||||||
await this.doRequest(client, params);
|
await this.doRequest(client, params);
|
||||||
@@ -152,7 +187,36 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async onGetDomainList(data: any) {
|
async getAutoMatchedDomains(certDomains: string[]): Promise<string[]> {
|
||||||
|
const matchedDomains: string[] = [];
|
||||||
|
let pageNumber = 1;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const result = await this.onGetDomainList({ pageNo: pageNumber });
|
||||||
|
const pageData = result.list;
|
||||||
|
this.logger.info(`获取到 ${pageData.length} 个DCDN域名`);
|
||||||
|
|
||||||
|
if (!pageData || pageData.length === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const matched = this.getMatchedDomains(pageData, certDomains);
|
||||||
|
matchedDomains.push(...matched);
|
||||||
|
|
||||||
|
const totalCount = result.total || 0;
|
||||||
|
if (pageNumber * 500 >= totalCount) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pageNumber++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchedDomains;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async onGetDomainList(data: PageSearch) {
|
||||||
if (!this.accessId) {
|
if (!this.accessId) {
|
||||||
throw new Error('请选择Access授权');
|
throw new Error('请选择Access授权');
|
||||||
}
|
}
|
||||||
@@ -161,7 +225,7 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin {
|
|||||||
const client = await this.getClient(access);
|
const client = await this.getClient(access);
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
// 'DomainName': 'aaa',
|
PageNumber: data.pageNo || 1,
|
||||||
PageSize: 500,
|
PageSize: 500,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -172,10 +236,9 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin {
|
|||||||
|
|
||||||
const res = await client.request('DescribeDcdnUserDomains', params, requestOption);
|
const res = await client.request('DescribeDcdnUserDomains', params, requestOption);
|
||||||
this.checkRet(res);
|
this.checkRet(res);
|
||||||
const pageData = res?.Domains?.PageData;
|
const pageData = res?.Domains?.PageData || [];
|
||||||
if (!pageData || pageData.length === 0) {
|
const total = res?.Domains?.TotalCount || 0;
|
||||||
throw new Error('找不到CDN域名,您可以手动输入');
|
|
||||||
}
|
|
||||||
const options = pageData.map((item: any) => {
|
const options = pageData.map((item: any) => {
|
||||||
return {
|
return {
|
||||||
value: item.DomainName,
|
value: item.DomainName,
|
||||||
@@ -183,7 +246,11 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin {
|
|||||||
domain: item.DomainName,
|
domain: item.DomainName,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return optionsUtils.buildGroupOptions(options, this.certDomains);
|
|
||||||
|
return {
|
||||||
|
list: optionsUtils.buildGroupOptions(options, this.certDomains),
|
||||||
|
total: total,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new DeployCertToAliyunDCDN();
|
new DeployCertToAliyunDCDN();
|
||||||
|
|||||||
Reference in New Issue
Block a user