inkle/ink
inkle's open source scripting language for writing interactive narrative.
Healthy across the board
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 4d ago
- ✓23+ active contributors
- ✓MIT licensed
Show 3 more →Show less
- ✓CI configured
- ✓Tests present
- ⚠Concentrated ownership — top contributor handles 67% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/inkle/ink)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/inkle/ink on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: inkle/ink
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/inkle/ink shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 4d ago
- 23+ active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Concentrated ownership — top contributor handles 67% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live inkle/ink
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/inkle/ink.
What it runs against: a local clone of inkle/ink — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in inkle/ink | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | Last commit ≤ 34 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of inkle/ink. If you don't
# have one yet, run these first:
#
# git clone https://github.com/inkle/ink.git
# cd ink
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of inkle/ink and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "inkle/ink(\\.git)?\\b" \\
&& ok "origin remote is inkle/ink" \\
|| miss "origin remote is not inkle/ink (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 34 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~4d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/inkle/ink"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Ink is inkle's open-source scripting language for writing branching interactive narratives, compiled to a JSON runtime format for playback in games and interactive fiction. It provides a domain-specific syntax for managing story choices, diverts, variables, and conditional logic that compiles down to a portable format executable across platforms via the C# runtime (inkjs, Unity integration, and inklecate CLI). Modular compiler architecture: compiler/Compiler.cs is the entry point orchestrating parsing and code generation; InkParser/ directory contains partitioned parser modules (one file per language feature: Divert, Choices, Expressions, Logic, Conditionals, etc.); output targets JSON format (ink_JSON_runtime_format.md). Runtime is separate (in inkjs/ink-unity-integration repos). InkTestBed/ contains manual integration test harness.
👥Who it's for
Narrative designers and game writers who need to structure non-linear branching stories with conditional logic and state management without writing procedural code; game developers integrating branching narrative into Unity or web games who want to separate story logic from engine implementation.
🌱Maturity & risk
Production-ready and actively maintained. The project has been in active development for years (evidenced by comprehensive documentation, multiple integrations listed in README, Travis CI setup, and tagged releases). Strong ecosystem support with official integrations (ink-unity-integration, inkjs, Inky editor) indicates maturity and industry adoption by narrative-focused studios.
Low risk for narrative use cases. C# codebase is well-structured with clear compiler/parser separation. However, the core dependency graph is not visible from file list—ensure compiler dependencies (likely System.* only) are stable. Single maintainer (inkle studio) means release velocity depends on their roadmap, but nonprofit backing suggests long-term commitment.
Active areas of work
Not explicitly visible from file structure alone, but the presence of .travis.yml indicates active CI/CD; README mentions 'Epic MegaGrants Recipient' suggesting recent funding and ongoing development. Check GitHub Issues and Releases tabs for current work; likely areas are parser robustness, editor features (Inky), and runtime optimizations.
🚀Get running
git clone https://github.com/inkle/ink.git
cd ink
# Build C# compiler
dotnet build compiler/Compiler.csproj
# Run testbed
dotnet run --project InkTestBed/InkTestBed.csproj
# Or compile a story
./inklecate myStory.ink
Daily commands:
Build: dotnet build compiler/Compiler.csproj. Execute: dotnet bin/Debug/inklecate.dll myStory.ink or use Inky editor (separate repo) for interactive development. InkTestBed test: dotnet run --project InkTestBed/InkTestBed.csproj. See build_release.command for distribution builds.
🗺️Map of the codebase
- compiler/InkParser/InkParser.cs: Core recursive descent parser entry point; tokenization and top-level language structure parsing happens here
- compiler/InkParser/InkParser_Expressions.cs: Handles expression parsing and evaluation logic—critical for variable assignments, conditionals, and runtime value computation
- compiler/InkParser/InkParser_Choices.cs: Parses choice syntax (* and +) and choice logic—fundamental to branching narratives
- compiler/InkParser/InkParser_Divert.cs: Parses flow control (-> jumps to knots/stitches); essential for non-linear narrative navigation
- compiler/Compiler.cs: Orchestrates parsing phases and JSON code generation; entry point for compilation pipeline
- Documentation/ink_JSON_runtime_format.md: Specification for the JSON output format—understand this to debug serialization or add runtime features
- InkTestBed/InkTestBed.cs: Manual test harness demonstrating story loading and playback; start here to understand runtime integration
🛠️How to make changes
Parser changes: Edit InkParser/InkParser_[Feature].cs files (each feature has its own partial class file—e.g., add choice syntax in InkParser_Choices.cs). Compiler logic: Modify compiler/Compiler.cs for codegen phases. New language construct: 1) Add parser method in appropriate InkParser_*.cs, 2) Update tokenization in InkParser.cs, 3) Add serialization logic in JSON format. Testing: Add .ink test cases to InkTestBed/test.ink and validate via InkTestBed harness. See Documentation/ArchitectureAndDevOverview.md for compiler pipeline details.
🪤Traps & gotchas
- Parser is hand-written recursive descent—no parser generator, so grammar is implicit in code. Changes require careful state management across InkParser_*.cs files. 2) Token stream is stateful—InkParser maintains a current position; easy to create lookahead bugs. 3) No visible unit test suite—only InkTestBed manual test. Adding features requires manual validation. 4) JSON output format is versioned—changes to ink_JSON_runtime_format.md must be backward-compatible or all runtimes (inkjs, Unity) must update simultaneously. 5) Include file handling (InkParser_Include.cs) is non-trivial—FileHandler.cs manages path resolution; test across relative/absolute/nested includes.
💡Concepts to learn
- Recursive Descent Parsing — Ink's entire parser (InkParser.cs and InkParser_*.cs) is hand-written recursive descent—understanding this pattern is essential to modify or debug parsing logic without a parser generator
- Abstract Syntax Tree (AST) — The parser builds an implicit AST (no visible tree structure in code) that the compiler then traverses to generate JSON; understanding AST traversal helps debug codegen bugs
- Divert Semantics and Scope Resolution — Ink's flow control (-> diverts, knots, stitches) is non-trivial—requires understanding variable scope, knot nesting levels, and dynamic vs. static target resolution in InkParser_Divert.cs
- Domain-Specific Language (DSL) Design — Ink is a DSL optimized for narrative—studying its choice syntax, tag system, and expression language teaches DSL tradeoffs between expressiveness and writer usability
- Code Generation to JSON — The compiler outputs a JSON format (ink_JSON_runtime_format.md) instead of bytecode or native code; understanding this serialization strategy is key to adding new language features that must survive runtime
- State Machine for Narrative Control Flow — Ink's runtime (defined in JSON) is essentially a state machine where each choice/divert transition mutates story state; this is the foundational model for understanding playback semantics
- Two-Phase Compilation (Parsing + Codegen) — Compiler.cs orchestrates separate parsing and code generation phases; understanding the separation allows modification of either phase independently (e.g., optimize JSON output without touching parser)
🔗Related repos
inkle/inky— Official editor for Ink stories; provides visual narrative graph and real-time preview—essential companion tool for this compilerinkle/ink-unity-integration— Unity plugin that packages this C# compiler and runtime; allows .ink stories to load and play within Unity gamesinkle/inkjs— JavaScript transpile of the Ink runtime; enables compiled .ink stories to run in browsers and Node.js (not the compiler itself)chapelr/chapelr— Alternative narrative scripting language with similar goals (branching narrative, choice management); useful for comparing design approachesChoiceScript/choicescript— Competitor narrative language by Choice of Games LLC; similar problem domain (interactive fiction), different syntax and feature set
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for InkParser modular components
The compiler/InkParser directory has 13 specialized parser modules (Expressions, Conditionals, Choices, Divert, etc.) but there's no visible test suite in the file structure. InkTestBed/test.ink exists as a manual test file, but no automated unit tests for individual parser components. This is critical for a compiler project to catch regressions when parsing complex narrative structures.
- [ ] Create Tests/ directory with InkParser subdirectories mirroring compiler/InkParser structure
- [ ] Add unit tests for InkParser_Expressions.cs covering all expression types and edge cases
- [ ] Add unit tests for InkParser_Choices.cs and InkParser_Conditional.cs with nested structures
- [ ] Add integration tests using test.ink and test_included_file.ink as fixtures
- [ ] Update .travis.yml to run tests in CI pipeline if not already present
Create GitHub Actions CI workflow to replace/supplement Travis CI
.travis.yml exists but GitHub Actions is now the standard for GitHub repos. A modern Actions workflow would improve visibility, faster feedback, and OS matrix testing. The repo lacks explicit test execution documentation in RunningYourInk.md showing how contributors should validate changes.
- [ ] Create .github/workflows/test.yml with matrix testing for Windows/Linux/macOS
- [ ] Configure workflow to build the compiler using the build_release.command script
- [ ] Add workflow step to run unit tests (from PR #1) and InkTestBed validation
- [ ] Document the CI/test setup in Documentation/RunningYourInk.md with specific commands
- [ ] Remove or deprecate .travis.yml with a note pointing to GitHub Actions
Add ParsedHierarchy documentation and missing visitor pattern tests
The ParsedHierarchy directory has 20+ AST node classes but Documentation/ArchitectureAndDevOverview.md likely lacks specifics on how the parse tree is constructed and traversed. Additionally, there are no visible tests for the visitor pattern used to traverse this hierarchy (common in compiler architecture).
- [ ] Expand Documentation/ArchitectureAndDevOverview.md with section 'Abstract Syntax Tree (AST) Structure' describing ParsedHierarchy classes and their relationships
- [ ] Add a diagram or table showing the inheritance hierarchy (FlowBase, IWeavePoint, INamedContent relationships)
- [ ] Create Tests/ParsedHierarchy/VisitorPatternTests.cs to test AST traversal and transformation
- [ ] Add example code in docs showing how to programmatically inspect compiled ink (e.g., walking a Knot tree)
- [ ] Document the role of ContentList, Divert, and Gather in controlling narrative flow
🌿Good first issues
- Add formal unit tests for InkParser_Expressions.cs covering arithmetic operators, string interpolation, and type coercion edge cases—currently relies only on InkTestBed manual testing.
- Document the internal AST node types and compiler intermediate representation in a new Architecture.md file with examples—ArchitectureAndDevOverview.md exists but lacks AST spec.
- Extend InkTestBed/test.ink with comprehensive test cases for divert edge cases (recursive knots, invalid targets, scope rules) and auto-validate output against expected JSON structure.
- Add syntax highlighting definitions for VSCode (launch.json and ink.code-workspace exist but .vscode/ink.tmLanguage-style syntax definition is missing)—Sublime3Syntax/ has working definitions that could be ported.
- Write a 'Compiler Pass Walkthrough' doc explaining the three phases: parsing → semantic analysis → JSON generation, with concrete examples from Compiler.cs.
⭐Top contributors
Click to expand
Top contributors
- @joethephish — 67 commits
- @joningold — 5 commits
- @tomkail — 5 commits
- @premek — 3 commits
- @Myonmu — 2 commits
📝Recent commits
Click to expand
Recent commits
35c63e5— Version 1.2.1 (joethephish)593292a— TR-49: No need to sort list items in ListWithSubRange (joethephish)4775bf3— Merge branch 'master' of github.com:inkle/ink (joethephish)6a7fa61— Universal builds of inklecate (i.e. official support for Apple Silicon) (joethephish)bbd2ed9— Merge pull request #966 from qyl27/fix-publish (joethephish)dbd49db— Merge pull request #942 from denisdefreyne/patch-1 (joethephish)5e30392— Fix nuget package info. (qyl27)ead3cab— Fix tiny typo in RunningYourInk.md (denisdefreyne)f4102e9— Merge pull request #926 from JasonnnW3000/master (joethephish)eb8c10a— Update LICENSE.txt, fix license year (JasonnnW3000)
🔒Security observations
The ink scripting language compiler codebase shows reasonable security architecture for a narrative scripting language. No critical vulnerabilities were identified in the static analysis based on available file structure and documentation. Main concerns are: (1) inability to audit dependencies due to missing package file content, (2) potential path traversal risks in file handling operations, (3) plugin system security considerations, and (4) error message handling. The project appears well-structured with no obvious hardcoded secrets, SQL injection risks, or XSS vulnerabilities visible. Recommendations focus on implementing dependency scanning, input validation hardening, and plugin system security controls.
- Medium · Missing dependency information for security audit —
Project dependency management (likely .csproj files). The package dependency file content is not provided, making it impossible to verify if the project uses vulnerable or outdated dependencies. This is critical for a compiled C# project that likely uses NuGet packages. Fix: Provide and regularly audit all NuGet package dependencies. Use tools like OWASP Dependency-Check or NuGet vulnerability scanners to identify outdated or vulnerable packages. Implement automated dependency scanning in CI/CD pipeline. - Low · Potential path traversal in file handling —
compiler/FileHandler.cs. The FileHandler.cs component handles file operations. Without visibility into the implementation, there's a theoretical risk of path traversal vulnerabilities if user input is not properly validated when constructing file paths. Fix: Implement strict path validation using Path.GetFullPath() and ensure all file operations are restricted to expected directories. Validate and sanitize all file path inputs before use. - Low · Plugin system security considerations —
compiler/Plugins/PluginManager.cs, compiler/Plugins/Plugin.cs. The codebase includes a plugin system (compiler/Plugins/) which could potentially load untrusted code if not properly restricted. Dynamic code loading poses inherent security risks. Fix: Implement strict plugin validation and sandboxing. Only allow plugins from trusted sources. Use code signing or integrity verification. Document plugin security requirements clearly. - Low · Insufficient error handling visibility —
compiler/InkParser/, compiler/Compiler.cs. Parser and compiler components handle complex language parsing. Overly detailed error messages could potentially expose sensitive information about the system or internal structure. Fix: Ensure error messages are user-friendly and don't expose system internals. Log detailed errors server-side only. Implement proper exception handling with appropriate message sanitization.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.