JSPM

plotos

0.1.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 6
  • Score
    100M100P100Q25920F
  • License MIT

A local-first CLI tool for story creation and management

Package Exports

  • plotos
  • plotos/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (plotos) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

PlotOS

A local-first CLI tool for story creation and management.

PlotOS helps writers create structured narratives with world-building, character management, conflict graphs, and plot generation.

Features

  • Plain Text, Local-first - All data stored as JSON, works offline
  • BYO API - Bring your own LLM API key (OpenAI, OpenRouter, DeepSeek, etc.)
  • Static Output - Generate shareable HTML plot pages
  • Four Core Schemas - World, Character, Conflict Graph, Plot
  • Narrative Engine - Generate plots from structured data
  • State Machine - Track project status from draft to published

Installation

# Install globally from npm
npm install -g plotos

# Or use with npx (no install required)
npx plotos init my-story

From Source

# Clone or download
git clone https://github.com/plotos/plotos.git
cd plotos

# Install dependencies
npm install

# Build
npm run build

# Link for global use
npm link

Quick Start

# Create a new project
plot init my-story
cd my-story

# Fill in world settings
# Edit memory/canon/world.json

# Add characters
# Edit memory/canon/characters.json

# Define conflicts
# Edit memory/canon/conflict_graph.json

# Check project health
plot doctor

# Validate data
plot validate

# Generate plot
plot build

# Export to HTML
plot export

# Publish to GitHub Pages
plot publish

Commands

plot init [name]

Initialize a new PlotOS project.

plot init my-story
plot init my-story --force  # Overwrite existing

Creates:

my-story/
├── plotos.json              # Project configuration
├── state.json               # Project state
├── memory/canon/            # Canon (locked) settings
│   ├── world.json           # World settings
│   ├── characters.json      # Characters
│   ├── conflict_graph.json  # Conflict graph
│   └── style_card.json      # Style guide
├── workspace/               # Working directory
│   ├── drafts/
│   ├── experiments/
│   ├── notes/
│   └── plot_variants/       # Plot versions
└── dist/                    # Output files

plot doctor

Diagnose project structure and configuration.

plot doctor
plot doctor --fix  # Auto-fix issues

plot validate

Validate project data against schemas.

plot validate
plot validate --strict  # Treat warnings as errors

plot build [version]

Generate plot from canon data.

plot build                    # Generate new version
plot build v002               # Specific version
plot build --model five_act   # Story structure model
plot build --scenes 30        # Target scene count
plot build --no-llm           # Generate without LLM
plot build --force            # Overwrite existing

plot lock / plot unlock

Lock or unlock canon settings.

plot lock                     # Freeze canon
plot lock --reason "Ready for publication"
plot unlock                   # Allow editing

plot export [version]

Export plot to HTML.

plot export                   # Export current version
plot export v002              # Export specific version
plot export --all             # Export all versions
plot export --runtime         # Generate runtime.json

plot publish

Publish to GitHub Pages.

plot publish
plot publish --dry-run        # Preview without publishing

plot preview

Preview exported plot locally.

plot preview
plot preview --port 8080

Project Structure

Canon Layer (memory/canon/)

Authoritative settings that should not be changed after locking.

  • world.json - World rules, systems, stakes, setting
  • characters.json - Character desires, fears, beliefs, arcs
  • conflict_graph.json - Conflict nodes, edges, sets
  • style_card.json - Narrative voice, prose style

Workspace Layer (workspace/)

Draft area for experimentation.

  • drafts/ - Draft content
  • experiments/ - Experimental variations
  • notes/ - Research and notes
  • plot_variants/ - Plot versions (plot_v001.json, etc.)

Publish Layer (dist/)

Generated output for sharing.

  • index.html - Version index
  • plot_v001.html - Plot page
  • runtime.json - Interactive mode config

Configuration (plotos.json)

{
  "name": "my-story",
  "version": "0.1.0",
  "provider": "openrouter",
  "model": "deepseek-chat",
  "api_key_env": "PLOTOS_API_KEY",
  "base_url": "https://openrouter.ai/api/v1",
  "language": "zh-CN",
  "template": "default",
  "generation": {
    "temperature": 0.7,
    "max_tokens": 4096
  }
}

State Machine

Init ──→ Draft ──→ Canon ──→ Published ──→ Interactive
  │        │         │           │             │
  └────────┴─────────┴───────────┴─────────────┘
                    (can iterate back)
State Description
Init Project created, no content yet
Draft World/characters/conflict in progress
Canon Settings locked, ready for generation
Published HTML exported and published
Interactive Runtime mode with user interaction

Schema Overview

World Schema

{
  "schema_version": "1.0",
  "world_id": "w_xxx",
  "title": "Story Title",
  "genre": ["fantasy", "adventure"],
  "premise": {
    "logline": "One-line story summary",
    "theme": "Core theme"
  },
  "axioms": [...],      // World rules
  "systems": [...],     // Power/magic systems
  "stakes": {...},      // What can be lost
  "setting": {...}      // Time, place, factions
}

Character Schema

{
  "schema_version": "1.0",
  "characters": [{
    "character_id": "c_xxx",
    "name": "Character Name",
    "role": "protagonist",
    "core": {
      "desire": "What they want",
      "fear": "What they fear",
      "belief": "Core belief"
    },
    "arc": {...},
    "relationships": [...]
  }]
}

Conflict Graph Schema

{
  "schema_version": "1.0",
  "graph_id": "g_xxx",
  "nodes": [
    { "id": "c_hero", "type": "character" },
    { "id": "goal_truth", "type": "goal" }
  ],
  "edges": [
    { "type": "wants", "from": "c_hero", "to": "goal_truth" },
    { "type": "blocks", "from": "c_villain", "to": "c_hero" }
  ],
  "conflict_sets": [...]
}

Plot Schema

{
  "schema_version": "1.0",
  "plot_id": "p_xxx",
  "structure": {
    "model": "three_act",
    "beats": [...]
  },
  "promises": {
    "reader_promise": [...]
  },
  "scenes": [{
    "scene_id": "s_001",
    "act": 1,
    "goal": "Scene goal",
    "turn": "Turning point",
    "outcome": "Result"
  }],
  "chapter_map": [...]
}

LLM Integration

PlotOS supports any OpenAI-compatible API:

# Set API key
export PLOTOS_API_KEY=your-api-key

# Configure provider in plotos.json
{
  "provider": "openrouter",
  "model": "deepseek-chat",
  "base_url": "https://openrouter.ai/api/v1"
}

Supported providers:

  • OpenAI
  • OpenRouter
  • DeepSeek
  • Anthropic (via OpenRouter)
  • Local models (Ollama, vLLM)

Development

# Development
npm run dev -- init test-story

# Build
npm run build

# Type check
npm run typecheck

License

MIT

Contributing

Contributions welcome! Please read the documentation in /docs for architecture details.