No description
  • TypeScript 91%
  • JavaScript 7.6%
  • Nix 1.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-07 23:59:59 -03:00
.forgejo/workflows Update to Node 26 2026-08-07 23:07:18 -03:00
src Has Pi UI 2026-08-07 23:59:59 -03:00
test Has Pi UI 2026-08-07 23:59:59 -03:00
.envrc Add pnpm and Nix development tooling (#2) 2026-07-30 19:01:34 +00:00
.gitignore Add pnpm and Nix development tooling (#2) 2026-07-30 19:01:34 +00:00
flake.lock Add pnpm and Nix development tooling (#2) 2026-07-30 19:01:34 +00:00
flake.nix Update to Node 26 2026-08-07 23:07:18 -03:00
GOAL.md docs: define world feast mission tasks 2026-07-29 22:26:02 -03:00
LICENSE Initial commit 2026-07-20 15:47:51 -03:00
package.json Add dev script 2026-08-07 23:17:27 -03:00
pnpm-lock.yaml Add dev script 2026-08-07 23:17:27 -03:00
pnpm-workspace.yaml Add dev script 2026-08-07 23:17:27 -03:00
README.md Has Pi UI 2026-08-07 23:59:59 -03:00
TODO.md chore: migrate to maintained Pi package 2026-07-30 10:41:00 -03:00
tsconfig.build.json Scaffold TypeScript CLI 2026-07-29 22:32:27 -03:00
tsconfig.json Scaffold TypeScript CLI 2026-07-29 22:32:27 -03:00
vitest.config.ts docs: complete mission verification 2026-07-29 23:44:34 -03:00

World Feast

World Feast is an interactive, Pi-backed CLI for continuing stories and keeping a Markdown world project consistent. Production workflows use Pi's public InteractiveMode, including native streaming, thinking display, tool cards, and scrollback. The simple line terminal remains available when tests inject input/output/sessionFactory.

Requirements and installation

Use Node.js 26 or later. From a source checkout:

corepack enable
pnpm install --frozen-lockfile
pnpm run build

# Use the current directory as the world project.
node dist/cli.js

# Or name a readable world-project directory.
node dist/cli.js /path/to/world

Nix users can build the pinned flake package instead:

nix build
./result/bin/world-feast /path/to/world

For development, the default flake shell provides Node.js and the pinned pnpm version. With direnv and nix-direnv installed, allow the checked-in .envrc once:

direnv allow
pnpm install --frozen-lockfile

The built command accepts zero or one world-project path. -h or --help prints usage without starting an interactive session. To make the built executable available as world-feast, run pnpm setup once to configure pnpm's global binary directory, start a new shell, then run from the source checkout:

pnpm link --global
world-feast /path/to/world

Model authentication

World Feast does not provide login, provider, or model command-line flags. It uses the installed Pi coding-agent SDK, with World Feast's config root set to ~/.config/world-feast by default or $XDG_CONFIG_HOME/world-feast when XDG_CONFIG_HOME is an absolute path. Configure the provider and model in that same root before starting World Feast:

PI_CODING_AGENT_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/world-feast" pnpm exec pi

In Pi, use /login to authenticate and /model to select a model. World Feast reads auth.json, models.json, and settings.json from this root. Provider environment keys supported by Pi can supply authentication instead. User Pi extensions for World Feast belong in ~/.config/world-feast/extensions/ or $XDG_CONFIG_HOME/world-feast/extensions/; project-local Pi extensions remain under <world-project>/.pi/extensions/.

World projects

World Feast discovers Markdown files recursively inside every top-level directory of the project. characters, groups, and stories are built-in groupings; any other top-level directory is a custom grouping, and custom groupings can contain arbitrary nested directories.

my-world/
├── characters/
│   └── mira.md
├── groups/
│   └── harbor-watch.md
├── stories/
│   ├── opening.md
│   └── arcs/
│       └── arrival.md
└── places/                 # custom grouping
    └── coast/
        └── breakwater.MD

Only regular Markdown files (.md, case-insensitive) within those directories are discovered. Files at the project root and symbolic links are ignored during discovery.

Story chronology

A story can begin with a YAML-style frontmatter block containing before and/or after lists. Both inline arrays and block lists are accepted:

---
before: [stories/opening.md]
after:
  - "../arrival.md"
---

The tide was already turning.

before and after express the story's chronology relative to the listed stories. A reference beginning with stories/ is a project-root story path. Every other reference is resolved relative to the directory of the story that declares it. Thus, from stories/arcs/arrival.md, stories/opening.md names <project>/stories/opening.md, while ../arrival.md names <project>/stories/arrival.md. References must resolve to discovered paths beneath stories/; missing and self-references are invalid. Before any mode starts, World Feast validates every discovered story. Malformed frontmatter and missing, outside-story, or self-references abort startup with affected paths and details; fix them before continuing.

Interactive workflows

Start the CLI, choose a workflow from the menu, and type chat requests. Story and single-file workflows then prompt for a project-relative target path. Consequences mode has no target prompt.

$ node dist/cli.js ./my-world
Welcome to World Feast.
Project: ./my-world
Your world files stay behind the selected workflow's safety boundary.
Type /switch to choose another workflow or /exit to leave.

┌─ World Feast ─────────────────────────────────────────────┐
│ Choose a workflow                                          │
│  1  Story        Draft and review an addition to a story    │
│  2  Single-file  Update one Markdown world file            │
│  3  Consequences Update non-story world records            │
│  4  Switch       Return to the mode menu                   │
│  5  Exit         Leave World Feast                         │
└───────────────────────────────────────────────────────────┘
Mode: 1
Starting Story mode (every proposal requires approval)…
Target Markdown file (or /switch, /exit): stories/arcs/arrival.md
Connecting to Pi…
Pi is ready.
Message (/switch to change mode, /exit to quit): Write the first exchange at the harbor gate.
You   Write the first exchange at the harbor gate.
Pi    The harbor gate was already crowded when the bell rang.

Select workflows with their number or name (story, single-file, or consequences). A target must be a project-relative Markdown file beneath a world grouping; story mode further requires a path beneath stories/.

Workflow Permission guarantee
Story The assistant has read-only research access and cannot mutate files directly. World Feast appends only prose that you accept (or edit and accept) to the selected story; this creates the selected story when it does not exist and never replaces existing bytes.
Single-file The assistant can create or update only the selected Markdown target; it cannot mutate any other path.
Consequences The assistant can create or update Markdown files canonically outside stories/, including genuinely distinct custom groupings; mutations through path or filesystem-identity aliases to stories are denied.

All modes enforce world-root-relative paths: absolute paths, traversal, and symbolic-link paths are rejected. Secure capability file operations require Linux with an accessible /proc/self/fd; elsewhere, World Feast fails closed with an actionable error rather than using race-prone pathname operations. Descriptor-anchored final operations resist concurrent replacement of ancestor paths.

Reviewing stories and changing modes

For every story response, World Feast displays a proposal and asks for a review:

┌─ Proposed story addition ─────────────────────────────────┐
The harbor gate was already crowded when the bell rang.
└───────────────────────────────────────────────────────────┘
Nothing is written until you approve it.
Review the displayed proposal: [a]ccept, [r]eject, [e]dit, /switch, or /exit: a

a/accept appends the proposal to the target story. r/reject discards it. e/edit asks for replacement prose and appends that instead.

At a target prompt, /switch (or /leave) ends the active workflow and returns to the mode menu. Inside native Pi, use /switch, /leave, or /exit; these are World Feast extension commands and shut down the current Pi screen cleanly. In story mode, Pi presents a native confirmation/input dialog after each assistant turn. The story is read-only to Pi and is appended only after accept or non-empty edit; reject/blank edit writes nothing. This review happens before the next native Pi turn, so the assistant transcript stays Pi-native without pretending the review is a chat message.