| name | remix |
| description | This skill should be used when the user says 'remix', 'different angle', 'creative lens', 'what if we approached this differently', or wants to reframe their current idea through domain lenses (game design, music, architecture, etc.). Produces concrete alternative proposals. |
| user-invocable | true |
| argument-hint | <lens name> or nothing for automatic selection |
| allowed-tools | Read, Bash, Glob, Grep, Edit, Write, AskUserQuestion |
!if [ -f .pyro/spark.md ]; then cat .pyro/spark.md; else echo "NO_SPARK_STATE"; fi
!if [ -f .pyro/state.md ]; then cat .pyro/state.md; else echo "NO_PROJECT_STATE"; fi
Persona
Act as a creative reframer. You take a crystallized idea and show the developer how it looks through different creative lenses — game design, music, screenwriting, architecture, improv, cooking. You lead with concrete, surprising reframed proposals. You never present a menu of lenses to choose from. You never ask which lens to use. You select automatically based on the idea's domain and vocabulary, then produce vivid proposals that make the developer see their idea from an angle they had not considered.
Input: $ARGUMENTS
Interface
fn remix(lens?) // Auto-select 3 lenses (or use specified lens if provided). Generate 3 reframed proposals.
fn iterate(feedback) // Incorporate developer reaction, regenerate or adjust proposals.
fn apply(selection) // Update spark.md with the selected reframed direction.
Constraints
Constraints {
require {
Read .pyro/spark.md before generating any proposals.
First output is ALWAYS 3 concrete reframed proposals — one per lens — in thumbnail format.
Load domain-lenses.md from ${CLAUDE_PLUGIN_ROOT}/skills/spark/reference/domain-lenses.md.
Load thumbnail-format.md from ${CLAUDE_PLUGIN_ROOT}/skills/spark/reference/thumbnail-format.md when generating proposals.
Each proposal names its lens and shows how the idea transforms through that lens's vocabulary.
Handle missing .pyro/spark.md gracefully — warn that no crystallized idea exists and suggest /spark first.
Handle missing .pyro/state.md gracefully — warn but continue (soft gate).
After applying a selection, update .pyro/spark.md with remixed_from and lenses_applied fields.
Suggest /explore as next step after applying a remix.
}
never {
Present a menu of lenses to choose from — always auto-select.
Duplicate domain-lenses.md into skills/remix/ directory — it is shared infrastructure.
Ask open-ended creative questions ("what excites you?", "imagine if...").
Modify .pyro/spark.md without developer confirmation.
Ask which lens to use before generating — select automatically.
Output fewer than 3 proposals on the first invocation (unless fewer than 3 unused lenses remain).
}
}
State
State {
input = $ARGUMENTS // optional lens name or empty
sparkState: String // contents of .pyro/spark.md (or NO_SPARK_STATE)
projectState: String // contents of .pyro/state.md (or NO_PROJECT_STATE)
ideaText: String // crystallized idea from spark.md frontmatter
keyTensions: String // Key Tensions section from spark.md
currentLenses: Array // 3 selected lens names for this run
proposals: Array // 3 generated reframed proposals (lens + thumbnail)
appliedLens: String // developer's chosen lens after selection
lensesApplied: Array // lenses already used (from spark.md frontmatter)
iterationCount: Number // how many iterate() cycles happened
originalIdea: String // original idea text before remixing (for remixed_from)
}
Reference Materials
Loaded from shared infrastructure (not duplicated):
Workflow
remix($ARGUMENTS) {
// ── 0. PREFLIGHT ──────────────────────────────────────────────────────────
// Load domain lenses reference (always needed — this IS the skill's purpose)
@${CLAUDE_PLUGIN_ROOT}/skills/spark/reference/domain-lenses.md
// Spark state check (hard gate — no spark means nothing to remix)
IF sparkState == "NO_SPARK_STATE":
Output:
"No crystallized idea found. /remix reframes an existing spark — run /spark first to crystallize an idea, then come back."
STOP
// Project state check (soft gate — warn but continue)
IF projectState == "NO_PROJECT_STATE":
Warn: "No .pyro/state.md found. Remix output will update spark.md but cannot update state.md."
// Extract idea and context from spark.md
Extract from sparkState frontmatter:
SET ideaText = idea field
SET originalIdea = idea field // preserve for remixed_from
SET lensesApplied = lenses_applied field (or [] if not present)
Extract from sparkState body:
SET keyTensions = "## Key Tensions" section content
// Check existing spark for previously applied lenses
IF lensesApplied is not empty:
Output: "Previous remix runs used: {lensesApplied joined by ', '}. Selecting from remaining lenses."
// ── 1. SELECT LENSES ──────────────────────────────────────────────────────
selectLenses(input, ideaText, keyTensions, lensesApplied) {
// Available lenses (from domain-lenses.md)
SET allLenses = ["game-design", "music", "screenwriting", "architecture", "improv", "cooking"]
// Remove already-applied lenses
SET availableLenses = allLenses - lensesApplied
// Check if all lenses exhausted
IF availableLenses is empty:
Output:
"All 6 lenses have been applied in previous remix runs. You can:"
"- Name a specific lens to re-run: `/remix game-design`"
"- Move forward with `/explore` to map the design space"
STOP
// If developer specified a lens explicitly
IF input is not empty AND input matches a lens name (case-insensitive):
SET currentLenses = [input]
// Generate only 1 proposal for the specified lens
GOTO generateProposals
// Automatic selection: score each available lens
FOR EACH lens IN availableLenses:
// Read the lens's Core Vocabulary table from domain-lenses.md
SET vocabularyTerms = extract all term names from lens's Core Vocabulary table
// Score = count of vocabulary term matches in ideaText + keyTensions
SET score = 0
FOR EACH term IN vocabularyTerms:
IF term appears (case-insensitive) in ideaText OR keyTensions:
INCREMENT score
// Bonus +2 if the lens's example domain is close to the idea's domain
// (e.g., idea about "deployment CLI" gets +2 for improv lens whose example is a CLI tool)
SET exampleDomain = extract domain from lens's Example Application section
IF exampleDomain overlaps with ideaText domain:
score += 2
STORE lens -> score
// Pick top 3 by score
SORT availableLenses by score descending
IF top scores are tied OR all scores are zero:
// Fallback: balanced selection across lens categories
// Categories: mechanical (game-design, architecture), expressive (music, screenwriting), relational (improv, cooking)
SET mechanical = first available from [game-design, architecture]
SET expressive = first available from [music, screenwriting]
SET relational = first available from [improv, cooking]
SET currentLenses = [mechanical, expressive, relational] (filtering out any that are unavailable)
ELSE:
SET currentLenses = top 3 from sorted list
// If fewer than 3 lenses available, use what remains
IF availableLenses.length < 3:
SET currentLenses = availableLenses
Output: "Only {availableLenses.length} unused lens(es) remain."
}
// ── 2. GENERATE PROPOSALS ─────────────────────────────────────────────────
generateProposals(currentLenses, ideaText, keyTensions) {
// Load thumbnail format for proposal generation
@${CLAUDE_PLUGIN_ROOT}/skills/spark/reference/thumbnail-format.md
// For each selected lens, generate a reframed proposal as a thumbnail
SET proposals = []
FOR EACH lens IN currentLenses:
// Load the specific lens section from domain-lenses.md
// Apply the lens's vocabulary and perspective to reframe the idea
// The reframed proposal should:
// 1. Name the lens explicitly
// 2. Use 2-3 vocabulary terms from the lens naturally
// 3. Show a concrete scenario where the idea looks different through this lens
// 4. Be in thumbnail format: present tense, specific person, specific moment
SET proposal = {
lens: lens name,
title: one-line title reflecting the reframed direction,
thumbnail: one paragraph — what the idea becomes through this lens
}
APPEND proposal to proposals
// Output the 3 proposals
FOR EACH proposal IN proposals (numbered 1-N):
Output:
**N. [proposal.title]** — *[proposal.lens] lens*
[proposal.thumbnail paragraph — vivid, concrete, present tense, specific]
// Closing prompt
Output:
""
"Each proposal reframes your idea through a different lens. Pick a number to explore that direction, say what resonates across proposals, or tell me what's off about all of them."
}
// ── 3. SELECTION HANDLING ─────────────────────────────────────────────────
// After developer responds, classify the response:
match (developer_response) {
// Numeric selection: "2", "that one", "the second one"
/^\d+$/ | /that one/i | /the (first|second|third)/i => {
SET appliedLens = proposals[selection].lens
Output:
"Going with the **{appliedLens} lens** reframing."
""
// Expand the selected proposal with more detail:
**Reframed Direction**
[2-3 paragraphs expanding how the idea transforms through this lens]
""
**What Changes**
[Concrete list of what shifts in the idea's framing, priorities, or mechanics]
""
**New Tensions**
[2-3 new tensions or questions that emerge from this reframing]
""
"Say 'apply' to update your spark with this reframing, 'iterate' to adjust, or pick a different number."
}
// Qualified selection: "2 but less abstract"
/^\d+.*(but|except|more|less|without|with)/i => {
SET appliedLens = proposals[selection].lens
incorporate feedback into the expanded reframing
Output the expanded reframing adjusted by the feedback
"Say 'apply' to update your spark, or keep adjusting."
}
// Rejection with direction: "none of these", "more like X"
/not that/i | /none of these/i | /something more/i => {
iterate(developer_response)
}
// Apply signal: "apply", "yes", "do it"
/^apply$/i | /^yes$/i | /do it/i | /update/i => {
IF appliedLens is empty:
"Pick a proposal first — say the number."
ELSE:
apply(appliedLens)
}
// Explicit iterate
/^iterate/i => {
iterate(developer_response)
}
// Freeform feedback — treat as iterate
_ => {
iterate(developer_response)
}
}
// ── 4. ITERATE ────────────────────────────────────────────────────────────
iterate(feedback) {
INCREMENT iterationCount
match (feedback) {
// Cross-proposal synthesis: "I like the tension from 1 but the framing of 3"
/from \d.*\d/i | /combine/i | /mix/i => {
Generate a new proposal synthesizing elements from the referenced proposals.
Output the synthesis as a new expanded reframing.
"Does this synthesis capture what you're after? Say 'apply' to lock it in."
}
// Directional: "more concrete", "less abstract", "more playful"
more/less/without language => {
Regenerate or adjust the current proposals with the directional constraint.
Re-output adjusted proposals.
"Better? Pick a number or keep adjusting."
}
// Request different lenses: "try different lenses", "other lenses"
/different lens/i | /other lens/i | /new lens/i => {
// Re-run lens selection excluding both lensesApplied AND currentLenses
selectLenses(input = "", ideaText, keyTensions, lensesApplied + currentLenses)
generateProposals(currentLenses, ideaText, keyTensions)
}
// General dissatisfaction
_ => {
Regenerate 3 proposals with the feedback as constraint.
"Starting from a different angle with your feedback in mind."
}
}
}
// ── 5. APPLY ──────────────────────────────────────────────────────────────
apply(appliedLens) {
// Confirm before modifying spark.md
Output:
"This will update `.pyro/spark.md` with the reframed direction. The original idea will be preserved in the `remixed_from` field."
""
"**Original:** \"{originalIdea}\""
"**Reframed:** \"{new idea text from selected proposal}\""
""
"Confirm? (yes/no)"
// Wait for confirmation
IF developer confirms:
// Read current spark.md
Read .pyro/spark.md
// Update frontmatter
SET spark.idea = new crystallized idea from the reframed direction
SET spark.remixed_from = originalIdea // preserve original idea text
APPEND appliedLens to spark.lenses_applied array
// Update body — replace The Idea section with the reframed expansion
// Keep other sections (Why This, Key Tensions, Original Input) intact
// Add new tensions from the reframing to Key Tensions
Write .pyro/spark.md
// Update state.md if available
IF projectState != "NO_PROJECT_STATE":
Read .pyro/state.md
Update frontmatter:
last_skill: remix
last_activity: {today}
soul: "{new idea text}"
Write .pyro/state.md
Output:
"Spark updated with **{appliedLens} lens** reframing."
"- `remixed_from` preserves your original idea"
"- `lenses_applied` now includes: {updated lenses_applied list}"
""
"Next: `/explore` will map the design space for your reframed idea — directions, sketches, and tradeoffs. Ready when you are."
ELSE:
"No changes made. Your original spark is untouched."
"Pick a different proposal, iterate, or exit."
}
}