From 21b93f23e0631f0675eb4fda0412c0c07bd7b161 Mon Sep 17 00:00:00 2001
From: Fred DE MATOS
Date: Thu, 15 Jan 2026 17:09:45 +0100
Subject: [PATCH 1/7] feat: add release command and ask-questions skill
---
.../SKILL.md => command/release.md | 23 ++++----
.../ask-questions-if-underspecified/SKILL.md | 59 +++++++++++++++++++
src/index.ts | 1 +
src/tools/skill.ts | 20 ++++++-
4 files changed, 91 insertions(+), 12 deletions(-)
rename skill/code-release/SKILL.md => command/release.md (67%)
create mode 100644 skill/ask-questions-if-underspecified/SKILL.md
diff --git a/skill/code-release/SKILL.md b/command/release.md
similarity index 67%
rename from skill/code-release/SKILL.md
rename to command/release.md
index 2d33a13..6dca615 100644
--- a/skill/code-release/SKILL.md
+++ b/command/release.md
@@ -1,13 +1,12 @@
---
-name: code-release
-description: >
- Prepare and execute a release with version bumping, changelog updates, and tags.
-use_when: >
- REQUIRED: When the user asks to prepare or perform a release,
- call skill({ name: "code-release" }) before changing any release artifacts.
+description: Prepare and execute a release with version bumping, changelog updates, and tags
---
-# Code Release Skill
+## Context
+
+- Current version: !`node -p "require('./package.json').version"`
+- Latest tag: !`git describe --tags --abbrev=0 2>/dev/null || echo "none"`
+- Commits since last tag: !`git log $(git describe --tags --abbrev=0 2>/dev/null || echo "HEAD~10")..HEAD --oneline 2>/dev/null || git log --oneline -10`
## CRITICAL CONSTRAINT
@@ -17,13 +16,15 @@ Any destructive or remote action requires confirmation, including:
- `git tag`
- `git push`
-## Step 1: Determine last released version
+## Your task
+
+### Step 1: Determine last released version
1. Prefer the latest Git tag that matches `v`.
2. If no matching tag exists, use the version in `package.json`.
3. Collect commits since the last version (tag to `HEAD`).
-## Step 2: Propose version bump
+### Step 2: Propose version bump
Analyze commits since the last version and recommend a semver bump:
- **major**: breaking changes or incompatible behavior changes.
@@ -32,14 +33,14 @@ Analyze commits since the last version and recommend a semver bump:
Present the recommendation and ask the user to confirm before changing any files.
-## Step 3: Update release artifacts (after confirmation)
+### Step 3: Update release artifacts (after confirmation)
- Update the version in `package.json`.
- Update `CHANGELOG` with a new section for the version.
- Summarize changes based on the commit range.
- Preserve the existing changelog format.
-## Step 4: Tag and publish (after confirmation)
+### Step 4: Tag and publish (after confirmation)
- Commit release changes with a clear release message.
- Create an annotated tag (for example, `vX.Y.Z`).
diff --git a/skill/ask-questions-if-underspecified/SKILL.md b/skill/ask-questions-if-underspecified/SKILL.md
new file mode 100644
index 0000000..00429e4
--- /dev/null
+++ b/skill/ask-questions-if-underspecified/SKILL.md
@@ -0,0 +1,59 @@
+---
+name: ask-questions-if-underspecified
+description: Clarify requirements before implementing. Use when serious doubts arise.
+use_when: >
+ When a request has multiple plausible interpretations or key details
+ (objective, scope, constraints, environment, or safety) are unclear,
+ load this skill before starting implementation.
+ Do NOT use when the request is already clear or when a quick, low-risk
+ discovery read can answer the missing details.
+---
+
+# Ask Questions If Underspecified
+
+## Goal
+
+Ask the minimum set of clarifying questions needed to avoid wrong work; do not start implementing until the must-have questions are answered (or the user explicitly approves proceeding with stated assumptions).
+
+## Workflow
+
+### 1) Decide whether the request is underspecified
+
+Treat a request as underspecified if after exploring how to perform the work, some or all of the following are not clear:
+- Define the objective (what should change vs stay the same)
+- Define "done" (acceptance criteria, examples, edge cases)
+- Define scope (which files/components/users are in/out)
+- Define constraints (compatibility, performance, style, deps, time)
+- Identify environment (language/runtime versions, OS, build/test runner)
+- Clarify safety/reversibility (data migration, rollout/rollback, risk)
+
+If multiple plausible interpretations exist, assume it is underspecified.
+
+### 2) Ask must-have questions first (keep it small)
+
+Ask 1-5 questions in the first pass. Prefer questions that eliminate whole branches of work.
+
+Use the `question` tool to present structured choices:
+- Offer multiple-choice options with clear labels
+- Mark recommended defaults with "(Recommended)" in the label
+- Use `multiple: true` when the user can select several options
+- The user can always select "Other" for custom input
+
+### 3) Pause before acting
+
+Until must-have answers arrive:
+- Do not run commands, edit files, or produce a detailed plan that depends on unknowns
+- Do perform a clearly labeled, low-risk discovery step only if it does not commit you to a direction (e.g., inspect repo structure, read relevant config files)
+
+If the user explicitly asks you to proceed without answers:
+- State your assumptions as a short numbered list
+- Ask for confirmation; proceed only after they confirm or correct them
+
+### 4) Confirm interpretation, then proceed
+
+Once you have answers, restate the requirements in 1-3 sentences (including key constraints and what success looks like), then start work.
+
+## Anti-patterns
+
+- Don't ask questions you can answer with a quick, low-risk discovery read (e.g., configs, existing patterns, docs).
+- Don't ask open-ended questions if a tight multiple-choice or yes/no would eliminate ambiguity faster.
diff --git a/src/index.ts b/src/index.ts
index f3f6fa5..b27daa8 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -105,6 +105,7 @@ const SmartfrogPlugin: Plugin = async (ctx) => {
const skillTool = createSkillTool({
pluginSkills: skills,
pluginDir: PLUGIN_ROOT,
+ client: ctx.client,
})
log("[init] Plugin loaded", {
diff --git a/src/tools/skill.ts b/src/tools/skill.ts
index 3f8121f..875d100 100644
--- a/src/tools/skill.ts
+++ b/src/tools/skill.ts
@@ -2,7 +2,11 @@ import { tool, type ToolContext } from "@opencode-ai/plugin"
import { existsSync, readdirSync, readFileSync } from "node:fs"
import { join, dirname } from "node:path"
import { homedir } from "node:os"
+import type { createOpencodeClient } from "@opencode-ai/sdk"
import { parseFrontmatter, type LoadedSkill } from "../loaders"
+import { log } from "../logger"
+
+type Client = ReturnType
export interface SkillInfo {
name: string
@@ -118,18 +122,20 @@ function loadSkillContent(location: string): string {
export interface CreateSkillToolOptions {
pluginSkills: LoadedSkill[]
pluginDir: string
+ client: Client
}
export function createSkillTool(options: CreateSkillToolOptions) {
let cachedSkills: SkillInfo[] | null = null
let cachedDescription: string | null = null
+ const { client, pluginDir, pluginSkills } = options
const getSkills = (cwd: string): SkillInfo[] => {
if (cachedSkills) return cachedSkills
// Merge order: plugin defaults < global < project (later entries override earlier on name collision)
const allSkills = [
- ...pluginSkillsToInfo(options.pluginSkills, options.pluginDir),
+ ...pluginSkillsToInfo(pluginSkills, pluginDir),
...discoverClaudeGlobalSkills(),
...discoverOpencodeGlobalSkills(),
...discoverClaudeProjectSkills(cwd),
@@ -183,6 +189,18 @@ export function createSkillTool(options: CreateSkillToolOptions) {
const body = loadSkillContent(skill.location)
const dir = dirname(skill.location)
+ try {
+ await client.tui.showToast({
+ body: {
+ message: `Skill "${skill.name}" loaded`,
+ variant: "info",
+ duration: 3000,
+ },
+ })
+ } catch (error) {
+ log("[skill] Failed to show toast", { error: String(error) })
+ }
+
return [
`## Skill: ${skill.name}`,
"",
From 4f0bf7e2455aa4ec4f09224cf9eb82f43bc87abc Mon Sep 17 00:00:00 2001
From: Fred DE MATOS
Date: Thu, 15 Jan 2026 17:16:15 +0100
Subject: [PATCH 2/7] chore: release 0.9.0
---
CHANGELOG.md | 5 +++++
package.json | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6800e48..f00422c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog
+## 0.9.0
+- Add /release command to guide release workflow
+- Replace code-release skill with ask-questions skill
+- Show a toast when loading a skill
+
## 0.8.0
- Add pdf-to-markdown tool for PDF conversion
diff --git a/package.json b/package.json
index c8eceed..d7b07e9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "opencode-froggy",
- "version": "0.8.0",
+ "version": "0.9.0",
"description": "OpenCode plugin with a hook layer (tool.before.*, session.idle...), agents (code-reviewer, doc-writer), and commands (/review-pr, /commit)",
"main": "dist/index.js",
"types": "dist/index.d.ts",
From 95de5302d6fc1e9258a35f9bbab55962227c3bb3 Mon Sep 17 00:00:00 2001
From: Fred DE MATOS
Date: Sun, 18 Jan 2026 11:41:24 +0100
Subject: [PATCH 3/7] fix(command): remove redundant "Run" prefix in
commit-push command
---
command/commit-push.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/command/commit-push.md b/command/commit-push.md
index 658213b..c9370b2 100644
--- a/command/commit-push.md
+++ b/command/commit-push.md
@@ -9,7 +9,7 @@ agent: build
## Your task
-1. Run `/diff-summary` to analyze all working tree changes
+1. /diff-summary to analyze all working tree changes
2. Present a summary to the user:
- Files modified/added/deleted with stats
- Proposed commit message based on the changes
From b98975068caec0db7a0c0f10104720e679eb4f30 Mon Sep 17 00:00:00 2001
From: Fred DE MATOS
Date: Tue, 20 Jan 2026 16:08:19 +0100
Subject: [PATCH 4/7] docs: rewrite skills section with complete documentation
Replace outdated code-release reference with actual ask-questions-if-underspecified skill. Add comprehensive documentation covering discovery locations, skill creation format, and automatic activation via use_when.
---
README.md | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 81 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index 26c94a7..42d6278 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
-OpenCode plugin providing hooks, specialized agents (architect, doc-writer, rubber-duck, partner, code-reviewer, code-simplifier), skills (code-release), and tools (gitingest, pdf-to-markdown, blockchain queries, agent-promote).
+OpenCode plugin providing hooks, specialized agents (architect, doc-writer, rubber-duck, partner, code-reviewer, code-simplifier), skills (ask-questions-if-underspecified), and tools (gitingest, pdf-to-markdown, blockchain queries, agent-promote).
---
@@ -17,7 +17,11 @@ OpenCode plugin providing hooks, specialized agents (architect, doc-writer, rubb
- [Commands](#commands)
- [Agents](#agents)
- [Skills](#skills)
- - [code-release](#code-release)
+ - [Overview](#overview)
+ - [Available Skills](#available-skills)
+ - [Discovery Locations](#discovery-locations)
+ - [Creating a Skill](#creating-a-skill)
+ - [Automatic Activation](#automatic-activation)
- [Tools](#tools)
- [gitingest](#gitingest)
- [prompt-session](#prompt-session)
@@ -117,15 +121,84 @@ Shows stats overview, commits, files changed, and full diff between branches.
## Skills
-Skills are loaded on-demand to provide specialized capabilities during a session.
+Skills are contextual instructions loaded on demand via the `skill` tool. The agent invokes `skill({ name: "skill-name" })` to load the instructions when needed.
-### code-release
+### Overview
-Prepare releases with version bumps, changelog updates, and tags.
+- Skills provide specialized guidance for specific tasks
+- Instructions are loaded only when explicitly requested
+- Multiple skills can exist with the same name; the highest-priority location wins
-- **Purpose**: Guide release preparation steps and require confirmation before changing release artifacts
-- **Activation**: On user request to prepare or perform a release
-- **Constraints**: Avoid changing versions, tags, or changelogs without explicit confirmation
+### Available Skills
+
+| Skill | Description |
+|-------|-------------|
+| `ask-questions-if-underspecified` | Clarify requirements before implementing. Use when serious doubts arise. |
+
+### Discovery Locations
+
+Skills are discovered from the following locations, in order of increasing priority:
+
+| Priority | Scope | Location |
+|----------|-------|----------|
+| 1 (lowest) | plugin | `/skill/` |
+| 2 | global | `~/.config/opencode/skill/` |
+| 3 (highest) | project | `/.opencode/skill/` |
+
+If multiple skills share the same name, the one from the highest-priority location takes precedence.
+
+### Creating a Skill
+
+Each skill lives in its own directory with a `SKILL.md` file:
+
+```
+skill/
+└── my-skill/
+ └── SKILL.md
+```
+
+The `SKILL.md` file uses YAML frontmatter for metadata:
+
+```markdown
+---
+name: my-skill
+description: Short description of the skill (required)
+use_when: >
+ Condition for automatic activation (optional).
+---
+
+# Detailed Instructions
+
+Markdown content with step-by-step guidance...
+```
+
+#### Frontmatter Fields
+
+| Field | Required | Description |
+|-------|----------|-------------|
+| `name` | Yes | Unique identifier for the skill |
+| `description` | Yes | Short description (displayed in skill listings) |
+| `use_when` | No | Condition for automatic activation |
+
+A skill without `name` or `description` will be ignored.
+
+### Automatic Activation
+
+If a skill defines `use_when`, a directive is injected into the system prompt:
+
+```
+MANDATORY: Call skill({ name: "my-skill" })
+```
+
+This instructs the agent to load the skill when the specified condition is met.
+
+**What is injected:**
+- The skill `name`
+- The `use_when` text (normalized: multiple spaces collapsed to single space)
+
+**What is NOT injected:**
+- The `description`
+- The markdown content (loaded only when the skill is invoked)
---
From d7cdfefdf2b809796e9ae38016dc2925f4d629df Mon Sep 17 00:00:00 2001
From: Fred DE MATOS
Date: Thu, 22 Jan 2026 23:44:52 +0100
Subject: [PATCH 5/7] fix(command): list untracked files instead of showing
truncated content
Previously, /diff-summary and /review-changes displayed truncated content (50 lines) of untracked files.
Now they list only file paths with instruction for agents to read them directly.
This enables /simplify-changes and /review-changes to properly handle untracked files by accessing their full content.
---
command/diff-summary.md | 7 +++----
command/review-changes.md | 5 +++--
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/command/diff-summary.md b/command/diff-summary.md
index c9f8a3c..fc464a4 100644
--- a/command/diff-summary.md
+++ b/command/diff-summary.md
@@ -43,9 +43,8 @@ else
git diff
echo ""
- echo "## Untracked Files Content"
- git ls-files --others --exclude-standard | while read f; do
- [ -f "$f" ] && echo "=== $f ===" && sed -n "1,50p" "$f" && sed -n "51p" "$f" | grep -q . && echo "... (truncated)"
- done
+ echo "## Untracked Files (new)"
+ echo "These files are new and not yet tracked by git. Read them directly to see their content."
+ git ls-files --others --exclude-standard
fi
'`
diff --git a/command/review-changes.md b/command/review-changes.md
index 29e7f94..2254342 100644
--- a/command/review-changes.md
+++ b/command/review-changes.md
@@ -16,7 +16,8 @@ agent: code-reviewer
!`git diff --stat`
!`git diff`
-## Untracked Files Content
-!`bash -c 'git ls-files --others --exclude-standard | while read f; do [ -f "$f" ] && echo "=== $f ===" && sed -n "1,50p" "$f" && sed -n "51p" "$f" | grep -q . && echo "... (truncated)"; done'`
+## Untracked Files (new)
+These files are new and not yet tracked by git. Read them directly to see their content.
+!`git ls-files --others --exclude-standard`
Review the above changes for quality, correctness, and adherence to project guidelines.
From bc1c7bb0e86ee6bfb7bcc8a7bfac61bafaa7e0c7 Mon Sep 17 00:00:00 2001
From: Fred DE MATOS
Date: Sun, 25 Jan 2026 11:40:31 +0100
Subject: [PATCH 6/7] feat(agent): allow code-simplifier to read untracked
files
---
agent/code-simplifier.md | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/agent/code-simplifier.md b/agent/code-simplifier.md
index a4a56c1..e1af06e 100644
--- a/agent/code-simplifier.md
+++ b/agent/code-simplifier.md
@@ -26,6 +26,7 @@ You do not introduce new features, fix bugs, or change logic. You only improve h
### 2. Scope discipline
- Only simplify code that was **modified or introduced in the current session**.
+- This includes **untracked files** (new files not yet committed) listed in the working tree.
- Do not refactor adjacent or pre-existing code unless strictly required to simplify the modified section.
- No cross-file refactors unless the change itself spans multiple files.
@@ -61,11 +62,12 @@ Apply simplifications only when they clearly improve readability or maintainabil
## Execution process
-1. Identify code that was added or modified in the current session.
-2. Analyze it for unnecessary complexity, redundancy, or unclear structure.
-3. Apply minimal, behavior-preserving refinements.
-4. Re-check that functionality, outputs, and side effects are unchanged.
-5. Produce the simplified code.
+1. Identify code that was added or modified in the current session, **including untracked files listed in the diff**.
+2. **Read the content of untracked files** using the Read tool before analyzing them.
+3. Analyze the code for unnecessary complexity, redundancy, or unclear structure.
+4. Apply minimal, behavior-preserving refinements.
+5. Re-check that functionality, outputs, and side effects are unchanged.
+6. Produce the simplified code.
## Output requirements
From b32ed399aa665b0d95593e10e1ae942c8d2c7831 Mon Sep 17 00:00:00 2001
From: Fred DE MATOS
Date: Sun, 25 Jan 2026 11:45:25 +0100
Subject: [PATCH 7/7] docs: add example for ask-questions-if-underspecified
skill
---
README.md | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/README.md b/README.md
index 42d6278..0256cd8 100644
--- a/README.md
+++ b/README.md
@@ -135,6 +135,35 @@ Skills are contextual instructions loaded on demand via the `skill` tool. The ag
|-------|-------------|
| `ask-questions-if-underspecified` | Clarify requirements before implementing. Use when serious doubts arise. |
+#### Example: ask-questions-if-underspecified
+
+**User request:**
+> "Add authentication to the API"
+
+**Agent response (after loading the skill):**
+
+The agent recognizes this request has multiple interpretations and uses the `question` tool:
+
+```
+┌─ Authentication Approach ────────────────────────────────────────┐
+│ │
+│ Which authentication method should be implemented? │
+│ │
+│ ○ JWT tokens (Recommended) │
+│ ○ Session-based with cookies │
+│ ○ OAuth 2.0 / OpenID Connect │
+│ ○ API keys │
+│ ○ Other │
+│ │
+└──────────────────────────────────────────────────────────────────┘
+```
+
+After the user selects "JWT tokens", the agent confirms:
+
+> "I'll add JWT-based authentication to the API endpoints using the existing Express middleware pattern. Success = all `/api/*` routes require a valid token, with a `/auth/login` endpoint for token generation."
+
+Then implementation begins.
+
### Discovery Locations
Skills are discovered from the following locations, in order of increasing priority: