About Twine 1

Twine 1 was available only as a desktop app for Mac and Windows, and was written in Python (instead of JavaScript, which the current version is written in). As such, it doesn't have much in common with the 2.x release series.

Twine 1.4.3

Release Notes: January 1, 2022


Development program

Story Map

  • Signficantly improved the performance of the story map, with minor improvements to numerous other features. Thanks to Richard Lake and Maarten ter Huurne for this.
  • Potentially fixed a crash involving dragging passages.
  • Fixed a bug where pasting passages would sometimes place them in incorrect positions.
  • Added an "Update StoryIncludes Links" menu option, allowing StoryIncludes passage availability to be manually refreshed. This menu item will be disabled if StoryIncludes isn't present.
  • Added Option-Command-F as an alternative 'exit fullscreen' key command.


  • Now, closing StorySettings will refresh the StoryIncludes links automatically.
  • Now, you can include a .tws which itself contains a StoryIncludes passage.

Passage editor

  • Pressing control-A while typing in the passage title box should now correctly select the title text.
  • If you highlight a link with separate link text and passage title (such as [[link text|passage]]) then press control-L, a new passage named "passage" (instead of "link text|passage") is created.
  • In the "create passages" prompt given when you close a passage containing red links, the 'cancel' button now correctly cancels closing the passage.


  • Fixed a bug where you couldn't import Twine HTML files which had tags written in uppercase.
  • Fixed a bug where Twine HTML files with storeArea <div>s with the attribute "hidden" couldn't be imported.
  • Changed the MIME-type of imported TTF font files from "application/x-font-ttf" to "application/font-sfnt", and added "format(truetype)" to the generated @font-face CSS, and made similar changes for OTF fonts.

Story formats

  • Now, Twine will continue instead of crashing if, during startup, the last opened story's format isn't available. Also, it will properly error and quit if zero story formats are available (which should be unlikely).
  • Changed the naming of custom story formats' Python files from [story format name]/[story format name].py to [story format name]/header.py, in order to fix the issue where if a user renames the story format's directory, the custom Header file will no longer be found. However, old story formats which still use [story format name].py should continue to work correctly.

Game engine


  • Fixed a missing Y in the "got itself in a mess" error message.
  • The storeArea's passage is now read using textContent instead of innerText, fixing a number of minor bugs involving consecutive whitespace in passages being truncated.


  • Fixed a bug where the image syntax didn't work with images at external URLs.


  • Fixed a bug where variables saved via «remember» were unwittingly shared over all Twine stories accessed from the same website.
  • Fixed a bug in Jonah where certain internal link

Twine 1.4.2

Release date: June 2, 2014


Development program

Fatal errors

  • Now, building games in non-English locales should no longer get an encoding error caused by the built file's timestamp. Thanks to mth for assistance and Cab for the report.


  • The Story___ passages are no longer forbidden from being included via StoryIncludes.
  • The StoryIncludes passage is no longer broken on OS X.


  • Fixed buggy HTML importing for passages that have > symbols in their titles.
  • It is now possible to import from HTML files that use the SugarCube custom header.
  • Fixed imported images having the wrong MIME-type if their filename extensions were in all-caps (such as "tree.JPG").
  • Altered the MIME-type of imported fonts in ttf and otf format to "application/x-font-..." instead of "application/font-...". Also, unrecognised files are now "application/octet-stream". This shouldn't really change anything, but may improve browser support.

Story Map

  • The position of passages created by right-clicking and selecting "New Passage Here" should be fixed.
  • Fixed passage names with full stops no longer failing to have incoming link arrows.
  • Selecting "New Passage" when a Start passage is missing no longer creates the "Start" passage, since it could be irritating for "partial .tws files" that are being used in a large StoryIncludes project.

Passage editor

  • Passages with very long names no longer have the left half of their name scrolled out of the title text box when you initially edit them.
  • The passage editor now has a uniform tab width (set to 4 spaces).
  • Fixed a bug where HTML wouldn't be highlighted if its tag names or attribute names contained hyphens (e.g. <div data-tags="...">)

Game engine


  • Built HTML files now have a UTF-8 byte-order mark. This should cause Dropbox to correctly transmit them with UTF-8 encoding instead of ASCII. Hooray!!
  • Fixed certain page elements (such as StoryTitle and StoryAuthor) not being drawn at the start of a test play build that begins at a non-Start passage.
  • Fixed the image preloader code, which didn't detect whitespace correctly, and thus prevented preloading images in HTML <img> tags that had a space between "src" and "=".


  • You should now be able to put a ] character inside the link syntax (e.g. [[<<$obj[0].x>>|Passage name]]) and put a quoted ">>" inside the macro syntax (e.g. <<print "<<--cool-->>" >> ).
  • Shorthand [<<display>>](<>): variable default was causing $vars provided as arguments to mess up horridly. This should fix this.
  • Raw HTML entities (such as or < or somesuch) are now correctly preserved, rather than being converted to their symbols during the build process.


  • Using Passage() instead of passage() in your code will no longer silently fail instead of producing an error message.
  • <<choice>>, <<button>> and <<textinput>> no longer incorrectly convert Twine operators in the text of the provided link to Javascript operators (e.g. <<choice [[not]]>> becoming <<choice [[!]]>>).
  • The undocumented clone() function has been updated to hopefully allow certain native objects to be cloned more effectively.
  • A number of macro error messages are a little clearer - displaying "$" instead of state.history[0].variables." when referring to the macro invocation.
  • Fixed a bug where certain objects were being passed by reference when used in a setter link - e.g. [[Link][$a = $obj]] caused $a and $obj to point to the same object, with changes to one altering the other.
  • Fixed a bug where object literals as shorthand <<display>> arguments wouldn't work at all.
  • Fixed a bug where multi-line string or object literals in <<set>> or <<print>> macros, etc., would not have Twine operators converted by Wikifier.parse() correctly.

History/Back Button

  • Game history: Added a test for iOS Safari's private browsing mode, which does not disable sessionStorage but does reduce its quota to 0
  • making it hard to tell if it's actually usable. This causes the "couldn't save the state" alert to not pop up if you're playing in private mode.
  • The story state serialisation functions have been rewritten to allow basic Javascript functions stored in Twine variables to be decompiled and stored. Previously, using the Sugarcane back button or a bookmark would cause function variables to lose their value. (Of course, this relies on function decompilation, so bound functions and native functions' serialisation will silently fail. And, when recompiling them, their original scope is lost.)


  • Added Array.prototype.forEach(), Object.create() and Array.isArray() polyfills to the engine, allowing IE 8-compliant scripts to use them.
  • The engine now records the previous value of window.onerror, and restores it once the message has been displayed once.

New features

Development program


  • Added StoryInit, a special passage in which to put Twine macros that you want to run before every play - including Test Plays of specific passages. This is generally a more ideal place to put your initial <<set>> macros instead of the Start passage. Thanks to T. M. Edwards for pioneering this feature.

Error checking

  • Added a very basic passage code error-checking system. When closing a passage, Twine will now report a few possible errors: not matching an <<if>> macro with an <<endif>>, using "=" instead of "is" in the <<if>> macro, misspelling "http://" in a link, and putting HTML <script> tags in a script passage. (Less obvious errors can only be identified by your browser's Javascript engine, and will, as usual, only be identified at runtime.)
  • Also, when closing a passage, Twine will now offer to create new passages for each red link in the passage text. This potentially saves you having to create them yourself.
  • Also, when closing a passage, Twine will now offer to import all images, linked from URLs, into the story, and update the [img] references to match. Importing images is recommended because it saves you the bother of hosting the image files, keeps the story from breaking if your image hosting site is down, and allows you to host the HTML file on sites such as http://philome.la, which only allow single HTML files to be uploaded.
  • All of the above checks and helpers can be run from the "Verify All Passages" menu item in the Build menu, or the "Verify Passage" item in the passage editor's Passage menu.


  • Twine now tries to keep track of passages that aren't present in the file, but are included via the StoryIncludes feature (henceforth, "included passages"). Links to included passages are now mauve, and passages that link to included passages now have a mauve marker drawn on them in the Story Map.

Story Metadata

  • Added a "metadata" option to the Story Menu, which lets you edit some data that is included in the final HTML file.
  • The "identity" specifies a noun to use for game interface dialog boxes (the restart confirmation, the error dialog, etc.) If left blank, then "game" will be used.
  • The "description" provides text to use for a HTML <meta> description element, which is often used by search engines etc. to provide a summary of the page. I've noticed that often Google will, at a loss to find the game content, display odd bits of the storeArea div as a page description in its search results, which is most definitely not a good look. Maybe this will fix things.


Story Formats

  • Custom story formats can now supply a Python file, "header.py", which lets various parts of the Twine development program be customised to match the features of the story format. See the base header.py class, which your header.py file should subclass, for details.

Game engine


  • You can now use the inline syntax as a shorthand for the <span class="..."> HTML tag.
  • @@.robot;This is a robot-class span@@ is equivalent to <span class="robot">This is a robot-class span</span>.
  • You can also use it alongside style attributes: @@.robot;text-decoration:underline;This is a robot-class span with an underline@@
  • One bothersome fact about Twine up to now is that there's no real "bridge" between the basic Twine link's functionality and raw HTML. There was no convenient way to make a raw <a> link trigger a passage change. So, I've added a "data-passage" HTML attribute that you can put on HTML <a>, <img>, <map> and <area> tags.
  • <a data-passage="Distant woods">Some text</a> is equivalent to %%[[Some text|Distant woods]]%%, but allows you to add extra HTML attributes to the link, like "style".
  • <img data-passage="Trees"> is equivalent to %%[img[Trees]]%% - thus, you can now refer to imported images in HTML. (If you wish to make an image that links to a passage, put the <img> inside an <a> element.)
  • <area data-passage="Trapdoor" coords="..."> is how you can make an image map area link to a passage.
  • You can also attach data-passage to any other kind of tag to make it serve as a link, too: <span data-passage="Secret link">This looks like ordinary text</span>.
  • To simulate setter-links, you can also add a "data-setter" property, too. <span data-passage="Cellar" data-setter="$teeth += 2">Collect teeth</span>. Note that it does nothing without a data-passage attribute as well.
  • It should now be possible to supply variables to the image syntax, as an image passage name or URL - for instance, [img[$pictureName]].
  • Removed the quote-by-line [[syntax]], on the basis that a good number of people don't really want indenting that often, and would rather have greater-than signs as bullet points. The rest can rely on the indented block syntax (%%<<<%%) or HTML <blockquote> tags.

Generated HTML

  • Passage links no longer have ID attributes that reveal the name of the passage they go to, allowing anyone to "cheat" by right clicking them and selecting "Inspect Element". This has been the case for every previous version of Twine, but not anymore!
  • Jonah: rewind links now have the class "toolbar-rewind" instead of "toolbar-rewind to here".

Default CSS

  • Mobile Sugarcane layout: I've added a somewhat rudimentary media query to Sugarcane that converts the sidebar to a vertical header, using a minimum of alterations, when viewed on a 640px-width

Twine 1.4.1

Release Date: January 11, 2014


Bugfixes Development program

  • Potentially fixed the Windows VC++ runtime problem. If you haven't installed the VC++ 9 redistributable, the Twine installer should now correctly contain it.
  • Fixed «endnobr» consuming the three characters that come after it.
  • Fixed external link syntax highlighting.
  • Fixed syntax highlighting for shorthand «print» macros.
  • Fixed unmatched «endif» and «endsilently» macros not being syntax-highlighted red.
  • Removed the "Delete Passage" menu item in the Story menu, due to an identical entry being in the Edit menu.
  • External links and variable links are no longer considered broken links in the IDE.
  • Fixed annotation passages being drawn too dark in smooth drawing mode.
  • Fixed the monospace font using the normal font's size instead of its own. time. This should make HTML exporting/importing more symmetrical.
  • Improved speed of HTML importing.
  • The StorySettings passage is no longer converted to all-lowercase at build
  • Fixed an error when trying to replace a passage with one from animported file.
  • Now, the "no Start passage" warning is suppressed if a StoryIncludes passage is present.
  • Fixed importing from HTML sometimes failing to read passages correctly.

Bugfixes Game engine

  • Fixed passages with names containing quote marks being unrecognised by links.
  • Altered Sugarcane's browser state-saving to avoid a crash in Firefox caused by having lots of variables in your story.
  • Fixed HTML tables in passages not being constructed correctly.
  • Fixed TiddlyWiki emdashes not being rendered correctly.
  • Fixed the «nobr» macro inserting zero-width space characters into contained macro tags, thus breaking them.
  • Fixed bug preventing custom macros from being usable in StoryMenu etc.
  • Fixed the [img] syntax used in CSS stylesheets inserting a terminating semicolon, preventing further attributes from being used on the same line.
  • Added "vertical-align:bottom" to images to compensate for a line-height difference between XHTML Transitional and HTML5. Why is there a line-height difference? The person who can answer that is not on this Earth, but in Heaven.
  • Fixed the «nobr» macro not working if any text follows it.
  • Fixed «choice». Now, clicking a «choice» disables all .choice links in the passage, not just itself. This returns it to 1.3.5 behaviour.
  • Fixed variables used as array indexes not being parsed correctly.
  • Restored the left positioning of the Sugarcane sidebar.
  • Added support for "javascript:" and "data:" URIs in external links.
  • You can now use external links in the simple link syntax, such as [[http://example.net]].
  • Possibly broken pretty-links (as in, links with a separate link text and destination) are now no longer assumed to be external URIs unless they contain a protocol (like "http:"), or the symbols . / \ or #. This should make link debugging a bit easier.
  • Fixed the shorthand «display» macro tag's title sometimes being incorrectly parsed as its first argument.
  • Shorthand «display»: Attempting to access a parameter() that wasn't supplied make "variadic passages" (passages that can take multiple optional variables) will no longer throw an error, on the newly considered basis that it would difficult.
  • Fixed a bug where backslashes would be incorrectly converted to arbitrary letters if passage obfuscation was being used.
  • «back» now works better when Undo is off in Sugarcane. Previously it would mess up the variable state in cases when link variables were in use.
  • «back» and «return» now work when restoring a Jonah state via bookmark.
  • «back» also now works when clicked in a past Jonah passage - previously it would act as if it was in the present passage.
  • «back» now works in the StoryMenu, StoryAuthor, StoryTitle and StorySubtitle passages.
  • «choice» now produces an error message if it's used in the StoryMenu, StoryAuthor, StoryTitle and StorySubtitle passage.
  • Fixed Jonah scrolling in IE 8.
  • Now, only the StoryTitle passage's text content will be used for the window title, instead of its raw code.
  • Now, if a story has no StoryTitle, or the StoryTitle has no text content, it will default to the name of the .tws file used to build it, instead of just "Untitled Story".
  • Fixed a bug where putting "Lookup:" in the StorySettings could potentially crash the game.
  • Added a sanity check in case a script overrides History.prototype.display() but doesn't pass enough arguments (since in 1.4 it takes 4 arguments instead of 3).
  • Fixed HTML <table> structures in passages not being rendered correctly.


Additions to Development program

  • IDE tag colours now vary between shades of orange based on the hash of the tags, to help differentiate dissimilarly tagged passages from a distance.
  • Added a Preferences option for showing the faint connector arrows for image and stylesheet passages.
  • Passages displayed via the shorthand «display» syntax now result in connector arrows being drawn.

Additions to Game engine

  • The StoryMenu now auto-updates when you change passages!! The code is re-executed and re-rendered into the element. This means you could, say, «print» a variable inside it, and it would update automatically. (This change also applies to StoryAuthor, StoryTitle and StorySubtitle).
  • Added the tags() function, which takes one or more strings and returns an array of the tags of the given passage (or the current passage if no name is supplied).
  • Added passage(), which simply holds the name of the current passage (If a passage is being «display»ed by another, passage() is the name of the “topmost” passage.)
  • Added turns(), which provides the number of turns that have elapsed in the current game.
  • Added visitedTag(), which returns the number of times passages with the given tag have been visited. Provide multiple tags to only search for passages that contain both.
  • Added 'header' and 'footer' elements to Jonah's .passage elements, to provide a bit more symmetry with Sugarcane's DOM layout.
  • The CSS selector “:link” in stylesheets is now converted to [class*=Link] at runtime. This is to provide backwards-compatibility for people who used “a:link” to refer to Twine links (which is no longer usable as internal links no longer have href attributes). It's a mean sight of a hack, but so be it - I shan't be adding back the "javascript:void(0)" href no matter what you say.
  • Added the "visitedLink" class, which is applied to passage links that link to already visited passages. “:visited” is converted to “.visitedLink” much like the above. This provides a surprising amount of power - you can give .visitedLink “display:none”, for instance, to make links to all visited passages disappear automatically.
  • Re-implemented «textinput». It creates an <input> text element which, when a <button> element is pressed, sets the variable to its string contents. It may also have an additional parameter, a link expressed in link syntax, which is used to create a <button> next to it. Examples: <<textinput $name>>, <<textinput $name [[Submit|Next passage]]>>.
  • The previous 1.3.6 «textinput» behaviour of triggering the passage change via pressing the Enter key has been removed for now.
  • Added «radio». Its arguments are a variable, and a number of strings for each option. When a <button> is pressed, the label of the selected radio button is put into the variable. Example: <<radio $feel "Strongly agree" "Strongly disagree">>. If you have multiple «radio» macros that refer to the same variable, they're treated as part of the same set.
  • Added «checkbox». It's similar to «radio», having identical syntax - but it sets the variable to an array value containing all of the checked boxes' labels as strings. Example: <<checkbox $weapons "Pistol" "Newspaper" "Letter opener">>.
  • Added «button», a macro that takes a link as its argument and creates a <button> element. Use it for passages which use «radio» or «checkbox», or a «textinput» set. Example: <<button [[Let's go!|armoury]]>>
  • As a counterpart to the alert() raised when a script fails to load, window.onerror is now set to issue a one-time alert() signifying that a Javascript error has occurred during play. Feel free to contact me or use the forum if you find the message mystifying.
  • StoryMenu now honours the 'nobr' passage tag.
  • Built HTML files are now timestamped.
  • Upgraded the built-in jQuery module to version 1.11.
  • Changed Responsive's footer to a sticky footer, like God and all His hideous bat-faced angels originally intended.
  • Altered Responsive's CSS to make the body background easier to change.
  • Altered the CSS for all targets to make StoryMenu contents display better.
  • Individual script or stylesheet passages may request the inclusion of jQuery or Modernizr, overriding the StorySettings options, by including in their code the case-insensitive string "requires jQuery" or "requires Modernizr". This enables jQuery-using scripts or Modernizr-using CSS to be easily pasted into stories without requiring any other modifications to the story.

Twine 1.4.0

Release Date: December 10, 2013

Game engine


  • You can now mix HTML tags and passage syntax in your story, without needing the <html> syntax. (It still remains for backwards-compatibility).
  • You can now use variables in place of a passage name in the link syntax - [[Exit|$placeName]] now creates a link to the passage whose name is in the $placeName variable. You can also do [[Back|previous()]] to replicate the <<back>> macro.
  • Also, you can write [[link text|passage name][$var = value]] to make a passage or external link that changes a variable when it's followed! The code section is treated as if it were arguments to a <<set>> macro. This syntax addition should work with <<choice>> macros (but not the [img] syntax). You can set multiple variables by separating them with a semicolon.
  • As a shorthand for <span style="...">, the TiddlyWiki inline style syntax is available. Type @@, then list CSS style attributes separated and terminated with semicolons, then put the passage text (including any other formatting and macros) ending with another @@. Example: @@font-size:2em; text-decoration: underline; Hello there!@@
  • Ending a line with \ will cause that line break to be removed from the rendered text. This can be useful when dealing with long chains of <<if>> macros.


  • <<remember>> now uses HTML5 Local Storage, which means it can now work even in an offline HTML file. Also, it can remember multiple variables given in a compound statement (like <<remember $a = 1, $b = 2>>).
  • Added <<forget>>, which undoes the effects of <<remember>>.
  • <<choice>> can now accept arguments phrased using the link syntax, e.g: <<choice [[a trapdoor?|falling]]>>. This saves the trouble of having to account for its inconsistent argument order.
  • <<nobr>> and <<endnobr>> remove all the line breaks in the text between them. They should be used instead of <<silently>> to enclose groups of macros.
  • The <<else if>> macro, which can also be written as <<elseif>>, allows you to essentially have multiple <<if>> macros chained together, without needing to nest each of them within the <<else>> / <<endif>> tag pair of the other.
  • You can also use variables in place of a passage name in <<display>>. For instance, <<display $name>> is now valid.

Shorthand macros

  • You can now write a shorthand form of <<print $variable>> like so: <<$variable>>. Note that this only works for printing just variables - not functions or anything else.
  • You can now write a shorthand form of <<display "Place">> like so: <<Place>>. Note that this only works for passages whose names do NOT contain spaces. Also, it can only be done with specific named passages - not variables or anything else.
  • You can supply additional arguments to the shorthand <<display>> macro - in effect, you can "call" passages as if they were macros. (Note: you cannot supply arguments to the longhand <<display>> because they will be interpreted as part of the passage name - for instance, <<display Cellar 2>> will try to display "Cellar 2" instead of "Cellar" with an argument of 2.)

Macro syntax/functions

  • You may now use "to" in macros instead of "=", and "is" instead of "eq". I think we can all agree it's too easy to confuse "=" with "eq", so you can instead write <<set $darts to 4>> for more readable code.
  • Strings containing 'and', 'or', '$' and other Twine operator symbols can be used inside macros without them changing into Javascript symbols.
  • Now you can put greater-than signs inside macro tags, such as <<set $arrow to "-->">>
  • All new variables are now 0 by default, regardless of whether you've <<set>> them or not.
  • Added either(), a function that randomly picks one of the things given to it.
  • Added visited(), a function that returns the number of times you've visited the given passage.
  • Added previous(), a function that returns the name of the previous passage visited.
  • If this passage is being included by a shorthand <<display>>, the parameter() function returns one of the space-separated terms in the macro invocation, parsed to a value. The function's argument is a zero-based index - parameter() or parameter(0) returns the first parameter, parameter(1) the second, and so forth.

Macro coding

  • setTransitionCSS() replaces the contents of the #transitionCSS <script> element with the passed string. This allows you to completely override the default transition CSS without it cascading down. I'm offering this as a JS function because many transitions will also require some extra JS, and being able to provide the complete transition code in just a script is desirable.
  • prerender and postrender are new objects whose function properties are executed every time the passage is rendered. The functions added to them take one argument: the resultant .passage .content element. Their 'this' value is the Passage object being rendered.

Passage tags

  • An alternative Tag CSS approach! Now, taking a stylesheet passage and adding an extra tag to it (in addition to "stylesheet") will cause that stylesheet to only be applied for passages with that given tag. (This, I feel, is a bit tidier than the old Tag CSS method - the [data-tags] selector need not be repeated dozens of times in a stylesheet, and applying only to the 'body' or '.passage' selectors. Although, it is slightly less flexible w/r/t tag hierarchies - the :not[data-tags] selector can't really be replicated.)
  • Twine now uses CSS transitions for passages appearing and disappearing. Giving a stylesheet passage the tag "transition" will cause that stylesheet to replace the default "fade-in" transition CSS, letting you define your own transition without having to override the other one's properties.
  • The special "nobr" passage tag removes line breaks from the whole passage.


The StorySettings passage enables a number of special story options to be set.

  • Undo: enables the player to "undo moves". In Sugarcane, this means being able to use the Back button in the browser. In Jonah, this means being able to use the "Rewind to here" link, and being able to click links in previous passages.
  • Bookmark: enables the player to use the "Bookmark" link in Sugarcane and Jonah. On by default.
  • Obfuscate: obfuscates the story's HTML source to prevent people from spoiling themselves by reading it. Off by default.
  • jQuery: set this on if you are using custom scripts that rely on the jQuery library. Otherwise, leave off. Note: Twine 1.4 relinquishes control of the "$" variable, so jQuery can now use it without $.noConflict().
  • Modernizr: set this on if you are using custom scripts that rely on the Modernizr library. Otherwise, leave off.


  • All passages are now added to the bottom, regardless of where you click the link.
  • Clicking a link that leads to a previously displayed passage will display a new version of the passage at the bottom, instead of scrolling up to the old version.
  • Clicking a link in a past passage in Jonah now rewinds the game state to that passage before following the link. This gives the author a greater level of control over the game state - it's no longer possible to re-use old links from earlier in the story that no longer make sense in the current context. (Note: Switching off the "Undo" StorySetting disables all links in past passages.)
  • <<back>> is now usable in Jonah. When used in Jonah, a <<back>> link removes the contained passage, plus any prior passages (as given by the "steps" argument or a passage name argument).


  • Removed the "Share" menu.
  • The "Rewind" menu is only visible if any passage has been tagged with 'bookmark'.
  • Added a "Bookmark" menu item, which produces a link to the current passage.
  • HTML5 History is now used to control the browser's Back and Forward buttons, and the <<back>> and <<return>> macros, in Sugarcane. This means that several bugs related to these are now fixed, and they should now work alongside random macros, player-input macros, and other such things.
  • <<choice>> is now usable in Sugarcane. It now creates a link that can only be clicked once in the whole story.
  • The sidebar now has position:absolute instead of position:fixed.


  • Added a <noscript> tag to alert the reader that Javascript is off.
  • Made it so that raw HTML <a> links in stories are styled as if they were proper externalLinks, in case the author unwittingly used the former in ignorance of the latter (a not uncommon occurence).
  • The passage content element, formerly classed "body" in Jonah and "content" in Sugarcane, now has a class of "body content" to match legacy CSS for both.

Development program


  • Special passages (Start, StoryAuthor, stylesheets, etc.) have different-coloured title bars. I've tried to stick with earthy hues in keeping with the colour scheme of the Twine icon, with redder hues used for stylesheet and script passages.
  • Passage tags are displayed in a peach ribbon along the bottom of the passage box.
  • Annotation passages are non-playable passages tagged with "annotation" that hold text to display on the story map, to annotate, comment or document the source code of the game. They have a different colour and size to normal passages.
  • Connection lines representing <<display>> macros are drawn with a bluer tint.
  • The position of newly created passages is much less arbitrary - passages will be placed closer to the expected area.
  • Altered the Greeking of zoomed-out passages to reflect the actual passage text length.
  • Selected passages now have their link arrows thickened to visually offset them.
  • Passage tooltips now display a preview of the passage's text (up to 840 characters).
  • Tagged stylesheets have arrows linking them and any passages with the same tag.


  • Added "Import From Compiled HTML" option, letting the author recover passages from built games.
  • Importing .twee source code no longer discards all the passage tags in the imported passages.
  • The "Proofing Copy" export option renders a few more markup styles better.


  • The "Test Play" menu item builds the game to a temp file, letting you run the story without having to have saved it to a specific filename first.
  • You can also right-click a passage and select "Test Play From Here" to start playing from that particular passage.
  • The "StoryIncludes" passage allows the passages inside other .tws or .twee files to be imported into this passage during building. If your game is particularly huge, you can divide it into a bunch of smaller .tws/.twee files, then add the filenames of these partial .tws/.twee files to one "main" file's StoryIncludes passage. All the passages in those files will then be copied into the main story at build time.
  • Added "Auto Build", a menu option that is only available when used with a StoryIncludes passage. If this is set, then when any one of those smaller .tws/.twee files is modified, the story is automatically rebuilt and can be tested in-browser. This requires both files to be open at the same time, though.

Passage editing

  • Passage titles must now be unique. The passage title input will turn red to indicate non-uniqueness.
  • Passage titles may no longer contain the | and ] symbols, due to such names being difficult to link.
  • Vastly improved the passage syntax highlighter.
  • Added very basic stylesheet CSS syntax highlighting.

Images and fonts

  • You can now add image files to the story file. These are stored as 'image passages' which can be included in passages using the image syntax: [img[imageName]] displays the image. Images are also embedded in the final HTML file, and don't need to be hosted elsewhere. Supported image file extensions are GIF, PNG, JPEG, SVG and WebP.
  • You can now embed font files, which can then be used in stylesheets, or, if you don't know CSS, the <font> element. Fonts are simply imported as stylesheet passages containing the font file in base64 encoding. Supported font file extensions are TTF, WOFF, OTF and SVG.


Twine 1.3.5

Release Date: November 22, 2009


I've just put out a new release of Twine, which I'm dubbing 1.3.5 because there aren't many new features to this one. Instead it has a number of bug fixes and optimizations -- in particular, you should see a significant speedup when working with large story files. This version also brings compatibility with OS X 10.6. I think it should work with earlier versions of OS X as well, but as always, I only have access to one version of OS X so let me know whether this is actually true.


Twine 1.3.0 / Twee 1.7.0

Release Date: October 10, 2009


  • Much faster story map updating, including an option to drop drawing quality for increased speed.

  • Syntax highlighting for passage editing, including different colors for broken links.

  • Several bug fixes, including one affecting the <<actions>> macro.

Twee 1.7 is pretty much the same as before, only with macro bugfixes.


Twine 1.2.0

Release Date: September 7, 2009


  • Links between passages are now shown as an arrow, with the source pointing to the destination.

  • Find and replace is now available, both in a passage editor window as well as global find/replace for a story.

  • The interface, especially for OS X users, has been polished. It now remembers your preferences as far as snapping to a grid and whether to show the toolbar.

It does fix two major bugs: one where Twine would save a story file to where it was last saved, even if you moved it after closing and re-opening Twine, and another where story files could not be opened on a different platform from where they were created. In order to make your story file cross-platform, you must re-save it after opening it in 1.2, and you also need to open it on the other platform in 1.2.


Twine 1.1.0 / Twee 1.6

Release Date: August 21, 2009


Twine 1.1 is purely a bugfix release; no new features have been added to the editor or to the Sugarcane template. It does include an update look for the Jonah template that brings its appearance more in line with Sugarcane. Twee 1.6 is identical to 1.5.1 except for the updated templates.


Twine 1.0.0

Release Date: June 29, 2009


Twine is a GUI for creating stories with Twee. It allows you to map out your passages visually and see links between them. It also has a simple editor integrated with it that has a fullscreen mode, so you can use it to compose text as well. Finally, you can build to the same Sugarcane and Jonah templates as you have with other, existing tools.