| name | rpg-harness-player |
| description | Play an RPG-Harness game from the shell. Use this skill when you're inside a folder containing game.yaml + characters/ + scripts/ (an RPG-Harness game), and the user wants you to play through the game — either as yourself or in character as a persona. Drives the game via the `rpgh` CLI, reading stdout JSON and writing stdin one input at a time. |
rpg-harness-player
You're a player playing through an RPG-Harness game. You make decisions, the game advances, you reach an ending. You write no code — you only invoke the rpgh CLI and react to its JSON output.
Before you start
Check three things:
- The
rpgh binary is available. Run which rpgh or bun run rpgh --help from inside the RPG-Harness repo. If neither works, ask the user to install it (brew install bun && bun link inside packages/cli/).
- You're at the right path. Identify the game directory. It contains
game.yaml, characters/, scripts/. Use an absolute or repo-relative path going forward (the CLI doesn't care).
- Pick a session name. A session is your save file. Pick something descriptive:
claude-thoughtful, playthrough-cautious, demo-2026-05-21. Don't use someone else's session — that overwrites their save.
GAME="examples/sengoku-raid"
SESSION="claude-$(date +%H%M%S)"
The loop (this is the whole skill)
[peek once] → read output → decide input → [step with input] → read output → repeat
Step 1: See where you are
rpgh peek "$GAME" --session "$SESSION"
Output is a single line of JSON:
{
"output": { "type": "...", ... },
"done": false,
"state": { "baseline": { ... } }
}
If done is true, the game is over. Read the final state and tell the user which ending you reached.
Step 2: Decide based on output.type
| output.type | Meaning | Your input |
|---|
scriptComplete | Between scripts — engine waits for you to pick one of nextAvailable[] | {"type":"select","scriptId":"<id>"} |
narration | Pure story text (no speaker) | {"type":"next"} |
dialogue | A character speaks (speakerName + text) | {"type":"next"} |
choice | Story branch — pick one of options[] (0-based index, only available:true ones) | {"type":"choose","index":N} |
clear | Scene break, just advance | {"type":"next"} |
gameEnd | You hit a terminal — no more scripts available | Stop. Report the ending. |
Step 3: Apply your decision
rpgh step "$GAME" --session "$SESSION" --input '{"type":"choose","index":2}'
The output of step is the next event. You do NOT need to peek again — just react to what step printed.
Step 4: Loop until done
Keep doing step 2 + step 3 until you see gameEnd or done: true.
Reading like a player, not like a parser
Even when output is just narration or dialogue, read the text. The story is the point. Tell the human what's happening in your own words occasionally — don't just dump raw JSON or robotically advance.
When the output is a choice, before sending input:
- State your interpretation of the situation in 1 sentence.
- List the options and what each one signals.
- Pick one and say why.
Example:
> 现在的场景:薄樱在樱花树下画画,问我也喜欢樱花吗。
> 选项:
> 1. 嗯,很美 — 安全
> 2. 只是路过 — 冷淡
> 3. 我喜欢看你画 — 主动
> 我选 3,因为这个 persona 是直接型,而且这个选项有 +2 affection
Then:
rpgh step "$GAME" --session "$SESSION" --input '{"type":"choose","index":2}'
Choosing in character
If the user gave you a persona ("play as a cautious introvert" / "play as someone trying to reach the bea-good ending"), every choice should follow that persona. Don't break character to optimize.
If the user said "just play your way", reveal your taste in the choices. Don't fake.
Locked options
In a choice, options have available: true or available: false. Locked options cannot be picked — picking them is a no-op (engine yields the same choice again). When you see a locked option, mention it in your reasoning ("the bold option requires affection >= 2, I don't have that yet").
When the game ends
rpgh peek "$GAME" --session "$SESSION"
The final state's baseline.completedScripts[-1] is the ending you reached. Tell the user:
- Which ending
- A 1-sentence reflection
- (If they asked) how to read the log:
cat "$GAME/.rpg-harness/sessions/$SESSION/log.jsonl"
Fork your save
A session is a directory. To branch and try a different choice:
cp -r "$GAME/.rpg-harness/sessions/$SESSION" "$GAME/.rpg-harness/sessions/${SESSION}-fork"
You can't go "back" within a single session (engine is forward-only), but you can fork before a key decision and play both branches.
Hard rules
- Never modify the game's
scripts/ or characters/ files unless the user explicitly asks. The author wrote them.
- Never run
step against a session you don't own (sessions list at <game>/.rpg-harness/sessions/).
- The only
rpgh subcommands you should use for play: peek, step. (sessions is informational; test and autoplay are not for playing.)
- If something errors with "ENOENT" or similar, you're probably in the wrong directory or used a wrong path. Don't keep retrying — check
pwd and ls.
Example transcript
$ rpgh peek "$GAME" --session "$SESSION"
{"output":{"type":"dialogue","speakerName":"narrator","text":"慶長十年、初秋。"},"done":false,"state":{"baseline":{"currentScriptId":"000_intro",...}}}
$ rpgh step "$GAME" --session "$SESSION" --input '{"type":"next"}'
{"output":{"type":"dialogue","speakerName":"narrator","text":"江戸城本丸の大広間。蝋燭の煙が天井に渦を巻く。"},...}
$ rpgh step "$GAME" --session "$SESSION" --input '{"type":"next"}'
{"output":{"type":"hubMenu","snapshot":{"activities":[{"id":"depart:kuro_swamp","title":"出立 — 黒沼地(難度 1)",...}, ...]}}, ...}
$ rpgh step "$GAME" --session "$SESSION" --input '{"type":"doActivity","id":"depart:kuro_swamp"}'
{"output":{"type":"narration","text":"黒沼地に踏み入る。霧が脛に絡みつく。"},...}
$ rpgh peek "$GAME" --session "$SESSION"
{"output":{"type":"gameEnd"},"done":true,...}
> 通关。结局:ending_pure_rite — 公儀の道、鎮魂結界の儀。
That's it. The whole skill.