eenky is the desktop companion application for writing, compiling, and deploying Ink interactive fiction stories to your eenk device. It is forked from inkle's Inky but uses a new code editor and is extended with the eenk compilation pipeline, a pixel-accurate device simulator, and a USB Device Manager.
Download the latest eenky release for your platform from the GitHub Releases page, or build from source by following the build instructions.
Security Warnings Troubleshootinglink_2
This app is free, open-source software. Because official developer signing certificates carry significant annual fees, the current binaries are not officially code-signed.
As a result, your operating system might flag eenky as untrusted on first launch. Follow these quick steps to mute the false alarm:
"App is damaged and cannot be opened"
Modern macOS Gatekeeper quarantines unnotarized binaries downloaded from the internet. To unblock it:
- Move the app to your
/Applications folder.
- Open Terminal and run:
xattr -cr /Applications/eenky.app
- Launch the app normally.
"Windows protected your PC" / SmartScreen
Microsoft Defender SmartScreen flags downloads from unverified publishers:
- When the blue banner appears, click "More info".
- Click the "Run anyway" button at the bottom.
- CodeMirror 6 editor with Ink syntax highlighting
- Made for Ink - most of the niceties from Inky have been recreated, such as the live preview, universal search, knot browser, include management, live syntax parsing, snippets, bult-in ink documentation, web export, etc.
- Auto-player - enable the random choice fuzzer to test your story thousands of times in the background as you write, helping you spot softlocks and other issues.
- One-click compile - runs the custom
inklecate → inkcpp_cl → eenkPackage pipeline to produce a self-contained .eenk story package, automatically converts .ttf files to .epdfont format, and dithers and packs images into .media
- Built-in simulator - test your story and preview what it will look like on a simulated, pixel-perfect 800×480 e-ink display
- Device Manager - easily transfer stories and save files over USB, without ever pulling the SD card out (also available on this website).
- Flash Firmware - wizard-style flasher for installing and updating the firmware (also available on this website).
- Dark Theme - turn off the lights in one click.
Writing for eenklink_2
Welcome to the eenk authoring guide! This chapter covers the eenk-specific features that extend the standard Ink language when writing stories for the eenk firmware.
You can define metadata for your story by adding a block comment at the very top of your main ink file using @ tags. eenky parses these tags during compilation and bakes them into your compiled story package (.eenk file) so the device can display them in the library.
/*
@title My Amazing Story
@author John Doe
@font my-custom-font
@cover cover.png
@thumbnail thumb.png
*/
Once upon a time...
- @title: The title of your story (maximum 63 characters).
- @author: The author of the story (maximum 31 characters).
- @font: The stem name of the font you want to use for the story (maximum 15 characters). See Fonts in eenk below.
- @cover: The cover image will automatically be resized to fit the device screen (480x800) for the sleep screen. Using this tag will pack the image into the
.media sidecar inside your .eenk package, see Images in eenk below.
- @thumbnail: A separate image path to be used as a 156x156 thumbnail in the library list. If not provided, the cover image will be resized and used instead. Using this tag will also pack the image into the
.media sidecar.
Note: Metadata tags are all optional. The whole metadata header is, too: you don't have to provide it to compile an ink story for eenk.
Fonts in eenklink_2
By default, eenk uses the user's preferred font setting from the device menu. However, you can set a specific font for your story by using the @font metadata tag.
The runtime will attempt to resolve the font defined by the metadata tag in the following order: built-in, custom bundled, custom global (see below). Note that users can also choose to override the @font tag via firmware settings.
Built-in Fontslink_2
The device comes with built-in fonts that you can request directly by their token name:
sans (or sans-medium): The default sans-serif font, Reader, from the Papyrix firmware.
sans-small: A smaller variant of the sans-serif font.
serif (or serif-medium): The classic serif font (Literata).
serif-small: A smaller variant of the serif font.
If the token doesn't match a built-in font, the engine will look for custom .epdfont font files, first in the story bundle, then in the global fonts/ directory on the SD card.
Variants for Custom Fontslink_2
Font variants may also be provided by adding a suffix to the font stem. If the story contains bold text, the engine will look for my-custom-font-bold.epdfont. Supported suffixes are -bold, -italic, -bolditalic.
If the engine cannot find those variants, synthetic variants are generated from the base font as a fallback (but these are lower quality).
If the requested font stem cannot be found in any of the above locations, eenk will gracefully fall back to the user's device default setting, or the builtin font.
Text Formattinglink_2
eenk supports inline text styling in both narrative text and interactive choice options. You can use standard Markdown syntax or HTML tags.
Note: If you use formatting with a custom font, consider providing the necessary font variants (e.g., my-custom-font-bold.epdfont) in your story bundle. While eenk will automatically generate synthetic fallbacks (algorithmic emboldening and obliquing), having dedicated files ensures the best quality. See Variants for Custom Fonts.
| Style |
Syntax |
Example |
| Italic |
*text* or _text_ |
*whispers quietly* |
| Bold |
**text** or __text__ |
**DANGER AHEAD** |
| Bold & Italic |
***text*** or **_text_** |
***CRITICAL ALERT*** |
For backwards compatibility with classic Ink stories and Inky's HTML export, standard HTML formatting tags are also supported:
<i>...</i> or <em>...</em> for italic text
<b>...</b> or <strong>...</strong> for bold text
- Nested tags such as
<b><i>...</i></b> for bold italic text
<br>, <br/>, or <br /> to insert explicit line breaks within paragraphs
The guard stepped forward. <b>"Halt!"</b> he yelled.<br><i>He did not look pleased.</i>
+ [**Fight** the guard] -> fight
+ [<i>Reason</i> with him] -> reason
Images in eenklink_2
You can embed images in your story using the standard Ink # IMAGE: tag. eenky will automatically process these images during compilation and bundle them into an optimized .media sidecar file inside your .eenk story package.
# IMAGE: my-image.png
# IMAGE: https://example.com/online-image.jpg
- Local Images: You can reference local images by placing them in the same folder as your
.ink file (or a subfolder relative to it).
- Online Images: You can also provide a direct URL to an online image. eenky will download it automatically during compilation.
Note: eenky inherits the classic Web export mode from Inky, which also supports the very same # IMAGE: tag format for rendering images in the browser! What are the odds!?
Checkpoints and Chapterslink_2
eenk supports special tags to let players save snapshots of their progress and rewind during gameplay via the on-device Story Menu (accessed by pressing BACK or Escape in the simulator):
Checkpoints (# CHECKPOINT)link_2
Use # CHECKPOINT without a title when you want to offer an ephemeral quick-save or safe point where players can rewind once (for instance, right before a deadly combat choice, tricky riddle, or branching decision).
=== before_the_trap ===
# CHECKPOINT
You stand before three levers. A skull is etched above the center one.
+ [Pull the left lever] -> left_lever
+ [Pull the center lever] -> center_lever
+ [Pull the right lever] -> right_lever
- Each occurrence of
# CHECKPOINT updates the player's quick-save to that exact position.
- There is no visual clue that a checkpoint has been reached, it is left to you whether or not to reveal it (for example with an explicit
[checkpoint], or a subtler in-game message).
- In the Story Menu, this is presented as
Rewind to last checkpoint.
Chapters (# CHECKPOINT: <Title>)link_2
Use # CHECKPOINT: <Title> when you want players to be able to choose how far back to rewind across the story (e.g., acts, chapters, or major branching milestones).
=== act_one ===
# CHECKPOINT: Act I - The Heist
The neon signs of Sector 4 flickered against the perpetual rain...
...
=== act_two ===
# CHECKPOINT: Act II - The Escape
Sirens echoed in the distance as the hovercraft engine roared to life...
- Each named checkpoint is added chronologically to the Story Menu, under
Rewind to....
- Rewinding to a chapter will remove access to subsequent ones: it's a linear chain and you snip it when you rewind.
- There is no visual clue that a chapter has been reached, it is left to you whether or not to reveal it (for example with an explicit
Act I, or a subtler in-game message).
Building with eenkylink_2
eenky compiles your .ink files into a .eenk package file optimized for the eenk hardware. It uses a customized compiler pipeline (inklecate -> inkcpp_cl -> eenkPackage).
- Open your Ink project folder in eenky.
- Click the Build button in the toolbar (also available from the File menu or with Ctrl+B or Cmd+B keyboard shortcut).
eenky will automatically extract your metadata headers, compile the ink script, convert source .ttf fonts to .epdfont files, dither and pack images into .media, and bundle everything into a single .eenk story package.
You can play it immediately in eenky's simulator by clicking the device button in the toolbar (also available from the Device menu or with Ctrl+L or Cmd+L keyboard shortcut). This creates a temporary package in the simulator but does not save it.
Transferring to the eenk devicelink_2
To play your compiled story on the hardware device, use the USB Device Manager (recommended) or copy files manually via SD card.
Using the Device Managerlink_2
- Wake up your eenk device and remain on the library screen.
- Connect it to your computer via USB-C.
- Open the Device Manager in eenky (Ctrl+D / Cmd+D) or use the Web Device Manager.
- Click Connect and select the serial port.
- Drag and drop your
.eenk package file into the upload zone (or click Upload Story and select the .eenk file). The Device Manager will unpack, verify, display the cover preview, and stream all story assets into /stories/<story_name>/ automatically.
- Click Disconnect and the device will refresh to reveal your new story in the library!
Manual Transfer to SD Cardlink_2
Direct SD card copying is not recommended because the device firmware requires unpacked story files in subfolders rather than the single .eenk archive:
- Rename
mystory.eenk to mystory.zip and extract it on your computer.
- Remove the MicroSD card from your device and connect it to your computer.
- Create a folder under
/stories/ on the SD card (e.g. /stories/mystory/).
- Copy
story.bin and any companion files (.media for image data, .epdfont for custom fonts) into /stories/mystory/.
- Eject the SD card, re-insert it into your device, and power on.
Sharing Your Storieslink_2
You can, of course, share the .eenk file for others to upload by dragging it into the Device Manager.
There are also a couple of alternatives for an even smoother installation experience.
One-Click Install Deeplinkslink_2
You can also skip the manual download phase by providing a one-click installation link formatted as such:
https://t0mg.github.io/eenk/device-manager?url=https://example.com/mystory.eenk
Where https://example.com/mystory.eenk is the location of your compiled story file.
For this to work, you need a host that allows any origin in their CORS headers.
If you don't have a personal website, or don't know what CORS headers are, a good place to host your story for free is GitHub. Just provide the link to the file on GitHub in the url query parameter, and the Device Manager will handle the rest (via jsdelivr in this case).
Typically, if you prefer to host your story on a place like itch.io, the download will be blocked. In that case, submitting the Story to the showcase page (see below) is a viable alternative.
Stories Showcaselink_2
The online Stories Showcase also hosts free stories with a 1-click install button.
If you would like to add your story there, just open an issue on GitHub.