Create evidence-based spaced repetition flashcards using cognitive science principles from Andy Matuschak's research. Use when user wants to create Mochi cards, flashcards, study materials, or mentions learning, memorization, spaced repetition, SRS, Anki-style cards, or knowledge retention. Applies the 5 properties of effective prompts (focused, precise, consistent, tractable, effortful) to ensure cards actually work for long-term retention.
Creates evidence-based flashcards in Mochi using cognitive science principles for long-term retention. Use when user wants to create study materials, mentions spaced repetition, Anki-style cards, or learning new concepts.
/plugin marketplace add JoshuaOliphant/claude-plugins/plugin install mochi-creator@oliphant-pluginsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/mochi_api_reference.mdreferences/prompt_design_principles.mdscripts/mochi_api.pytemplates/knowledge_type_templates.mdThis skill enables creation and management of flashcards, decks, and templates in Mochi.cards, a spaced repetition learning system. Critically, this skill applies evidence-based cognitive science principles to ensure flashcards actually work for long-term retention.
Core Philosophy: Writing prompts for spaced repetition is task design. You're creating recurring retrieval tasks for your future self. Effective prompts leverage retrieval practice - actively recalling information strengthens memory far more than passive review.
Use this skill to transform content into study materials, organize learning resources into deck hierarchies, and create cards that are focused, precise, consistent, tractable, and effortful.
Before using this skill, set the Mochi API key as an environment variable:
export MOCHI_API_KEY="your_api_key_here"
To obtain an API key:
The scripts/mochi_api.py script provides a complete Python interface to the Mochi API. Import and use it in Python code:
from scripts.mochi_api import MochiAPI
# Initialize the client (reads MOCHI_API_KEY from environment)
api = MochiAPI()
# Create a deck
deck = api.create_deck(name="Python Programming")
# Create a card in that deck
card = api.create_card(
content="# What is a list comprehension?\n---\nA concise way to create lists in Python",
deck_id=deck["id"],
manual_tags=["python", "syntax"]
)
Or execute it directly from command line for testing:
python scripts/mochi_api.py list-decks
python scripts/mochi_api.py create-deck "My Study Deck"
python scripts/mochi_api.py list-cards <deck-id>
CRITICAL: Before creating any flashcard, understand what makes prompts effective. Bad prompts waste time and fail to build lasting memory. Great prompts compound learning over years.
Every prompt you create must satisfy these five properties (based on Andy Matuschak's research):
Focused: One detail at a time
Precise: Specific questions demand specific answers
Consistent: Should produce the same answer each time
Tractable: You should answer correctly ~90% of the time
Effortful: Must require actual memory retrieval, not trivial inference
Write 3-5 focused prompts instead of 1 comprehensive prompt.
This feels unnatural initially. You'll want to economize. Resist this urge.
Example transformation:
❌ One unfocused prompt:
Q: What are the ingredients in chicken stock?
A: Chicken bones, onions, carrots, celery, bay leaves, water
✅ Six focused prompts:
Q: What protein source forms the base of chicken stock?
A: Chicken bones
Q: What three vegetables form the aromatic base of chicken stock?
A: Onions, carrots, celery (mirepoix)
Q: What herb is traditionally added to chicken stock?
A: Bay leaves
Q: What liquid comprises the majority of chicken stock?
A: Water
Q: What is the French term for the onion-carrot-celery base?
A: Mirepoix
Q: What ratio of vegetables to liquid is typical in stock?
A: Roughly 1:4 (vegetables to water)
Notice: Each prompt lights a specific "bulb" in your understanding. The unfocused version leaves bulbs unlit.
Only create prompts about material that genuinely matters to you.
Ask yourself: "Do I actually care about remembering this in six months? Why?"
Binary prompts (yes/no questions)
Pattern-matching prompts (answerable by syntax recognition)
Unfocused prompts (multiple details)
Vague prompts (imprecise questions)
Trivial prompts (no retrieval required)
Before creating each card, verify:
If any checkbox fails, revise before creating the card.
For basic question-and-answer flashcards, create cards with markdown content using --- to separate card sides.
Example user requests:
Implementation approach:
decks = api.list_decks()
# Or create new deck
deck = api.create_deck(name="Python Programming")
deck_id = deck["id"]
content = """# What are Python decorators?
---
Functions that modify the behavior of other functions or methods.
They use the @decorator syntax above function definitions.
Example:
@staticmethod
def my_function():
pass
"""
card = api.create_card(
content=content,
deck_id=deck_id,
manual_tags=["python", "functions", "decorators"]
)
Multi-card creation from text:
When creating multiple cards from a document or conversation:
For structured, repeatable card formats (vocabulary, definitions, examples), use templates with fields.
Example user requests:
Implementation approach:
# Create a new template
template = api.create_template(
name="Vocabulary Card",
content="# << Word >>\n\n**Definition:** << Definition >>\n\n**Example:** << Example >>",
fields={
"word": {
"id": "word",
"name": "Word",
"type": "text",
"pos": "a"
},
"definition": {
"id": "definition",
"name": "Definition",
"type": "text",
"pos": "b",
"options": {"multi-line?": True}
},
"example": {
"id": "example",
"name": "Example",
"type": "text",
"pos": "c",
"options": {"multi-line?": True}
}
}
)
card = api.create_card(
content="", # Content can be empty when using fields
deck_id=deck_id,
template_id=template["id"],
fields={
"word": {
"id": "word",
"value": "ephemeral"
},
"definition": {
"id": "definition",
"value": "Lasting for a very short time; temporary"
},
"example": {
"id": "example",
"value": "The beauty of cherry blossoms is ephemeral, lasting only a few weeks."
}
}
)
Reusing existing templates:
templates = api.list_templates()
for template in templates["docs"]:
print(f"{template['name']}: {template['id']}")
template = api.get_template(template_id)
field_ids = list(template["fields"].keys())
Organize cards into hierarchical deck structures for better content organization.
Example user requests:
Implementation approach:
Creating decks:
# Top-level deck
deck = api.create_deck(
name="Programming",
sort=1
)
# Nested subdeck
subdeck = api.create_deck(
name="Python",
parent_id=deck["id"],
sort=1
)
Listing decks:
result = api.list_decks()
for deck in result["docs"]:
parent = f" (under {deck.get('parent-id', 'root')})" if deck.get("parent-id") else ""
print(f"{deck['name']}: {deck['id']}{parent}")
# Handle pagination if needed
if result.get("bookmark"):
next_page = api.list_decks(bookmark=result["bookmark"])
Updating deck properties:
# Archive a deck
api.update_deck(deck_id, archived=True)
# Change deck display settings
api.update_deck(
deck_id,
cards_view="grid",
sort_by="updated-at",
show_sides=True
)
# Reorganize deck hierarchy
api.update_deck(deck_id, parent_id=new_parent_id)
Deck organization strategies:
sort field numerically to control deck orderingarchived? to hide decks from active reviewCreate multiple cards efficiently from source materials like notes, documents, or conversations.
Example user requests:
Implementation approach:
def create_cards_from_list(items, deck_id, template_id=None):
"""Create multiple cards with error handling."""
results = {"success": [], "failed": []}
for item in items:
try:
if template_id:
card = api.create_card(
content="",
deck_id=deck_id,
template_id=template_id,
fields=item["fields"]
)
else:
card = api.create_card(
content=item["content"],
deck_id=deck_id,
manual_tags=item.get("tags", [])
)
results["success"].append(card["id"])
except Exception as e:
results["failed"].append({"item": item, "error": str(e)})
return results
Content extraction strategies:
Different types of knowledge require different prompt strategies. Always apply the 5 properties, but adapt your approach based on what you're learning.
Characteristics: Names, dates, definitions, ingredients, components
Strategy: Break into atomic units, write more prompts than feels natural
Example - Learning Recipe Components:
❌ Poor approach:
api.create_card(
content="# What ingredients are in chocolate chip cookies?\n---\nFlour, butter, sugar, brown sugar, eggs, vanilla, baking soda, salt, chocolate chips",
deck_id=deck_id
)
✅ Better approach - Create 5-8 focused cards:
facts = [
("What is the primary dry ingredient in chocolate chip cookies?", "Flour"),
("What fat is used in chocolate chip cookies?", "Butter"),
("What two sweeteners are used in chocolate chip cookies?", "White sugar and brown sugar"),
("What provides structure in chocolate chip cookies?", "Eggs"),
("What flavoring extract is used in chocolate chip cookies?", "Vanilla"),
("What leavening agent makes cookies rise?", "Baking soda"),
("What balances sweetness in cookies?", "Salt"),
]
for question, answer in facts:
api.create_card(
content=f"# {question}\n---\n{answer}",
deck_id=deck_id,
manual_tags=["baking", "cookies", "recipes"]
)
Key principle: Each card lights one specific "bulb" of understanding
Closed lists (fixed members like "7 continents"):
Open lists (evolving categories like "design patterns"):
Implementation:
# Closed list - continents
continents = ["Africa", "Antarctica", "Asia", "Australia", "Europe", "North America", "South America"]
for i, continent in enumerate(continents):
others = ", ".join([c for j, c in enumerate(continents) if j != i])
api.create_card(
content=f"# Name all 7 continents\n---\n{others}, __{continent}__ (fill in the blank)",
deck_id=deck_id,
pos=chr(97 + i) # 'a', 'b', 'c', etc. for ordering
)
# Open list - design patterns
patterns = [
("Observer", "Behavioral"),
("Factory", "Creational"),
("Adapter", "Structural"),
]
for pattern, category in patterns:
api.create_card(
content=f"# What category does the {pattern} pattern belong to?\n---\n{category} patterns",
deck_id=deck_id,
manual_tags=["design-patterns", category.lower()]
)
Characteristics: Principles, theories, mental models, frameworks
Strategy: Use multiple "lenses" to trace the edges of a concept
The Five Conceptual Lenses:
Example - Learning "Dependency Injection":
concept = "dependency injection"
deck_id = get_or_create_deck("Software Design Patterns")
# Lens 1: Attributes
api.create_card(
content="# What is the core attribute of dependency injection?\n---\nDependencies are provided from outside rather than created internally",
deck_id=deck_id,
manual_tags=["dependency-injection", "attributes"]
)
# Lens 2: Similarities/Differences
api.create_card(
content="# How does dependency injection differ from service locator?\n---\nDI pushes dependencies in, service locator pulls them out",
deck_id=deck_id,
manual_tags=["dependency-injection", "comparison"]
)
# Lens 3: Parts/Wholes
api.create_card(
content="# Give one concrete example of dependency injection\n---\nPassing a database connection to a class constructor instead of creating it inside the class",
deck_id=deck_id,
manual_tags=["dependency-injection", "examples"]
)
# Lens 4: Causes/Effects
api.create_card(
content="# What problem does dependency injection solve?\n---\nMakes code testable by allowing mock dependencies to be injected",
deck_id=deck_id,
manual_tags=["dependency-injection", "benefits"]
)
# Lens 5: Significance
api.create_card(
content="# When would you use dependency injection in your work?\n---\nWhen writing testable APIs that need to swap database implementations or mock external services",
deck_id=deck_id,
manual_tags=["dependency-injection", "application"]
)
Key principle: Multiple angles create robust understanding resistant to forgetting
Characteristics: Processes, workflows, algorithms, techniques
Strategy: Focus on transitions, timing, and rationale (not rote steps)
Anti-pattern: Don't create "step 1, step 2, step 3" cards - this encourages rote memorization
Better approach: Focus on:
Example - Learning "How to Make Sourdough Bread":
❌ Poor approach (rote steps):
# Don't do this!
api.create_card(
content="# What is step 1 in making sourdough?\n---\nMix flour and water",
deck_id=deck_id
)
api.create_card(
content="# What is step 2 in making sourdough?\n---\nLet it autolyse for 30 minutes",
deck_id=deck_id
)
# ... etc - encourages mindless recitation
✅ Better approach (transitions and rationale):
# Focus on transitions
api.create_card(
content="# When do you know the autolyse phase is complete?\n---\nAfter 30-60 minutes when flour is fully hydrated",
deck_id=deck_id,
manual_tags=["sourdough", "transitions"]
)
# Focus on rationale
api.create_card(
content="# Why do you autolyse before adding salt?\n---\nSalt inhibits gluten development; autolyse allows gluten to form first",
deck_id=deck_id,
manual_tags=["sourdough", "rationale"]
)
# Focus on timing/heads-up
api.create_card(
content="# How long does bulk fermentation take for sourdough?\n---\n4-6 hours at room temperature (temperature-dependent)",
deck_id=deck_id,
manual_tags=["sourdough", "timing"]
)
# Focus on conditions
api.create_card(
content="# What indicates sourdough is ready for shaping?\n---\n50-100% volume increase, jiggly texture, small bubbles on surface",
deck_id=deck_id,
manual_tags=["sourdough", "conditions"]
)
Key principle: Understand the why and when, not just the what
Purpose: Keep ideas "top of mind" to drive actual application, not just retention
Use when: You want to change behavior or apply knowledge, not just remember facts
Strategy: Create prompts around contexts where ideas might be meaningful
Example - Applying "First Principles Thinking":
# Context-based application
api.create_card(
content="# What's one situation this week where you could apply first principles thinking?\n---\n(Give an answer specific to your current work context - answer may vary)",
deck_id=deck_id,
manual_tags=["first-principles", "application"],
review_reverse=False # Don't review in reverse
)
# Implication-focused
api.create_card(
content="# What's one assumption you're making in your current project that could be questioned?\n---\n(Identify a specific assumption - answer will vary)",
deck_id=deck_id,
manual_tags=["first-principles", "reflection"]
)
# Creative application
api.create_card(
content="# Describe a way to apply first principles thinking you haven't mentioned before\n---\n(Novel answer each time - leverages generation effect)",
deck_id=deck_id,
manual_tags=["first-principles", "creative"]
)
Key principle: Extend the "Baader-Meinhof effect" where new knowledge feels salient and you notice it everywhere
Warning: Salience prompts are experimental. Standard retrieval prompts have stronger research backing.
Guide users through card creation with clarifying questions when details are ambiguous. Critically, always validate quality before creating cards.
Example user requests:
Implementation approach:
First, establish emotional connection:
Determine information needed:
Before creating ANY card, apply quality validation:
Suggest knowledge-type appropriate patterns:
Create cards with quality commentary:
# Show your reasoning
print("Creating focused card: Tests ONE detail (what problem DI solves)")
print("Precise: Asks specifically about testability benefit")
print("Tractable: You should get this right ~90% of the time")
api.create_card(
content="# What problem does dependency injection solve?\n---\nMakes code testable by allowing mock dependencies",
deck_id=deck_id,
manual_tags=["design-patterns", "dependency-injection"]
)
Offer iteration and refinement:
Flag quality issues proactively:
Quality-First Workflow:
def create_card_with_validation(question: str, answer: str, deck_id: str) -> None:
"""Always validate before creating."""
# Check 1: Focused?
if " and " in question or len(answer.split(",")) > 2:
print("⚠️ This prompt seems unfocused. Consider breaking into separate cards.")
return
# Check 2: Precise?
vague_words = ["interesting", "important", "good", "tell me about"]
if any(word in question.lower() for word in vague_words):
print("⚠️ Question is vague. Be more specific about what you're asking.")
return
# Check 3: Binary?
if question.strip().startswith(("Is ", "Does ", "Can ", "Will ")):
print("⚠️ Binary question detected. Rephrase as open-ended.")
return
# Check 4: Pattern-matchable?
if len(question) > 200:
print("⚠️ Question is very long - might be answerable by pattern matching.")
return
# Validation passed - create the card
api.create_card(
content=f"# {question}\n---\n{answer}",
deck_id=deck_id
)
print("✅ Card created (passed quality checks)")
Remember: Your job is to help create cards that work - not just cards that exist. Push back on poor quality prompts.
Control card order within decks using the pos field with lexicographic sorting:
# Cards sort lexicographically by pos field
card1 = api.create_card(content="First card", deck_id=deck_id, pos="a")
card2 = api.create_card(content="Third card", deck_id=deck_id, pos="c")
# Insert between existing cards
card_between = api.create_card(content="Second card", deck_id=deck_id, pos="b")
Tags can be added inline in content or via manual_tags:
# Inline tags in content
content = "# What is Python?\n---\nA programming language #python #programming"
# Manual tags (preferred for programmatic creation)
card = api.create_card(
content="# What is Python?\n---\nA programming language",
deck_id=deck_id,
manual_tags=["python", "programming", "basics"]
)
Use manual tags when:
Prefer soft deletion for safety:
# Soft delete (reversible)
from datetime import datetime
api.update_card(card_id, trashed=datetime.utcnow().isoformat())
# Undelete
api.update_card(card_id, trashed=None)
# Hard delete (permanent)
api.delete_card(card_id) # Cannot be undone
Handle pagination for large collections:
def get_all_cards(deck_id):
"""Retrieve all cards from a deck, handling pagination."""
all_cards = []
bookmark = None
while True:
result = api.list_cards(deck_id=deck_id, limit=100, bookmark=bookmark)
all_cards.extend(result["docs"])
bookmark = result.get("bookmark")
if not bookmark or not result["docs"]:
break
return all_cards
Extract topics from a document and create organized flashcards:
Transform vocabulary lists into flashcards:
Turn teaching moments from conversations into cards:
Handle API errors gracefully:
from scripts.mochi_api import MochiAPIError
try:
card = api.create_card(content=content, deck_id=deck_id)
except MochiAPIError as e:
# Report specific error to user
print(f"Failed to create card: {e}")
# Possibly retry or ask for corrected input
Common errors:
Complete Python client for the Mochi API. Provides classes and functions for:
MochiAPI: Main client class with methods for all operationscreate_card(), update_card(), delete_card(): Card operationscreate_deck(), update_deck(), delete_deck(): Deck operationscreate_template(), get_template(), list_templates(): Template operationslist_cards(), list_decks(): Listing with pagination supportExecute directly for command-line testing or import as a module for programmatic use.
Detailed API reference documentation including:
Consult this reference when:
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.