Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/0x-unkwn0wn/simterm/llms.txt

Use this file to discover all available pages before exploring further.

A Simterm campaign is a self-contained RON file (or a directory holding one) that the engine loads at runtime. The framework itself ships no story content — every hostname, vulnerability, filesystem, narrative line, and visual theme is authored by you in data. The engine only provides the mechanics to interpret it. A campaign can be loaded from:
  • A directory that contains a campaign.ron file, or
  • A direct .ron file path.

Campaign struct fields

The top-level Campaign struct is the root of every campaign file. All fields except name and missions have safe defaults; define only what your campaign needs.
FieldTypeDefaultDescription
namestringrequiredCampaign name shown on launch.
languageen or esesLanguage for generic engine/UI text. Campaign story text is not auto-translated.
introstring list[]Lines displayed when the campaign starts.
missionsMission listrequiredOrdered mission sequence. Must not be empty.
themeThemeneutral defaultsBranding, prompt, grades, and cosmetic UI text.
easter_eggsEasterEgg list[]Hidden flavor commands that do not affect game state.
fortunesstring listgeneric defaultsTexts used by the fortune command (random pick).
signalsstring listgeneric defaultsPlain-text words used by the signal minigame.
achievementsCampaignAchievement list[]Campaign-defined achievements with declarative triggers.
commandsCampaignCommand list[]Declarative commands with state effects (flags, trace, achievements).
envstring→string map{}Environment variables for env, export, and $VAR expansion.
processesstring list[]Extra ps rows beyond those synthesized from services.
terminalTerminalCommand list[]Authored realistic shell commands for fictional CLIs (presentational only).

Minimal campaign skeleton

The skeleton below contains only the two required fields — name and missions — with a single host mission. Every omitted field uses its default.
Campaign(
    name: "My Campaign",
    missions: [
        Mission(
            id: "op1",
            name: "FIRST CONTACT",
            briefing: ["Map the host and recover the flag."],
            objective: Some("/root/flag.txt"),
            target: (
                hostname: "box-01.lab.local",
                ip: "10.0.0.10",
                os: "Linux 5.x",
                services: [
                    (port: 80, name: "http", version: "nginx 1.20"),
                ],
                vulnerabilities: [
                    (
                        id: "WEB-LFI",
                        name: "Local file inclusion",
                        affected_service: 80,
                        difficulty: 4,
                        stealth_cost: 5,
                        reliability: Reliable,
                    ),
                ],
                filesystem: [
                    Dir(name: "home", children: [
                        Dir(name: "op", children: [
                            File(
                                name: "id_rsa",
                                content: ["local key material"],
                                loot: Some((privesc_key: true)),
                            ),
                        ]),
                    ]),
                    Dir(name: "root", children: [
                        File(
                            name: "flag.txt",
                            content: ["FLAG{example}"],
                            root: true,
                        ),
                    ]),
                ],
            ),
        ),
    ],
)

Loading a campaign

Pass --campaign with the path to your campaign directory or .ron file:
cargo run -p simterm -- --campaign ./my_campaign

Campaign authoring workflow

1

Copy the sample campaign

Start from the bundled example so you have a working baseline:
cp -r examples/sample_campaign campaigns/my_campaign
2

Edit campaign.ron

Open campaigns/my_campaign/campaign.ron and replace the example content with your own missions, targets, filesystem trees, and theme text.
3

Run --check

Verify the file parses and contains at least one mission:
cargo run -p simterm -- --check --campaign ./campaigns/my_campaign
4

Run --doctor

Run the deeper semantic pass to catch dangling references, unreachable content, and out-of-range values:
cargo run -p simterm -- --doctor --campaign ./campaigns/my_campaign
5

Play

Launch the campaign and test the full loop:
cargo run -p simterm -- --campaign ./campaigns/my_campaign

Sub-pages in this section

Missions

Mission fields, entry vectors, endings, and multi-host networks.

Targets

TargetNode, services, vulnerabilities, and local privilege escalation.

Filesystem

Virtual filesystem, loot, hash puzzles, binaries, and encoding.

Commands

Easter eggs, declarative campaign commands, terminal commands, and achievements.

Theming

Theme struct, stealth grades, defense messages, fortunes, and signals.

Validation

—check vs —doctor, error and warning reference, and troubleshooting.
Campaigns are distributed separately from the Simterm framework. Your campaign directory is self-contained — players run it with simterm --campaign ./your_campaign. The framework is MIT licensed; your campaign content can use whatever license you choose.

Build docs developers (and LLMs) love