# Idea

> Capture a new product idea / feature concept / internal tool proposal to the ideas backlog (pre-triage).

- Skill: `me2resh/idea` (Agent Skill)
- Install (CLI): `npx skillmds@latest add me2resh/idea`
- Raw SKILL.md: https://api.skillmd.com/api/skills/me2resh/idea/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Product & Planning
- Author: me2resh (https://skillmd.com/u/me2resh)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/me2resh/idea

---


# /idea — Submit a New Product Idea

Read `.claude/rules/writing-standard.md`. Use the **controlled technical writing profile** for the idea
record: state the opportunity plainly and preserve uncertainty.

Capture a new product, feature, or internal-tool idea so it lands somewhere durable instead of evaporating in chat. This skill is intentionally lightweight: it adds an entry to the ideas backlog and (optionally) creates a tracking GitHub Issue. It does **not** replace `/write-spec` — that comes later, after the idea has been triaged.

## Path resolution

Read the registry path via `portfolio_registry`, the per-project docs dir via `portfolio_projects_dir`, and the ideas backlog via `portfolio_ideas_backlog` — all from `.claude/hooks/_lib-portfolio-paths.sh`. Source the helper at the top of any bash block that touches those paths:

```bash
source "$(git rev-parse --show-toplevel)/.claude/hooks/_lib-read-config.sh"
source "$(git rev-parse --show-toplevel)/.claude/hooks/_lib-portfolio-paths.sh"
registry=$(portfolio_registry)
```

Defaults match today's single-fork layout (`./apexyard.projects.yaml`, `./projects`, `./projects/ideas-backlog.md`). Adopters in split-portfolio mode override the `portfolio.{registry, projects_dir, ideas_backlog}` keys in `.claude/project-config.json`. Don't hardcode literal `apexyard.projects.yaml` or `projects/` paths in bash blocks — the helper resolves whichever mode the adopter is in. See `docs/multi-project.md`.

## Usage

```
/idea Auto-tag inbound emails by intent
/idea Internal CLI for resetting staging data
/idea New product: AI design system linter
```

## Where the entry goes

Every idea lands in `projects/ideas-backlog.md` at the root of your ops repo (your fork of apexyard). One shared backlog for every project — triage decides which project ends up owning a given idea.

If the file doesn't exist yet, create it with a header and a table.

## Process

### 0. Write the active-issue-skill marker (REQUIRED — me2resh/apexyard#268)

Before any `gh issue create` (or other tracker CLI), write this skill's name to the active-issue-skill marker so `require-skill-for-issue-create.sh` lets the command through. At skill entry:

```bash
# Resolve the ops-fork root the SAME way the hooks do (_lib-ops-root.sh):
# anchor on the .apexyard-fork marker (split-portfolio v2 — onboarding.yaml
# lives in the sibling portfolio repo, NOT the ops fork), falling back to the
# onboarding.yaml + apexyard.projects.yaml pair (single-fork v1).
ops_root="$PWD"; r="$PWD"
while [ "$r" != / ]; do
  if [ -f "$r/.apexyard-fork" ] || { [ -f "$r/onboarding.yaml" ] && [ -f "$r/apexyard.projects.yaml" ]; }; then
    ops_root="$r"; break
  fi
  r=${r%/*}
done
mkdir -p "$ops_root/.claude/session"
echo "idea" > "$ops_root/.claude/session/active-issue-skill"
```

Remove the marker on **every** exit path (success, early-exit, user cancel, error):

```bash
rm -f "$ops_root/.claude/session/active-issue-skill"
```

The `clear-issue-skill-marker.sh` SessionStart hook sweeps stale markers from killed sessions, but a clean exit should never leave one behind. See AgDR-0030.

### 1. Parse the title

Take the title from `$ARGUMENTS`. If empty, ask:

```
What's the idea? Give me a short title (1 line).
```

### 2. Gather metadata

Ask conversationally (one question at a time, don't batch):

**Category** — must be one of four values. Present numbered options and **re-prompt on invalid input**:

```
Category?
  1. New Product
  2. Feature
  3. Internal Tool
  4. Process
>
```

Accept `1`, `2`, `3`, `4` or the corresponding word (case-insensitive). On anything else, say `Please pick 1-4 or type the category name.` and re-ask. Loop until valid — do **not** silently accept garbage.

**Submitter** — who's proposing it. Default to the current git user (`git config user.name`). If the user wants to override, accept their input as-is.

**One-line description** — what would it do? Who's it for? If empty, re-prompt: `Give me one sentence about what this idea does.` Loop until non-empty.

Don't go deeper than that — this is a lightweight capture, not a spec.

### 3. Check for duplicates

Before computing an ID or appending anything, fuzzy-match the title against existing backlog entries:

```bash
# Normalise a title: lowercase, strip punctuation, collapse whitespace
normalise() { echo "$1" | tr '[:upper:]' '[:lower:]' | tr -d '[:punct:]' | tr -s ' '; }

# Extract existing titles from the backlog table
grep -E '^\| IDEA-[0-9]+ \|' projects/ideas-backlog.md 2>/dev/null \
  | awk -F'|' '{print $3}' \
  | sed 's/^ *//;s/ *$//'
```

Compare the normalised new title against every normalised existing title using a simple token-overlap heuristic: if ≥ 80% of the words in the shorter title appear in the longer one, flag as a potential duplicate.

If a potential match is found:

```
⚠ Similar idea already in the backlog:
  IDEA-025 — {existing title} (status: {status})

Is this a duplicate? (y = skip, n = add anyway)
>
```

- `y` → skip the append, return without logging anything new, suggest `/write-spec IDEA-025` if the user wants to work on the existing idea
- `n` → continue to step 4

If no match is found, continue silently to step 4.

### 4. Compute the next ID

```bash
# Find the highest existing IDEA-NNN in the backlog file
grep -oE 'IDEA-[0-9]+' <backlog-file> 2>/dev/null | sort -V | tail -1
# Increment by 1, or start at IDEA-001 if none exist
```

### 5. Append the entry

If the backlog file doesn't exist, create it with this header:

```markdown
# Ideas Backlog

Lightweight capture of product ideas, feature concepts, and internal tool proposals.
Use `/idea` to add a new entry. Triage moves entries into `/write-spec`, then into a GitHub Issue.

| ID | Title | Category | Submitter | Date | Status | Description |
|----|-------|----------|-----------|------|--------|-------------|
```

Append a new row:

```markdown
| IDEA-NNN | {title} | {category} | {submitter} | YYYY-MM-DD | NEW | {one-line description} |
```

### 6. Offer the tracking issue

After the entry is appended, ask:

```
Would you like me to create a tracking GitHub Issue for IDEA-NNN? (y/n)
```

If the user says no, skip this step entirely — the backlog entry is already saved, and that's enough.

If yes, resolve the idea body template via the portfolio helper so adopter overrides win when present:

```bash
source "$(git rev-parse --show-toplevel)/.claude/hooks/_lib-read-config.sh"
source "$(git rev-parse --show-toplevel)/.claude/hooks/_lib-portfolio-paths.sh"
template=$(portfolio_resolve_template tickets/idea.md)   # → custom-templates/tickets/idea.md if present, else templates/tickets/idea.md
```

Single-fork adopters (no `portfolio` block) and adopters with no override fall straight through to `templates/tickets/idea.md`. Adopters who want a customised idea-tracking-issue shape drop their version at `<private_repo>/custom-templates/tickets/idea.md`. See `templates/README.md` for the path-mirroring convention.

**Backward-compat fallback**: if `portfolio_resolve_template` returns empty (template file missing — partial adopter setup), fall back to the inline heredoc body below and print a one-line WARN on stderr (`WARN: tickets/idea.md template missing — using inline fallback`).

Substitute the gathered values into the resolved template (or the fallback heredoc below), then create with the `enhancement` and `idea` labels (creating the labels if needed):

```bash
gh issue create \
  --title "[Idea] {title}" \
  --body "$(cat <<'EOF'
## Idea
{one-line description}

## Category
{category}

## Submitter
{submitter}

## Backlog Entry
IDEA-NNN — see backlog file.

## Next Step
Triage. Decide whether to spec, schedule, or close.

## Glossary
| Term | Definition |
|------|------------|
| {term} | {definition} |
EOF
)" \
  --label "idea,needs-triage"
```

**Error handling** — if `gh issue create` fails for any reason (missing auth, labels don't exist, network error, rate limit), catch the error and fall back gracefully:

```
⚠ Couldn't create the tracking issue: {reason}
  The idea is still saved in projects/ideas-backlog.md as IDEA-NNN.

  Try again? (y = retry, n = skip, gh = show the gh error for debugging)
>
```

Common failure modes and what to do:

| Failure | Action |
|---------|--------|
| `could not resolve repository` | Ask the user which repo to file the issue in; the backlog entry was already saved |
| `missing scope: issues:write` | Tell the user to run `gh auth refresh -s issues` and offer to retry |
| `label "idea" not found` | Create the label first (`gh label create idea`) then retry |
| `repository has disabled issues` (#653) | GitHub Issues is off on the repo. Surface the fix: `gh repo edit <owner/repo> --enable-issues` (needs admin), or set `tracker.kind` to your real tracker. Reuse `tracker_check_issues` from `_lib-tracker.sh` to print the hint. The backlog entry is already saved. |
| `HTTP 403 rate-limited` | Offer to retry after a short wait |
| Any other error | Show the raw `gh` output, skip the tracking issue, keep the backlog entry |

The guiding principle: **the backlog entry is the primary artefact; the tracking issue is a bonus**. Never lose the backlog entry because the GitHub Issue creation failed.

If the issue is created successfully, append the issue URL to the backlog row's Description column as `(GH#NN)`.

### 7. Offer validation (optional, default-no)

After the GitHub Issue step (whether the user accepted or skipped it), ask:

```
Validate now? Run /validate-idea IDEA-NNN — y/n (default n)
```

Default-no respects the lightweight-capture intent of `/idea`. Most users batch-validate later. If the user accepts, hand off to `/validate-idea IDEA-NNN`; if they skip, proceed to step 8.

## Output

```
Captured: IDEA-NNN — {title}
Backlog: {file path}
Status: NEW
Tracking issue: {url or "skipped"}
Validation: {"completed — verdict <GREEN|YELLOW|RED>" | "skipped (run /validate-idea IDEA-NNN later)"}

Next: triage with the team, then `/write-spec` if it survives.
```

## Rules

1. **Lightweight only** — `/idea` captures, it does not spec. Don't ask for goals, metrics, or requirements here.
2. **Always assign an ID** — `IDEA-NNN`, zero-padded to 3 digits.
3. **One row per idea** — never edit existing rows from this skill; new ideas always append.
4. **Status starts at NEW** — triage changes it later.
5. **Single backlog** — every idea goes into `projects/ideas-backlog.md` at the root of the ops repo; triage assigns it to a project later.
6. **Validate before accepting** — category must be 1-4; description must be non-empty. Loop until valid; never silently accept garbage.
7. **Dedup before appending** — fuzzy-match the title against existing entries; flag and confirm before creating a second entry for the same idea.
8. **The backlog is the primary artefact** — if the tracking issue fails to create, the backlog entry still stands. Never lose data because GitHub was flaky.
9. **Don't create the issue silently** — always ask first.
10. **Never delete** — superseded ideas get status `SUPERSEDED`, not removal.

## Status values

| Status | Meaning |
|--------|---------|
| NEW | Just captured, not triaged |
| TRIAGED | Reviewed, awaiting decision |
| SPECCED | `/write-spec` produced a PRD |
| SHIPPED | Built and released |
| WONTDO | Triaged out — not pursuing |
| SUPERSEDED | Replaced by a different idea |

---

*Part of [ApexYard](https://github.com/me2resh/apexyard) — multi-project SDLC framework for Claude Code · MIT.*

