Search...Search plugins and themes...
⌘K
Sign in
  • Get started
  • Download
  • Pricing
  • Enterprise
  • Account
  • Obsidian
  • Overview
  • Sync
  • Publish
  • Canvas
  • Mobile
  • Web Clipper
  • CLI
  • Learn
  • Help
  • Developers
  • Changelog
  • About
  • Roadmap
  • Blog
  • Resources
  • System status
  • License overview
  • Terms of service
  • Privacy policy
  • Security
  • Community
  • Plugins
  • Themes
  • Discord
  • Forum / 中文论坛
  • Merch store
  • Brand guidelines
Follow us
DiscordTwitterBlueskyThreadsMastodonYouTubeGitHub
© 2026 Obsidian

Inkwright

nukcolenukcole67 downloads

Write, playtest and debug ink interactive fiction: live play panel, saves, knot graph, web export and bilingual stories. English and Chinese interface.

Add to Obsidian
  • Overview
  • Scorecard
  • Updates7

Write, playtest and debug ink interactive fiction in Obsidian. Works on desktop and mobile. Interface in English and Chinese.

Think of it as Inky inside your vault: your story files sit next to your notes, character sheets and outlines, the play panel recompiles as you type, and the knot graph shows the shape of your branches. When the story is ready, export it as a single web page.

中文说明

Edit a line and the play panel updates; make a choice, switch the story to Chinese, then open the knot graph

Why Inkwright?

Writing a branching story is already a choose-your-own-adventure. The adventure should not be: alt-tab to Inky, copy the file over, lose the outline, forget which knot you were in, alt-tab back.

  • Your story lives where your notes live. Character sheets, maps, the timeline, the 3 a.m. plot twist you typed on your phone: all one [[link]] away from the script.
  • Write a line, play the line. Save, and the play panel has already recompiled. No build step, no ceremony.
  • See the spaghetti before your readers do. The knot graph draws every branch and outlines in red the knots no path can reach. (Every writer has that one perfect ending nobody will ever see.)
  • Works on the train. Desktop and mobile, same vault, same saves.
  • One file to ship. Export a single .html, drop it on itch.io, go to bed.
  • One story, two languages. Write {tr("Hello", "你好")} once; readers switch languages mid-story without losing their place, and the plugin nags you about untranslated lines more reliably than any editor.
  • Roll the dice. Put a game.md next to a story and it plays as a game: skill checks with odds on the buttons, resources, items, random tables, decks, a map, a dungeon that grows as you explore. Solo tabletop RPGs and gamebooks, written as notes.
  • Robots welcome. A JSON API lets your coding agent play every ending while you make tea.
=== you ===
You have a story in your head and a vault full of notes.
* [Keep alt-tabbing between three apps] -> still_alt_tabbing
* [Install Inkwright] -> happily_ever_after

Install

In Obsidian, open Settings → Community plugins → Browse, search for Inkwright, then install and enable it. Or open the listing in the community directory.

Requires Obsidian 1.13 or later; older versions get the previous release automatically.

Features

  • Edit .ink files in your vault with syntax highlighting.
  • Pick up where you left off: the player keeps your run across edits, restarts and devices (saved in a vault folder, one file per device), and stops where the story changed under you instead of starting over.
  • Play panel: the story recompiles a moment after you save, so you can play while you write. Undo the last choice, restart, or start from any knot or stitch.
  • Errors you can click: compile errors and warnings are listed with file and line; click to jump there.
  • Multi-file stories: INCLUDE paths resolve relative to the main story's folder, as in Inky and inklecate. Lock a main story so the panel keeps playing it while you edit its chapters.
  • Variables and visit counts for the current playthrough.
  • Saves: save, load and delete progress per story. Saves are stored in the plugin's data, so they sync with your vault.
  • Knot graph: diverts, tunnels and threads between knots, with knots that can never be reached from the start highlighted.
  • Export as web page: one self-contained .html file next to the story, playable in any browser, with undo and progress kept in the browser, even when you re-export an updated version (the player's run is replayed on it and stops, with a note, where a choice they took is gone). Upload it anywhere (itch.io, GitHub Pages, …).
  • Bilingual stories: declare VAR lang = "en" (or VAR 语言) and write text as {tr("Hello", "你好")}-style calls; the play panel and exported pages get a language switch that replays the run in the other language without losing progress. Text left outside such a call is reported as a warning.
  • The player writes: a choice tagged #input:name gets a text field; the line typed goes into the name VAR (a name, an oath, a diary line), and saves, undo and the language switch keep it.
  • A dice tray for solo play: ask the oracle yes/no questions at five odds (with a chaos value if you like), roll any formula, roll inspiration tables; the answers are part of the run and the journal.
  • Game mode: a game.md note next to the story turns it into a game with dice checks, skills, resources, characters, items, random tables, decks, hands of cards, a map and more (see Game mode below).
  • Playtest at scale: npm run check-ink -- <folder> --all plays every branch (both sides of every check in a game) and reports endings, runtime errors, unreached knots and choices; --random 300 plays random runs and gives the odds of each ending.
  • Write the session to a note: in a game, one command turns the run so far (text, choices, dice) into a markdown note.
  • Chinese interface and error messages (the language follows Obsidian, or can be set in the settings).

Knot graph of a short story next to the play panel

Usage

  1. Open a .ink file. Click the ▶ ribbon icon (or run Open player) to play it in the sidebar, or run Open player in the main area (full screen); a button on the panel's bar moves it between the two.
  2. For a story split into several files, open the main file and choose Lock in the panel (or run Lock current file as main story).
  3. Run Open knot graph to see the story's structure, and Export as web page to publish it.

Bilingual stories

The language variable is set by the panel; the text function is yours, so name it as you like:

VAR lang = "en"

{tr("It rained all night.", "雨下了整整一夜。")}
* [{tr("Open the door", "开门")}] -> door

=== function tr(en, zh) ===
{ lang == "zh":
    ~ return zh
}
~ return en

Languages are "en" and "zh". String literals in ink cannot contain ", so use “” or ' inside them.

Game mode

A folder whose main story sits next to a game.md note is a game. The note's frontmatter holds the rules; the story stays plain ink. The state lives in ink variables, so saves, undo, the language switch and the web export all keep working.

---
rules: { kind: sum, dice: [6, 6] }          # 2d6 + skill vs difficulty; also rollUnder (d100) and bag (chaos bag)
languages: [zh, en]
skills:
  - { id: insight, name: { zh: 洞察力, en: Insight } }
  - { id: strength, name: { zh: 力量, en: Strength } }
resources:
  - { id: fear, name: { zh: 恐惧, en: Fear }, min: 0, max: 100, initial: 0 }
characters:
  - { id: xin, name: { zh: 昕, en: Xin }, skills: { insight: 3, strength: 2 } }
---

Run Generate game engine ink to write _engine.ink from the note, INCLUDE it, and tag choices:

INCLUDE _engine.ink

* [{t("轻轻推开门", "Ease the door open")} #check:insight:10]
    { check("insight", 10) >= 3:
        {t("门无声地开了。", "It swings open without a sound.")}
    - else:
        {t("门轴发出一声长响。", "The hinge groans.")}
        ~ fear += 20
    }

With languages: [zh, en] the generated ink declares the language variable and its own t(zh, en) helper, so a game does not write a text function of its own.

The player picks a character, sees the odds of each check on the choice, and each roll shows up as a card in the text and in the dice log. The generated ink falls back to plain rules, so the story still runs in Inky.

What a game note can declare:

  • Checks and voices: #check:skill:difficulty on a choice (:red for a one-shot check), five result bands from critical failure to critical success, skills that speak up as inner voices (#voice:skill), modifiers from resources and items.
  • Resources, characters, companions: clamped to min..max; several playable characters as presets; companions with their own resources.
  • Items: an inventory list; #needs:item locks a choice until the item is carried.
  • Effects: #fx:shake|flash|dark|pulse on a line.
  • Dice and random tables: {roll("2d6+3")}, d66, exploding d6!, keep highest 4d6kh3 / lowest 2d20kl, dice pools 5d6>=5; {table("encounter")} reads a row from a table written inline or in another note's markdown table.
  • Decks and hands: draw("clues"), shuffle, deck_left; hands drawn as rows of cards, #play:hand plays the picked card. Cards can carry numbers and art and come from a folder of notes.
  • Map: places, links, hidden places, counters and tokens over an image, or drawn on an Obsidian canvas; #go:place makes a place tappable.
  • Growing dungeon: rooms from a sheet of shapes, hung on free doors as you explore, with secret doors, the way back and notes per room.
  • Party: several characters played at once, drawn as cards with stat bars.
  • Chaos bag: checks that draw a token instead of rolling.

The web export carries the engine along, so an exported game plays the same in a browser.

Agent API

For coding agents and scripts, the plugin exposes app.plugins.plugins.inkwright.api, usable through the Obsidian CLI: compile a story, play it headlessly with a list of choices, read variables and visit counts, inspect the knot graph, drive the visible play panel, or export it. Everything returns JSON.

obsidian eval code='app.plugins.plugins.inkwright.api.help()'
obsidian eval code='app.plugins.plugins.inkwright.api.play("stories/main.ink",{choices:[0,"Open"]}).then(JSON.stringify)'

Privacy

Inkwright makes no network requests. Stories are compiled and played locally with inkjs.

Development

npm install
npm test          # unit tests
npm run lint      # Obsidian review rules
npm run build     # type check + bundle main.js
npm run check-ink -- <folder> [--all] [--random N]   # compile and play every story under a folder
npm run export-web -- <main.ink> <out.html>          # web export from the command line
npm run gen-engine -- <main.ink> [--check]           # write (or check) a game's _engine.ink
OBSIDIAN_PLUGIN_DIR=/path/to/vault/.obsidian/plugins/inkwright npm run dev   # watch build into a vault

Releases are built by GitHub Actions when a version tag (e.g. 0.2.0, no v) is pushed.

Thanks

  • inkle, for creating ink and Inky, open-sourcing them under MIT, and showing with 80 Days, Heaven's Vault and friends what a few * and -> can do. Inkwright is an unofficial fan tool and not affiliated with inkle.
  • inkjs by Yannick Lohse and contributors, the JavaScript port of ink that compiles and runs every story here.
  • Obsidian, for a plugin API that lets an interactive fiction studio move into a note-taking app.

License

MIT. The story engine is inkjs (MIT); ink is by inkle.

HealthExcellent
ReviewSatisfactory
About
Edit and playtest ink interactive fiction in Obsidian with syntax highlighting and a live play panel that recompiles after save, lets you undo choices, restart, or jump to any knot. Debug with clickable compile errors, view knot graphs, use per-story saves and multi-file stories, lock a main story, export a single-file HTML, and toggle languages for bilingual stories.
CodeWritingVisualization
Details
Current version
0.6.0
Last updated
3 days ago
Created
2 weeks ago
Updates
7 releases
Downloads
67
Compatible with
Obsidian 1.13.0+
Platforms
Desktop, Mobile
License
MIT
Report bugRequest featureReport plugin
Author
nukcolenukcole
GitHubluoxin9510
  1. Community
  2. Plugins
  3. Code
  4. Inkwright

Related plugins

Mermaid Tools

Improved Mermaid.js experience: visual toolbar with common elements and more.

StoryLine

Transform your vault into a powerful book planning and writing tool. Corkboard, KanbanBoard view, timeline, plotlines,character tracking, and more.

Kroki

Render Kroki diagrams.

Adamantine Pick

Embeddable Pikchr diagrams renderer.

Excalidraw

Visual PKM powerhouse. Create and edit Excalidraw drawings.

Advanced Canvas

Supercharge your canvas experience. Create presentations, flowcharts and more.

Templater

Create and use dynamic templates.

LanguageTool Integration

Advanced grammar and spell checking, powered by LanguageTool.

ExcaliBrain

An interactive, structured mind-map of your Obsidian vault.

Breadcrumbs

Visualise the hierarchy of your vault using a breadcrumb trail or matrix view.