
Game Facilitator
- 412 installs
- 133 repo stars
- Updated February 24, 2026
- jwynia/agent-skills
Facilitate tabletop, workshop, or narrative games by managing rules, turns, prompts, and player guidance through an interactive agent session.
About
Game-facilitator turns agents into structured session hosts for RPGs and workshop games: track state, explain rules, prompt players, and keep pacing fair so interactive play runs smoothly without a human GM.
- Session flow control
- Rules adjudication
- Player prompts
- Scene pacing
- Multi-player coordination
Game Facilitator by the numbers
- 412 all-time installs (skills.sh)
- +7 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #55 of 247 Game Development skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/jwynia/agent-skills --skill game-facilitatorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 412 |
|---|---|
| repo stars | ★ 133 |
| Last updated | February 24, 2026 |
| Repository | jwynia/agent-skills ↗ |
What it does
Facilitate tabletop, workshop, or narrative games by managing rules, turns, prompts, and player guidance through an interactive agent session.
Files
Game Facilitator: Narrative RPG Skill
You facilitate narrative RPG experiences—running scenes, portraying NPCs, describing the world, and maintaining story coherence while honoring player agency. Your role is to create emergent stories collaboratively, not to execute a predetermined plot.
Core Principle
The story belongs to everyone at the table.
You are not the author of a fixed story the players must discover. You are a collaborator creating story together. Your job is to:
- Make the world feel alive and responsive
- Give players meaningful choices with real consequences
- Create situations, not plots
- Say "yes, and..." to player creativity
- Make failure as interesting as success
---
The Facilitator Mindset
You Are Not The Author
The players are protagonists of their own story. You provide:
- Situation: The unstable state demanding response
- Opposition: Obstacles, NPCs, world resistance
- Consequences: What happens as a result of choices
- World: The consistent reality they navigate
You do NOT provide:
- Predetermined endings
- "Correct" solutions
- Plot that happens regardless of choices
- Your story that players watch
The Improv Foundation
Apply improv principles to collaborative narrative:
| Principle | Application |
|---|---|
| Yes, and... | Accept player contributions, build on them |
| Make your partner look good | Help players be awesome |
| There are no mistakes | Unexpected turns become story |
| Don't block | Allow player ideas to succeed |
| Serve the story | Not your ego, not a plan |
Play to Find Out
You don't know how the story ends. Neither do the players. The ending emerges from:
- Player choices
- Dice/mechanics (if used)
- NPC motivations
- World logic
- Creative collision
Embrace not knowing. That's where magic happens.
---
Operational Modes
Mode: Scene
Run a specific dramatic scene with clear structure.
Scene Structure (Goal → Conflict → Disaster):
1. Establish the Goal
- What do the players want in this scene?
- Make it specific and achievable
- Connect to larger story stakes
2. Escalate Conflict
- Opposition should intensify
- Each beat raises difficulty
- Multiple types of conflict layer
3. Reach Disaster
- End with consequences
- "Yes, but..." or "No, and furthermore..."
- Create new problems even in success
Scene Endings:
- Yes, but... — They get what they want, but new problem (best)
- No, and... — They fail, and it gets worse
- No — They fail, must try another approach
- Yes — Clean success (use sparingly)
Cut Scenes When:
- Conflict resolves one way or another
- No more escalation possible
- Players are stuck (move time/place)
- Energy is flagging
Mode: Sequel
Process the aftermath of a scene.
Sequel Structure (Reaction → Dilemma → Decision):
1. Reaction: Let players process emotionally
- "How does your character feel about that?"
- Give space for roleplay
- Can be brief or extended
2. Dilemma: Present the difficult choice
- No good options, only trade-offs
- Connect to character values
- Make it genuinely hard
3. Decision: Player commits to next action
- This becomes the goal of the next scene
- Honor their choice with consequences
Sequel Length Controls Pacing:
- Short sequels → fast, action-heavy feel
- Long sequels → contemplative, character-heavy feel
Mode: NPC
Portray a non-player character in dialogue or action.
NPC Essentials:
- Want: What do they want right now?
- Method: How do they pursue it?
- Obstacle: What's in their way?
- Voice: How do they speak differently?
Voice Differentiation:
- Speech pattern (formal/casual, verbose/terse)
- Vocabulary level and word choices
- Physical mannerisms described
- Emotional baseline (anxious, confident, suspicious)
NPC in Conflict:
- Play them true to their motivations
- Don't soften them to help players
- Don't harden them to punish players
- Let them be surprised, persuaded, changed
When NPCs Have Information:
- They share what serves their goals
- They hide what protects them
- They reveal when players earn it
- They never info-dump
Mode: World
Describe the setting and world response.
Description Principles:
- Lead with what matters to the scene
- Engage multiple senses
- Imply more than you state
- Let players ask for details
World Response to Actions:
- The world notices what players do
- Actions have ripple effects
- NPCs react to rumors, evidence
- Environment changes from interaction
Environmental Storytelling:
- Details that imply history
- Signs of recent events
- Evidence of inhabitants
- Atmosphere that supports tone
Mode: Oracle
Make decisions when outcomes are uncertain.
When to Decide vs. When to Roll:
- Decide: When outcome is obvious or dramatically necessary
- Roll: When genuine uncertainty exists and randomness adds interest
Decision Factors:
- Player approach quality (clever plans should help)
- Character capabilities (skills matter)
- Established world logic (what makes sense)
- Story needs (what creates better narrative)
Fail Forward Principle: Failure should never stop the story. Failure should:
- Create new complications
- Reveal information
- Change the situation
- Cost something but continue
Mode: Generation
Create new content on demand.
Generate NPCs:
- Name that fits the world
- Immediate want and method
- One distinctive trait
- Relationship to situation
Generate Locations:
- Primary sensory impression
- What's happening there
- What's interesting to interact with
- How it connects to known places
Generate Events:
- What would happen if players weren't here?
- What factions are pursuing goals?
- What random intersection occurs?
- What consequence arrives?
Generate Complications:
- New obstacle in current approach
- Unexpected connection revealed
- Time pressure introduced
- Resource depleted
---
Session Structure
Opening: Situation Setup
Establish the unstable situation demanding response:
- What's the immediate problem/opportunity?
- Who are the involved parties?
- What's at stake?
- What happens if nothing is done?
Not: "Here's what you need to do." But: "Here's what's happening. What do you do?"
Middle: Play to Find Out
Cycle through scenes and sequels: 1. Players declare intentions 2. Frame scene with goal 3. Run conflict with escalation 4. Reach disaster/resolution 5. Process in sequel 6. New decision leads to new scene
Track:
- What's been established (can't contradict)
- NPC locations and motivations
- Ticking clocks and countdown timers
- Player resources and relationships
Ending: Resolution or Cliffhanger
Session Ending Options:
- Resolution: Major goal achieved or failed, new status quo
- Cliffhanger: Moment of maximum tension, decision pending
- Transition: Situation changed, new chapter beginning
Ending a Campaign:
- Major character arcs should complete
- Central tension must resolve
- Consequences of journey should be clear
- Room for epilogue/aftermath
---
Pacing Techniques
The Scene-Sequel Ratio
| Ratio | Feel | Good For |
|---|---|---|
| 3:1 scenes:sequels | Breakneck | Action, thriller, chase |
| 2:1 | Fast | Adventure, heist |
| 1:1 | Balanced | Most campaigns |
| 1:2 | Contemplative | Drama, intrigue |
Tension Curve
Build tension across the session:
- Opening: Establish normalcy, then disrupt
- Rising: Each scene escalates stakes
- Peak: Maximum tension, crucial choice
- Falling: Consequences unfold
- Resolution: New equilibrium (until next session)
Pacing Tools
| Tool | Effect |
|---|---|
| Cut scene early | Increases pace |
| Skip sequel | Urgent feel, exhausting if overused |
| Expand sequel | Character depth, slower pace |
| Cliffhanger cut | Tension maintained between sessions |
| Montage | Compress time, skip less interesting parts |
| Flashback | Reveal backstory at moment of impact |
---
Player Agency
Meaningful Choices
Every significant choice should:
- Have distinct options (not false choice)
- Have perceivable consequences
- Express character values
- Be irreversible (no takebacks)
When Players Surprise You
Player does something unexpected: 1. Don't say no reflexively 2. Ask clarifying questions 3. Consider what would actually happen 4. Let them try (with appropriate difficulty) 5. Make the outcome interesting regardless
Player derails your plan:
- You don't have a plan, you have a situation
- NPCs adjust to new reality
- Consequences follow actions
- The story goes where it goes
The Spotlight
Ensure all players get:
- Moments where their character shines
- Scenes focused on their goals
- NPCs who care about them specifically
- Challenges suited to their abilities
Rotate spotlight; don't let one player dominate.
---
NPC Management
Active NPCs
Keep track of NPCs with ongoing presence:
Name: [Who]
Want: [Current goal]
Method: [How they pursue it]
Relationship: [To players/situation]
Next action: [What they do if players don't intervene]NPC Factions
Groups with collective goals:
- What do they want?
- What resources do they have?
- Who are their rivals?
- What's their next move?
The Countdown
Things that happen if players don't act:
- NPCs pursue their goals
- Situations deteriorate
- Opportunities close
- Consequences arrive
Make countdowns visible when appropriate; sometimes hidden.
---
World Consistency
What's Been Established
Track canon from play:
- Facts stated about the world
- NPC names and relationships
- Locations and their features
- Events that have occurred
Never contradict established facts without in-world explanation.
Integration with World Bible
If using shared-world skill:
- Check bible before introducing major elements
- Add new canon to bible after sessions
- Flag potential contradictions
- Use established NPCs/locations
Improvised Canon
New facts created in play:
- Note them immediately
- Consider implications
- Let them ripple outward
- They're now as real as anything pre-planned
---
Tone Management
Setting Tone
Tone emerges from:
- Description choices (gritty vs. lush)
- NPC demeanor (serious vs. playful)
- Consequence severity (lethal vs. forgiving)
- Humor allowance (grimdark vs. comedy)
Reading the Table
Watch for:
- Energy levels (tired players need simpler scenes)
- Engagement (bored players need spotlight or change)
- Discomfort (safety tools when needed)
- Excitement (ride the wave when energy is high)
Adjusting Mid-Session
If tone is wrong:
- Introduce element that shifts it (comic relief, serious threat)
- Cut to different scene type
- Explicitly discuss with players
- Take a break to reset
---
Common Situations
Players Are Stuck
Options:
- NPC arrives with information or demand
- Environment changes (danger, opportunity)
- Cut away and return with new context
- Ask "What does your character want?"
- Offer choices explicitly
Players Are Arguing
Options:
- Let them resolve in character
- Apply time pressure (decide or X happens)
- Split party temporarily (both approaches happen)
- Ask what their characters do, not what they think should happen
Player Wants Impossible Thing
Options:
- Clarify what's actually impossible vs. difficult
- Offer path to eventually achieving it
- Show consequences of attempting it
- Ask what they actually want (goal behind goal)
Scene Is Dragging
Options:
- Escalate conflict sharply
- Cut to aftermath
- Introduce complication
- Ask "Are we done here?"
---
Integration with Other Skills
| Skill | Integration |
|---|---|
| story-sense | Core narrative principles apply |
| worldbuilding | Consistency diagnostics for world |
| character-arc | NPC transformation over campaign |
| scene-sequencing | Pacing structure |
| dialogue | NPC voice and subtext |
| shared-world | Canon tracking across sessions |
| genre-conventions | Genre expectations and subversion |
| cliche-transcendence | Avoiding tired tropes |
---
Available Tools
session-notes.ts
Quick session note template generator.
deno run --allow-read --allow-write scripts/session-notes.ts "Session Title"npc-generator.ts
Generate NPCs on demand.
deno run --allow-read scripts/npc-generator.ts --tone dark-fantasy
deno run --allow-read scripts/npc-generator.ts --role merchant --trait suspiciouscomplication-generator.ts
Generate complications when stuck.
deno run --allow-read scripts/complication-generator.ts --current "investigating the crime"---
Anti-Patterns
The Railroad
Pattern: Pre-determined plot that happens regardless of choices. Problem: Players are audience, not participants. Fix: Create situations, not plots. Play to find out.
The Adversary
Pattern: GM "wins" when players lose. Problem: Collaboration replaced by competition. Fix: You're on the same side. You want them to succeed (eventually).
The Novelist
Pattern: Extensive narration, minimal player input. Problem: Players are passive recipients. Fix: Describe briefly, ask "What do you do?" constantly.
The Pushover
Pattern: Every player idea succeeds without cost. Problem: No tension, no stakes. Fix: Success with complications. Failure that's interesting.
The Blocker
Pattern: "No, you can't do that" to player ideas. Problem: Player agency crushed. Fix: "Yes, and here's what happens..." or "Yes, if you can..."
The Secrets Hoarder
Pattern: Key information never accessible to players. Problem: Players can't make informed choices. Fix: If information matters, create paths to discover it.
The Prep Over-Investor
Pattern: Hours of detailed prep players never see. Problem: Wasted effort, rigid attachment to prep. Fix: Prep situations and NPCs, not scenes. Improvise from foundations.
---
Session Prep
What to Prepare
- The situation: What's unstable and demands response
- Key NPCs: 2-3 with clear wants and methods
- Key locations: 2-3 where action might occur
- Countdown: What happens if players do nothing
- Bangs: Provocative events to trigger if needed
What NOT to Prepare
- Predetermined outcomes
- Fixed sequence of scenes
- NPC conversations in advance
- "The" solution to problems
- Endings
The 5-Minute Prep
If pressed for time: 1. One sentence situation 2. One NPC who wants something 3. One complication waiting to happen
That's enough. Improvise the rest.
---
Example Interactions
Example 1: Opening a Session
Setup: Players arrive at a town where they heard rumors of trouble.
Your approach: 1. Describe arrival (senses, atmosphere, oddity) 2. Present the immediate situation visibly 3. Introduce NPC who reacts to their presence 4. Ask: "What do you do?" 5. Frame first scene based on their response
Example 2: Player Does Something Unexpected
Player: "I want to seduce the dragon."
Your approach: 1. Don't laugh dismissively (even if surprised) 2. Clarify: "What are you hoping to achieve?" 3. Consider: What would the dragon actually do? 4. Allow the attempt (with appropriate difficulty) 5. Make the outcome interesting (success creates different problems)
Example 3: Session Is Flagging
Signs: Players seem distracted, scene is meandering.
Your approach: 1. Inject complication (NPC arrives, danger emerges) 2. Or cut scene: "Let's skip ahead—what are you doing next?" 3. Or take break: "Five minutes, then we'll pick up the pace" 4. Ask directly: "Are we having fun? What would be more interesting?"
---
Output Persistence
This skill has built-in persistence through the session-notes.ts tool.
Existing Persistence Mechanism
The game-facilitator skill uses session-notes.ts to create and maintain session logs:
deno run --allow-read --allow-write scripts/session-notes.ts "Session Title"This generates structured session notes that persist:
- Session summary - what happened
- NPC states - characters introduced or changed
- World changes - consequences that carry forward
- Player decisions - choices that affect future sessions
- Threads - open plot hooks and unresolved situations
Session Note Location
Session notes are stored in the campaign directory structure. If no structure exists, the script will prompt for setup.
Note: Unlike other skills that write to explorations/, game-facilitator outputs belong in the campaign's own directory structure since they're operational game data, not explorations.
Conversation vs. File
| Goes to File | Stays in Conversation |
|---|---|
| Session summary | Active play |
| NPC/world state changes | Real-time facilitation |
| Important player decisions | Moment-to-moment narration |
| Open threads for next session | Dice rolls and mechanics |
What You Do NOT Do
- You do not decide the story's ending in advance
- You do not block player creativity without good reason
- You do not compete against the players
- You do not force specific solutions
- You do not punish players for surprising you
- You do not hog the spotlight with NPC monologues
Your role is facilitation: create space for collaborative story to emerge. The players are the protagonists. The story is everyone's.
---
Key Insight
The best sessions happen when everyone, including you, is surprised by what happens. When an NPC becomes more important than planned because the players connected with them. When the "obvious" solution fails and the backup plan creates a better story. When the dice produce an outcome no one expected and everyone embraces it.
You're not performing a story. You're discovering one together.
That's the magic of collaborative narrative: it belongs to no one and everyone.
#!/usr/bin/env -S deno run --allow-read
/**
* complication-generator.ts - Generate complications when the game needs a push
*
* Creates:
* - New obstacles
* - Unexpected connections
* - Time pressures
* - Resource problems
* - NPC interventions
*
* Usage:
* deno run --allow-read complication-generator.ts
* deno run --allow-read complication-generator.ts --type obstacle
* deno run --allow-read complication-generator.ts --current "searching the mansion"
*/
interface Complication {
type: string;
description: string;
escalation: string;
question: string;
}
const COMPLICATION_TYPES = [
'obstacle',
'revelation',
'time-pressure',
'resource',
'npc-intervention',
'environment',
'betrayal',
'opportunity'
];
const COMPLICATIONS: Record<string, Complication[]> = {
'obstacle': [
{
type: 'obstacle',
description: 'The direct path is blocked—guards, locks, or physical barrier',
escalation: 'Someone notices them trying to get past',
question: 'How do they bypass it without drawing attention?'
},
{
type: 'obstacle',
description: 'They need something they don\'t have to proceed',
escalation: 'Time is running out to acquire it',
question: 'Who has what they need, and what will it cost?'
},
{
type: 'obstacle',
description: 'Someone they need is unavailable, missing, or unwilling',
escalation: 'The person is in danger themselves',
question: 'Can they find them or accomplish the goal another way?'
},
{
type: 'obstacle',
description: 'Their reputation precedes them—doors are closing',
escalation: 'Active efforts to stop them are beginning',
question: 'Who\'s spreading information and why?'
},
{
type: 'obstacle',
description: 'The skill required is beyond any of them',
escalation: 'Failed attempts draw attention or worsen the situation',
question: 'Who can they recruit, and can they be trusted?'
},
],
'revelation': [
{
type: 'revelation',
description: 'They learn their goal is not what they thought',
escalation: 'Someone else knows the truth and is using it',
question: 'Does this change what they want, or just how they pursue it?'
},
{
type: 'revelation',
description: 'An ally has been working against them',
escalation: 'The betrayer has already reported to someone',
question: 'How much damage has been done, and can it be undone?'
},
{
type: 'revelation',
description: 'The enemy has a sympathetic motivation',
escalation: 'Defeating them will cause collateral harm',
question: 'Is there a solution that doesn\'t require their destruction?'
},
{
type: 'revelation',
description: 'Two things they thought separate are connected',
escalation: 'The connection explains a pattern they missed',
question: 'What else is connected that they haven\'t seen?'
},
{
type: 'revelation',
description: 'They are not the only ones pursuing this goal',
escalation: 'The competition is ahead of them',
question: 'Compete, cooperate, or eliminate the rivals?'
},
],
'time-pressure': [
{
type: 'time-pressure',
description: 'A deadline they didn\'t know about is imminent',
escalation: 'Missing it will close their path permanently',
question: 'Can they make it, and what corners must be cut?'
},
{
type: 'time-pressure',
description: 'Someone important is dying or in immediate danger',
escalation: 'Each moment of delay reduces survival chances',
question: 'Drop everything or trust others to handle it?'
},
{
type: 'time-pressure',
description: 'Help is coming—but so is opposition',
escalation: 'It\'s unclear which will arrive first',
question: 'Prepare for help, prepare for attack, or flee?'
},
{
type: 'time-pressure',
description: 'A ritual, event, or process is counting down',
escalation: 'Completion will change everything irreversibly',
question: 'Stop it, redirect it, or embrace what\'s coming?'
},
{
type: 'time-pressure',
description: 'They\'re being hunted and the pursuit is closing in',
escalation: 'Their safe havens are being compromised one by one',
question: 'Run, hide, or turn and face the pursuers?'
},
],
'resource': [
{
type: 'resource',
description: 'A crucial resource runs out (money, supplies, energy)',
escalation: 'Alternatives are expensive, dangerous, or compromising',
question: 'What are they willing to sacrifice to continue?'
},
{
type: 'resource',
description: 'Something they rely on breaks or is taken',
escalation: 'Operating without it puts them at serious disadvantage',
question: 'Repair, replace, or adapt to the loss?'
},
{
type: 'resource',
description: 'An ally cannot continue (injured, called away, arrested)',
escalation: 'The ally knows things that could be extracted',
question: 'Rescue them, find replacement, or proceed alone?'
},
{
type: 'resource',
description: 'The safe place is no longer safe',
escalation: 'They may have been compromised before leaving',
question: 'Where can they go, and who can they still trust?'
},
{
type: 'resource',
description: 'Their reputation/credibility takes a major hit',
escalation: 'Former allies are distancing themselves',
question: 'Clear their name, work from shadows, or accept the label?'
},
],
'npc-intervention': [
{
type: 'npc-intervention',
description: 'A powerful figure takes interest in the situation',
escalation: 'Their interest comes with strings attached',
question: 'Accept help that comes with obligations?'
},
{
type: 'npc-intervention',
description: 'An old contact appears with urgent need',
escalation: 'Ignoring them will burn the bridge permanently',
question: 'Help them now, or prioritize current goals?'
},
{
type: 'npc-intervention',
description: 'Someone offers a shortcut—suspiciously convenient',
escalation: 'The offer has a deadline',
question: 'Too good to be true, or genuine opportunity?'
},
{
type: 'npc-intervention',
description: 'An enemy wants to negotiate',
escalation: 'They have something valuable to offer or threaten',
question: 'Hear them out, or reject any dealing?'
},
{
type: 'npc-intervention',
description: 'An innocent gets caught in the crossfire',
escalation: 'Saving them will compromise the mission',
question: 'Mission or conscience?'
},
],
'environment': [
{
type: 'environment',
description: 'Weather or natural conditions turn dangerous',
escalation: 'The conditions are worsening rapidly',
question: 'Push through, shelter, or find another route?'
},
{
type: 'environment',
description: 'The location is more dangerous than expected',
escalation: 'They\'re deeper in than they realized',
question: 'Retreat while possible, or commit to the danger?'
},
{
type: 'environment',
description: 'Something awakens, activates, or notices them',
escalation: 'It\'s mobile and interested',
question: 'Communicate, hide, fight, or flee?'
},
{
type: 'environment',
description: 'The terrain or structure is unstable',
escalation: 'Movement may trigger collapse',
question: 'Slow and careful, or race through before it fails?'
},
{
type: 'environment',
description: 'They become separated or disoriented',
escalation: 'One group encounters danger alone',
question: 'Reunite first, or trust both groups to handle their situations?'
},
],
'betrayal': [
{
type: 'betrayal',
description: 'Information was leaked—someone talked',
escalation: 'The leak is ongoing, not past',
question: 'Find the leak, or change plans entirely?'
},
{
type: 'betrayal',
description: 'An ally chose a side, and it wasn\'t theirs',
escalation: 'The ally is actively working against them now',
question: 'Confront, avoid, or turn them back?'
},
{
type: 'betrayal',
description: 'They were set up—the situation was a trap',
escalation: 'The trap is closing',
question: 'How did they not see it, and who orchestrated it?'
},
{
type: 'betrayal',
description: 'Something they were promised isn\'t delivered',
escalation: 'They\'ve already given their end of the bargain',
question: 'Pursue compensation, or write off the loss?'
},
{
type: 'betrayal',
description: 'They discover they were manipulated into helping the wrong side',
escalation: 'Their actions have caused harm they must face',
question: 'Make amends, deny responsibility, or embrace the new alignment?'
},
],
'opportunity': [
{
type: 'opportunity',
description: 'A distraction creates an unexpected opening',
escalation: 'The window is closing fast',
question: 'Take the risky opportunity, or stick to the plan?'
},
{
type: 'opportunity',
description: 'They discover something valuable while pursuing the goal',
escalation: 'Taking it will complicate the main mission',
question: 'Side objective worth the risk?'
},
{
type: 'opportunity',
description: 'An enemy is vulnerable, but attacking means exposure',
escalation: 'The vulnerability won\'t last',
question: 'Strike now, or preserve cover for later?'
},
{
type: 'opportunity',
description: 'They could solve a bigger problem than they planned',
escalation: 'It requires abandoning the current approach',
question: 'Bigger win with bigger risk, or stay the course?'
},
{
type: 'opportunity',
description: 'They find unlikely allies in the situation',
escalation: 'The allies have their own agenda',
question: 'Temporary alliance worth the complications?'
},
],
};
function random<T>(array: T[]): T {
return array[Math.floor(Math.random() * array.length)];
}
function generateComplication(type?: string): Complication {
const selectedType = type && COMPLICATIONS[type] ? type : random(COMPLICATION_TYPES);
return random(COMPLICATIONS[selectedType]);
}
function formatComplication(comp: Complication, current?: string): string {
let output = `
COMPLICATION GENERATED
======================
Type: ${comp.type.toUpperCase()}
`;
if (current) {
output += `While: ${current}\n\n`;
}
output += `WHAT HAPPENS
${comp.description}
IF IGNORED / ESCALATION
${comp.escalation}
QUESTION FOR PLAYERS
${comp.question}
HOW TO USE
- Drop this in when the scene needs energy
- Present through NPC announcement, discovery, or event
- Let players react—don't predetermine their response
- The escalation triggers if they delay or ignore
`;
return output;
}
function showUsage() {
console.log(`
Complication Generator
======================
Generate complications to inject energy into stalled scenes.
Usage:
deno run --allow-read complication-generator.ts [options]
Options:
--type <type> Specific complication type
--current <desc> Description of current situation
--count <n> Generate multiple complications
Types: ${COMPLICATION_TYPES.join(', ')}
Examples:
deno run --allow-read complication-generator.ts
deno run --allow-read complication-generator.ts --type time-pressure
deno run --allow-read complication-generator.ts --current "investigating the crime scene"
deno run --allow-read complication-generator.ts --count 3
`);
}
function main() {
const args = Deno.args;
if (args.includes('--help') || args.includes('-h')) {
showUsage();
Deno.exit(0);
}
let type: string | undefined;
let current: string | undefined;
let count = 1;
for (let i = 0; i < args.length; i++) {
if (args[i] === '--type' && args[i + 1]) {
type = args[++i];
} else if (args[i] === '--current' && args[i + 1]) {
current = args[++i];
} else if (args[i] === '--count' && args[i + 1]) {
count = parseInt(args[++i]);
}
}
for (let i = 0; i < count; i++) {
const comp = generateComplication(type);
console.log(formatComplication(comp, current));
if (i < count - 1) {
console.log('\n' + '─'.repeat(50) + '\n');
}
}
}
main();
#!/usr/bin/env -S deno run --allow-read
/**
* npc-generator.ts - Generate NPCs on demand for game sessions
*
* Creates NPCs with:
* - Name fitting the tone
* - Immediate want and method
* - Distinctive trait
* - Potential hook
*
* Usage:
* deno run --allow-read npc-generator.ts
* deno run --allow-read npc-generator.ts --tone dark-fantasy
* deno run --allow-read npc-generator.ts --role merchant --trait suspicious
*/
interface NPC {
name: string;
role: string;
want: string;
method: string;
trait: string;
voice: string;
hook: string;
}
const TONES: Record<string, { names: string[]; flavor: string }> = {
'dark-fantasy': {
names: ['Grimwald', 'Sera', 'Thorne', 'Ashlyn', 'Mordecai', 'Lilith', 'Cain', 'Isolde', 'Raven', 'Dusk'],
flavor: 'grim, desperate, haunted'
},
'high-fantasy': {
names: ['Aldric', 'Elara', 'Thorin', 'Lyanna', 'Galen', 'Seraphina', 'Bram', 'Mira', 'Cedric', 'Faye'],
flavor: 'noble, questing, legendary'
},
'urban-fantasy': {
names: ['Jack', 'Maya', 'Dante', 'Zara', 'Marcus', 'Luna', 'Ash', 'Vera', 'Cole', 'Iris'],
flavor: 'street-smart, hidden, dual-life'
},
'sci-fi': {
names: ['Kira', 'Dex', 'Nova', 'Zane', 'Echo', 'Ryn', 'Jax', 'Vera', 'Orion', 'Cass'],
flavor: 'pragmatic, augmented, frontier'
},
'historical': {
names: ['Edmund', 'Catherine', 'William', 'Elizabeth', 'Thomas', 'Margaret', 'John', 'Anne', 'Henry', 'Mary'],
flavor: 'formal, hierarchical, tradition-bound'
},
'modern': {
names: ['Sam', 'Alex', 'Jordan', 'Casey', 'Morgan', 'Riley', 'Taylor', 'Jamie', 'Quinn', 'Blake'],
flavor: 'contemporary, relatable, grounded'
},
};
const ROLES = [
'merchant', 'guard', 'innkeeper', 'scholar', 'priest', 'criminal', 'noble',
'peasant', 'artisan', 'soldier', 'healer', 'entertainer', 'messenger',
'hunter', 'sailor', 'servant', 'beggar', 'traveler', 'official', 'mystic'
];
const WANTS = [
'money to pay a debt',
'information about someone',
'protection from a threat',
'revenge for a wrong',
'escape from this place',
'to find a missing person',
'to keep a secret hidden',
'to expose a secret',
'power over others',
'to be left alone',
'recognition for their work',
'to help someone they love',
'to destroy something',
'to preserve something',
'to prove themselves',
'to atone for past actions',
'to acquire a specific item',
'to prevent a coming disaster',
'to complete a dying wish',
'to sabotage a rival'
];
const METHODS = [
'manipulation and lies',
'direct confrontation',
'bargaining and deals',
'pleading and sympathy',
'threats and intimidation',
'seduction and charm',
'deception and disguise',
'patience and observation',
'bribery and corruption',
'violence as last resort',
'gathering allies',
'undermining rivals',
'leveraging connections',
'exploiting weaknesses',
'offering genuine help'
];
const TRAITS = [
'nervous, fidgeting constantly',
'overly friendly, too eager to please',
'suspicious, watches everyone',
'exhausted, barely holding on',
'arrogant, dismissive of others',
'grieving, heavy with loss',
'cheerful despite circumstances',
'bitter about past failures',
'devoutly religious',
'secretly terrified',
'calculating every angle',
'genuinely kind-hearted',
'barely concealed anger',
'mysterious, speaks in riddles',
'blunt to the point of rudeness',
'drunk or intoxicated',
'physically distinctive (scar, limp)',
'clearly lying about something',
'desperately hiding something',
'nostalgic for better times'
];
const VOICE_PATTERNS = [
'speaks in short, clipped sentences',
'rambles and loses track of thoughts',
'formal and overly polite',
'casual, uses slang and curses',
'whispers conspiratorially',
'loud and commanding',
'hesitant, lots of pauses',
'rapid-fire, barely pauses for breath',
'asks too many questions',
'never quite answers directly',
'uses elaborate vocabulary',
'speaks in platitudes and sayings',
'nervous laughter between phrases',
'sighs heavily before speaking',
'interrupts constantly'
];
const HOOKS = [
'knows something about a player\'s background',
'has an item the players need',
'is being hunted by the same enemy',
'witnessed something the players need to know',
'owes a debt to someone the players know',
'recognizes a player from somewhere',
'is pretending to be someone else',
'has a job that needs doing',
'is dying and needs one last thing',
'is working for the opposition secretly',
'can provide access to a restricted area',
'has a missing family member to find',
'carries a curse that affects others',
'knows the location of something valuable',
'is the last survivor of something significant'
];
function random<T>(array: T[]): T {
return array[Math.floor(Math.random() * array.length)];
}
function generateNPC(options: {
tone?: string;
role?: string;
trait?: string;
}): NPC {
const tone = options.tone && TONES[options.tone] ? options.tone : random(Object.keys(TONES));
const toneData = TONES[tone];
return {
name: random(toneData.names),
role: options.role || random(ROLES),
want: random(WANTS),
method: random(METHODS),
trait: options.trait || random(TRAITS),
voice: random(VOICE_PATTERNS),
hook: random(HOOKS),
};
}
function formatNPC(npc: NPC): string {
return `
NPC GENERATED
=============
Name: ${npc.name}
Role: ${npc.role}
MOTIVATION
Want: ${npc.want}
Method: ${npc.method}
PORTRAYAL
Trait: ${npc.trait}
Voice: ${npc.voice}
STORY HOOK
${npc.hook}
QUICK REFERENCE
"${npc.name} the ${npc.role} wants ${npc.want}
and will use ${npc.method} to get it."
NOTES FOR PLAY
- Play the want actively—they're always pursuing it
- The trait is visible; the want may be hidden
- The hook creates connection—use when the moment is right
`;
}
function showUsage() {
console.log(`
NPC Generator
=============
Generate NPCs on demand for game sessions.
Usage:
deno run --allow-read npc-generator.ts [options]
Options:
--tone <tone> Set the tone/setting
--role <role> Specify role/occupation
--trait <trait> Specify personality trait
--count <n> Generate multiple NPCs
Tones: ${Object.keys(TONES).join(', ')}
Roles: ${ROLES.slice(0, 10).join(', ')}...
Examples:
deno run --allow-read npc-generator.ts
deno run --allow-read npc-generator.ts --tone dark-fantasy
deno run --allow-read npc-generator.ts --role merchant --trait suspicious
deno run --allow-read npc-generator.ts --count 3
`);
}
function main() {
const args = Deno.args;
if (args.includes('--help') || args.includes('-h')) {
showUsage();
Deno.exit(0);
}
const options: { tone?: string; role?: string; trait?: string } = {};
for (let i = 0; i < args.length; i++) {
if (args[i] === '--tone' && args[i + 1]) {
options.tone = args[++i];
} else if (args[i] === '--role' && args[i + 1]) {
options.role = args[++i];
} else if (args[i] === '--trait' && args[i + 1]) {
options.trait = args[++i];
}
}
// Check for count
const countIdx = args.indexOf('--count');
const count = countIdx > -1 && args[countIdx + 1] ? parseInt(args[countIdx + 1]) : 1;
for (let i = 0; i < count; i++) {
const npc = generateNPC(options);
console.log(formatNPC(npc));
if (i < count - 1) {
console.log('\n' + '─'.repeat(50) + '\n');
}
}
}
main();
#!/usr/bin/env -S deno run --allow-read --allow-write
/**
* session-notes.ts - Generate session note templates
*
* Creates structured session notes for tracking:
* - What happened (summary)
* - NPCs introduced
* - Locations visited
* - Plot threads
* - Player decisions
* - Next session setup
*
* Usage:
* deno run --allow-read --allow-write session-notes.ts "Session Title"
* deno run --allow-read --allow-write session-notes.ts "Session Title" --output session-3.md
*/
function getDate(): string {
return new Date().toISOString().split('T')[0];
}
function generateSessionNotes(title: string): string {
const date = getDate();
return `# ${title}
**Date:** ${date}
**Duration:** [X hours]
**Players Present:** [List]
---
## Session Summary
[2-3 sentences capturing the key events]
---
## What Happened
### Opening Situation
[What was the state at session start?]
### Key Events
1. [First major thing that happened]
2. [Second major thing]
3. [Third major thing]
### Ending State
[How did the session end? Cliffhanger? Resolution?]
---
## NPCs Encountered
### New NPCs
| Name | Role | Notable |
|------|------|---------|
| [Name] | [What they do] | [What players remember them for] |
### Returning NPCs
| Name | What Happened |
|------|---------------|
| [Name] | [Their role in this session] |
---
## Locations
### New Locations
- **[Location Name]:** [Brief description and what happened there]
### Revisited Locations
- **[Location Name]:** [What changed or was discovered]
---
## Plot Threads
### Advanced
- [ ] [Thread name]: [What progress was made]
### New
- [ ] [New thread]: [How it was introduced]
### Dormant
- [ ] [Thread on hold]: [Why it's waiting]
### Resolved
- [x] [Completed thread]: [How it resolved]
---
## Player Decisions
Significant choices the players made:
1. **[Decision]:** [What they chose and why it matters]
2. **[Decision]:** [What they chose and why it matters]
---
## Consequences Pending
Things that will happen because of this session:
- [ ] [NPC will react to...]
- [ ] [Faction will respond by...]
- [ ] [Environment will change because...]
---
## Loot/Resources
### Acquired
- [Item/resource]: [Where/how obtained]
### Expended
- [Item/resource]: [How used]
---
## Memorable Moments
[Quote, scene, or moment worth remembering]
---
## GM Notes
### What Worked
- [Thing that went well]
### What to Improve
- [Thing to do better]
### Prep for Next Session
- [ ] [Thing to prepare]
- [ ] [NPC to develop]
- [ ] [Location to detail]
---
## Next Session
### Setup
[What situation will open the next session?]
### Threads to Pursue
1. [Most pressing thread]
2. [Secondary thread]
### NPCs Likely to Appear
- [Name]: [Why]
---
*Notes taken: ${date}*
`;
}
function showUsage() {
console.log(`
Session Notes Generator
=======================
Generate structured session note templates.
Usage:
deno run --allow-read --allow-write session-notes.ts "Session Title"
deno run --allow-read --allow-write session-notes.ts "Session Title" --output file.md
Options:
--output, -o Output file path (default: prints to console)
Examples:
deno run --allow-read --allow-write session-notes.ts "The Heist Begins"
deno run --allow-read --allow-write session-notes.ts "Session 3" -o notes/session-3.md
`);
}
async function main() {
const args = Deno.args;
if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
showUsage();
Deno.exit(0);
}
// Find title (first non-flag argument)
let title = '';
let output = '';
for (let i = 0; i < args.length; i++) {
if (args[i] === '--output' || args[i] === '-o') {
output = args[++i] || '';
} else if (!args[i].startsWith('-')) {
title = args[i];
}
}
if (!title) {
console.error('Error: Session title required');
showUsage();
Deno.exit(1);
}
const notes = generateSessionNotes(title);
if (output) {
await Deno.writeTextFile(output, notes);
console.log(`Session notes created: ${output}`);
} else {
console.log(notes);
}
}
main();