An open standard for interactive stories

One story format. Every engine. Every tool.

Open Story Foundation is an open, versioned format for dialogues, characters and translations, stored as plain text. Build on it, ship it to any engine, and stop writing exporters.

Spec status: draft v1

arc_1_war/01_intro_scene.osf.osf
Versions {
  language = "1"
  story    = "v1"
  dialogue = "v1"
  i18n     = "v1"
}

Dialogue 01_intro_scene {
  Node node_03 {
    speaker: protagonist
    text: "Am I dreaming?"

    Option node_03_option_01 {
      next: node_04
      set: { is_dreaming: true }
      text: "Yes, you are."
    }

    Option node_03_option_02 {
      next: Dialogue.02_shadows_speak
      text: "No. Fool"
    }
  }
}
build/…/01_intro_scene.yamlOSF resource
apiVersion: dialogue/v1
kind: Dialogue
data:
  id: 01_intro_scene
  nodes:
    node_03:
      content:
        speaker: Character.protagonist
        text: Am I dreaming?
      options:
        node_03_option_01:
          next: node_04
          set:
            is_dreaming: true
          content:
            text: Yes, you are.
        node_03_option_02:
          next: Dialogue.02_shadows_speak
          content:
            text: No. Fool
  • Unity
  • Unreal
  • Godot
  • Your engine
  • Your tool
One file, read by any engine or tool that supports OSF. What osf build should emit for engines is an open question in draft v1.

The problem

Every team rebuilds the same plumbing.

01

Every tool invents its own format.

Studios can’t move content between tools without a rewrite.

02

Every engine needs its own exporter.

The same integration work is repeated by every vendor, for every engine.

03

Studios fear lock-in.

So they hesitate to adopt new tools, including yours.

From studios: [Demand evidence TBD, e.g. a quote or numbers from LoreHub v1 customers]

How OSF works

Two open layers. Write one, ship the other.

People write the .osf language, a brace-based syntax like Terraform’s HCL. It compiles to OSF resources: one YAML file per resource with apiVersion, kind and data, like Kubernetes manifests, described by a JSON Schema. A tool only has to read and write one of the two layers to interoperate.

Plain text, strict schema.

Readable by people, diffable in Git, parseable by machines and AI. YAML resources get completion and validation in VS Code, JetBrains and Neovim through the JSON Schema.

git diff
@@ arc_1_war/01_intro_scene.osf @@
     Option node_03_option_02 {
       next: Dialogue.02_shadows_speak
-      text: "No. Fool"
+      text: "No, fool."
     }

Versioned plugins.

Every resource’s apiVersion is <plugin>/<version>. One Versions block pins them all, so an upgrade is a one-line change, and a compiler that doesn’t support a listed version stops instead of guessing.

versions.osf
Versions {
  language = "1"     // version of this syntax

  story    = "v1"    // built in
  dialogue = "v1"    // built in
  i18n     = "v1"    // plugin
}

Translations built in.

Every text has a stable key. Translations live in one folder per language. Per language, choose whether a missing line is an error or falls back to the source.

story.osf
I18n {
  source = Eng
  Locale Rus "Russian"  { enforce = true }
  Locale Jpn "Japanese"
}
keyEngsourceRusenforce = trueJpnfalls back
Dialogue.01_intro_scene.nodes.node_01.content.textWhere am I?Где я?→ Where am I?
Dialogue.01_intro_scene.nodes.node_03.options.node_03_option_01.content.textYes, you are.Да, спишь.→ Yes, you are.
Dialogue.01_intro_scene.nodes.node_04.content.textStrangeСтранно→ Strange

Validate, format, build.

CLI in development

One CLI checks schema, references, variable types and translations, formats files for clean diffs, and compiles .osf to OSF YAML resources. Until it ships, the working checker is tools/validate.py.

terminalpreview
$ osf validate example
example/arc_1_war/01_intro_scene.osf:34:3: warning: Node node_04 in Dialogue 01_intro_scene is never reached
example/story.osf:11:3: warning: Jpn: 15 of 15 texts untranslated (not enforced)
example/arc_1_war/01_intro_scene.osf:23:13: error: Node node_03, Option node_03_option_01: next: node "node_05" does not exist in Dialogue 01_intro_scene

1 error, 2 warnings.

$ osf build example        # after fixing the typo
example/story.osf:11:3: warning: Jpn: 15 of 15 texts untranslated (not enforced)
Built 12 resources into example/build (2 dialogues, 2 characters, 1 variable, 15 texts).

Why join

Support OSF once. Grow with everyone who does.

This is an invitation, not a sale. One shared format grows everyone’s market, and nobody has to build it alone.

Your users keep their stories.

Studios adopt your tool without migrating content, and can leave without fear, which makes them more willing to come in.

Write one importer, not ten.

Support OSF once and read content written in every other OSF tool.

Keep what makes you different.

OSF is already split into versioned plugins (story, dialogue, i18n). Your tool’s own features belong in a plugin of their own, not a fork. [How third-party plugins are named and registered is not in the spec yet]

Shape the spec.

The v1 spec is a draft. Members help settle its open questions: gender and plural agreement in references, inline media, stable ids for save files, and the build output engines read.

Get listed as OSF compatible.

Once your tool’s output passes validation, it appears on the members page. [How “OSF compatible” is granted: open decision]

Build it with us.Join the foundation →

AI can draft it. The validator can check it. Humans review the diff.

Plain text with a strict schema is easy for language models to write, and every change can be validated before it merges.

Already built on OSF

One file, opened in two editors.

01_intro_scene.osf · Visual Studio Code
01_intro_scene.osf
1Dialogue 01_intro_scene {23  Node node_01 {4    next: node_025    speaker: protagonist6    title: "..."7    text: "Where am I?"8  }910  Node node_02 {11    next: node_0312    text: "Total Darkness surrounds you."13  }1415  Node node_03 {16    speaker: protagonist17    text: """18      What is it all about?19      Am I dreaming?20    """21    ...
01_intro_scene · LoreHub
node_01protagonistWhere am I?node_02narrationTotal Darkness…node_03protagonistWhat is it all about?Am I dreaming?Yes, you are.No. Foolnode_04StrangeDialogue02_shadows_speakset is_dreaming
The same 01_intro_scene.osf in VS Code (code only, with the OSF Language extension for syntax highlighting) and in LoreHub (visual node editor).

How to join

Four steps to OSF compatible.

  1. 1

    Read the spec and the JSON Schema.

    docs/spec.md and schema/osf-v1.schema.json. The format is small: Story, Character, Variable and Dialogue, plus the i18n plugin.

  2. 2

    Add OSF import and export.

    To your tool or engine. Read and write OSF YAML resources, the .osf language, or both.

  3. 3

    Validate against the example project.

    Run python3 tools/validate.py on your output and on osf/example.

  4. 4

    Tell us.

    Send the form below and get listed as compatible.

Join the foundation

Tell us what you’re building.

Engine teams and narrative tool makers welcome. Sending the form opens your email app with the details filled in.

Goes to [email protected][Join address is a placeholder until the mailbox exists]

FAQ

Questions tool makers ask.

Who owns OSF?

OSF is an open project started by Lostwood Games, the makers of LoreHub, inviting other tools to co-govern the spec. [Governance and what “Foundation” means: open decision]

What license is it under?

[License TBD] for the spec and tools. The OSF Language extension for VS Code is MIT.

Is it stable?

Not yet. The spec is draft v1. It is versioned so upgrades are explicit: a project pins every plugin version, and a compiler that doesn’t support a pinned version stops instead of guessing.

Do I have to use LoreHub?

No. LoreHub is the first visual editor built on OSF, and one implementation among the ones we hope to list here. Any editor that reads and writes the format works.

Can I add my own features?

Yes, that is what plugins are for: story, dialogue and i18n are themselves plugins. [Third-party plugin rules are still to be written into the spec]

What does it cost to join?

[Membership terms TBD: free or paid, any obligations]

Is there a CLI I can install?

Not yet. osf validate, osf build and osf fmt are in development. Today, tools/validate.py checks a project.