Docs SimOS

Simulated OS

The story plays as a fictional phone. Players swipe through messenger chats, scroll social feeds, take calls and read push notifications — all driven by your OmiScript.

Apps on the phone

Apps are registered in Studio → Apps, then opened from the script.

Switch the visible app with @app appId. The app must be registered in the Studio with a matching id. The template ships with messenger, social and phone apps out of the box.

apps.omi
@app chatter
// Everything after this lands in the 'chatter' app context

Messenger chats

Deposit messages into a chat thread and let the player reply.

Open a chat with @chat chatId. Lines inside the block drip in as messages. The ? reply: gate sends the player’s chosen line as their message.

messenger.omi
// Switch to a messenger-type app registered in Studio → Apps.
// All @chat content is deposited into that chat's message log.
@app chatter

// Open a specific chat — chatId must be registered under this app in Studio.
@chat chat_sarah
  // Messages drip in one at a time as the engine runs
  sarah: "hey, you there?"
  sarah: "hello??"

  // Reply gate — the player picks one option to send as their message
  ? reply:
    - "sorry, was asleep"
      player: "sorry just woke up lol"
      sarah: "okay good, we need to talk"
      // Track that the player replied — useful for branching later
      $replied_sarah = true
      -> Replied

    - "leave on read"
      // No player message — sarah gets no response
      -> Left On Read

## Replied
sarah: "meet me at the usual spot. 20 mins."
@end

## Left On Read
// Push a notification into the player's notification shade
@notify chatter "Sarah" "is waiting for your reply..."
@end

Social feed

Post into a feed and let the player comment on specific posts.

@post postId deposits a post into the active social feed app. The comment gate ? comment on appId postId: posts the player’s reply to that thread.

social.omi
## The Post
// Switch to a social_feed-type app registered in Studio → Apps
@app social_feed

// Posts deposit into the feed as the engine runs — displayed newest-first in the UI.
// 'image' is a logical name from Studio → Assets → CGs (no file extension).
@post post_morning
  by: sarah
  text: "Another late night at the office. Someone send help ☕"
  image: sarah_office
  likes: 12
  likeable: true

// Comment gate — the player picks a reply to a specific post.
// appId and postId must reference what's already been deposited above.
? comment on social_feed post_morning:
  - "Hang in there!"
    player: "Hang in there, you've got this!"
    sarah: "Aw, thanks 🥺"
    -> After Comment

  - "Say nothing"
    -> After Comment

## After Comment
// Push a banner notification into the player's notification shade
@notify social_feed "Sarah" "liked your comment"
"Your notification lit up a moment later."
@end

Premium feed

Subscriber-only content — lock posts behind a subscription gate.

Mark a post free: true to keep it always visible, or gate it with locked_until: and a teaser:. The ? subscribe to appId userId: gate lets the story itself drive the subscription.

premium.omi
## The Exclusive
// Premium feed — requires a premium_feed-type app in Studio → Apps
@app vip_feed

// free: true — always visible regardless of subscription status
@post post_free_001
  by: creator
  text: "Hey everyone, big news coming soon 👀"
  likes: 204
  likeable: true
  free: true

// locked_until — the post is blurred with a lock overlay until the condition is true.
// player_subscribed_to(appId, userId) is a built-in engine expression.
@post post_locked_001
  by: creator
  text: "Here's the full behind-the-scenes video from last night."
  image: bts_video_thumb
  locked_until: player_subscribed_to(vip_feed, creator)
  teaser: "Subscribe to unlock exclusive content 🔒"

// ? subscribe to — narrative-driven subscription gate.
? subscribe to vip_feed creator:
  - "Subscribe"
    creator: "Thank you so much! 🥺"
    // Persistent — survives across playthroughs, so future chapters know
    $$subscribed_vip = true
    -> Subscribed
  - "Maybe later"
    -> Skipped

## Subscribed
"The locked post shimmered and revealed itself."
@end

## Skipped
"The blurred post remained. For now."
@end

Phone & voicemail

Incoming calls, answer or decline, and missed calls that leave voicemail.

? call from charId: rings the phone — the player answers, declines, or taps End Call early (the - "hang up" branch). @voicemail vmId deposits a voicemail into the phone app.

phone_call.omi
## The Call
// Switch to a phone-type app registered in Studio → Apps
@app phone

// Incoming call gate — the player picks Answer, Decline, or another branch.
// Dialogue inside a branch becomes the in-call conversation in the Phone app.
? call from sarah:
  - "answer"
    sarah: "Hey. Are you alone?"
    player: "Yeah, why?"
    sarah: "I need you to listen carefully."
    sarah: "Don't come to the office tomorrow."
    -> After Call

  - "decline"
    // No in-call dialogue — goes straight to the branch body
    -> Missed Call

  // 'hang up' is a special branch — runs when the player taps End Call mid-conversation
  - "hang up"
    sarah: "...hello?"
    -> Hung Up

## After Call
"She hung up before you could ask anything."
@end

## Missed Call
// Voicemail — deposited into the phone app's voicemail inbox
@voicemail vm_sarah_001
  from: sarah
  duration: 0:12
  transcript: "It's me. Call me back. Please."
@end

## Hung Up
"You stared at the phone. Had that been a mistake?"
@end

Notifications

Push a banner into the player’s notification shade.

@notify appId "Title" "Body" drops a system notification the player can tap to jump back into that app.

notify.omi
@notify chatter "Sarah" "is waiting for your reply..."
@notify social_feed "Sarah" "liked your comment"

Storyomi Creator Docs

Back to Storyomi