# omp-matrix-welcome

A Matrix-style start screen for [Oh My Pi](https://pi.dev) (`omp`). It draws
full-width digital rain with a block banner and an info panel showing the omp
version, the selected model and provider, the working directory, and your recent
sessions.

```
                              ████  ██  ██      ██   ██ ██   ██      ██████  ██████
                             ██  ██ ██  ██      ███ ███  ██ ██       ██   ██   ██
                             ██  ██ ██████ ████ ███████   ███   ████ ██   ██   ██
                             ██  ██ ██  ██ ████ ██ █ ██    ██   ████ ██████    ██
                             ██  ██ ██  ██      ██   ██    ██        ██        ██
                              ████  ██  ██      ██   ██    ██        ██      ██████

                         OMP      17.2.12
                         MODEL    Claude Opus 5  ·  anthropic
                         CWD      ~/code/oh-my-pi
                         RECENT   oh-my-pi  (12m ago)
                                  portfolio-site  (3h ago)
                                  scratch  (2d ago)

                                press any key to continue   8
```

The rain flows around the panel instead of through it, so the text stays
readable. Each column has its own speed and trail length, trails fade from a
white head through five shades of green, and banner cells occasionally flicker
into a rain glyph.

The screen dismisses itself when the countdown runs out, and immediately on any
keypress, when you submit input, or when the agent starts responding.

## Requirements

omp 17 or newer. There is no build step and no dependencies: omp loads the
TypeScript directly.

## Install

From npm:

```bash
omp plugin install omp-matrix-welcome
```

From this repository, which does not require an npm publish:

```bash
omp plugin install github:p1x3l4rtd3v/omp-matrix-welcome
```

Both routes register the package under `~/.omp/plugins` and load the entry
declared by `package.json#omp.extensions`. Add `--scope project` to install into
the current project rather than your user profile.

Restart omp afterwards. Extension modules are wired during session startup, so
`/reload-plugins` will not pick up a newly installed extension.

To check the install:

```bash
omp plugin list
omp plugin doctor
```

To remove it:

```bash
omp plugin uninstall omp-matrix-welcome
```

### Local development

Point the installer at a working copy instead of a published version:

```bash
git clone https://github.com/p1x3l4rtd3v/omp-matrix-welcome.git
omp plugin install ./omp-matrix-welcome
```

A local path is treated as `omp plugin link`, so your edits apply on the next omp
start without reinstalling.

## Turn off the built-in welcome screen

omp only builds its own welcome component when `startup.quiet` is off. Turn it on
and this screen is the only one that renders:

```
/settings  ->  Interaction  ->  Startup & Updates  ->  Quiet Startup: on
```

The same setting can live in `~/.omp/agent/config.yml` as `startup.quiet: true`,
though the `/settings` route is safer because omp writes that file itself.

## Configuration

Settings live in a JSON file outside the package, so upgrades never overwrite
them. The first file found wins:

1. `<project>/.omp/matrix-welcome.json`
2. `~/.omp/agent/matrix-welcome.json`

If `PI_CODING_AGENT_DIR` is set, or omp runs under `--profile`, the second path
follows that agent directory instead.

Every key is optional. A missing, malformed, or out-of-range value falls back to
its default and is reported by `/matrix-config`, so a typo never breaks startup.

```json
{
  "countdown": 5,
  "charset": "ascii",
  "density": 0.7,
  "bannerText": "MATRIX"
}
```

| Key | Default | Accepted | Meaning |
| --- | --- | --- | --- |
| `countdown` | `8` | 0 to 600 | Seconds before auto-dismiss. `0` waits for a keypress. |
| `frameDelayMs` | `70` | 16 to 1000 | Milliseconds between frames. Lower is faster rain. |
| `height` | `"full"` | `"full"` or 8 and up | Rows used. `"full"` fills the terminal. |
| `charset` | `"katakana"` | `"katakana"`, `"ascii"` | Rain glyphs. Use `"ascii"` if katakana render double-width. |
| `maxSessions` | `4` | 0 to 20 | Recent sessions to list. `0` hides the list. |
| `bannerFlicker` | `0.012` | 0 to 1 | Chance per frame that a banner cell flickers into a glyph. |
| `density` | `0.9` | 0 to 1 | Fraction of columns carrying a drop. |
| `bannerText` | `"OH-MY-PI"` | 1 to 16 chars | Banner text, folded to upper case. A to Z, 0 to 9, space and `- . ! ? : ; , ' " ( ) [ ] { } / \ \| + = * # @ & % $ _ < > ~ ^` are supported; anything else is skipped and reported by `/matrix-config`. |

Colours are 24-bit ANSI escapes in the `C` object in `index.ts`. They are not
configurable from the JSON file.

## Commands

| Command | Effect |
| --- | --- |
| `/matrix` | Replay the welcome screen, reloading the config file first |
| `/matrix-config` | Show the config file in use, the effective values, and any warnings |

`/matrix-config` is the fastest way to find out why a setting seems to be
ignored. It prints the exact path it read and one warning per field that fell
back to its default.

## Preview outside omp

```bash
npx tsx scripts/preview.ts
```

This renders the animation straight to your terminal with sample data, reading
the same config file the extension uses, so you can tune colours and speed
without restarting omp. Press Ctrl+C to quit.

The script lives in `scripts/` and guards its side effects behind an entry-point
check, so omp never treats it as an extension and importing it does nothing. That
guard matters more than it looks: omp's loader imports a candidate module before
it decides whether the module exports a valid factory, so a preview script with
top-level side effects would take over the terminal and, once its countdown
expired, call `process.exit` on the host session.

## Layout behaviour

- Every rendered line is padded to exactly the terminal width, so nothing wraps.
- When the terminal is too narrow for the block banner, or too short for the full
  panel, it falls back to a single-line banner and drops the session list.
- Below 24 columns it renders nothing rather than producing garbled output.
- Height comes from `process.stdout.rows`. If the top row looks clipped, set
  `height` to a couple of rows below your terminal height.

## How it works

- The default export is the extension factory that receives `ExtensionAPI`.
- The screen mounts through `ctx.ui.custom(factory, { overlay: true })`, which
  anchors it bottom-center at full width and gives it keyboard focus.
- Data comes from `ctx.model`, `pi.pi.VERSION`, and
  `pi.pi.getRecentSessions(ctx.sessionManager.getSessionDir(), n)`. Each one is
  probed defensively, so a change in omp degrades a single field rather than
  breaking the screen.
- Timers use `ctx.setInterval` and `ctx.clearTimer`. Those get the same isolation
  as handler dispatch, so a throw inside a frame cannot tear down the session,
  and they are cleared automatically on `session_shutdown`.
- Host types are described structurally in `index.ts`, which is why the package
  needs no dependency on omp's own types.

## Files

| Path | Purpose |
| --- | --- |
| `index.ts` | Extension factory, rain simulation, and renderer |
| `config.ts` | Defaults, config file lookup, and validation |
| `scripts/preview.ts` | Standalone preview, inert when imported |

## Troubleshooting

The screen does not appear. Check that the plugin is enabled with
`omp plugin list`, and that you restarted omp instead of running
`/reload-plugins`. In any non-interactive context, such as `--print`, RPC mode,
or a subagent, `ctx.hasUI` is false and the screen is skipped deliberately.

Two welcome screens appear. Set `startup.quiet: true` as described above, and
check that no other welcome extension is installed.

Settings appear to be ignored. Run `/matrix-config`.

Katakana glyphs look too wide or leave gaps. Set `"charset": "ascii"`.

## Publishing

```bash
npm publish --access public
```

`files` ships `index.ts`, `config.ts`, `scripts/`, the README and the licence,
which is six files in total. `omp plugin install` validates the manifest at
install time: every entry in `omp.extensions` must resolve on disk and import to
a factory function, and the install is rolled back if it does not.

## License

MIT
