npm package: @oh-my-pi/cli
Description: Plugin manager for pi - install and manage pi config plugins from git repos
Author: Can Bölük
Latest version: 1.3.3710

<p align="center">
  <img src="https://raw.githubusercontent.com/can1357/oh-my-pi/main/assets/banner.png" alt="Oh My Pi" >
</p>

<p align="center">
  <strong>
    Think oh-my-zsh, but for <a href="https://github.com/badlogic/pi-mono">pi</a>.
  </strong>
</p>

<p align="center">
  <a href="https://www.npmjs.com/package/@oh-my-pi/cli"><img src="https://img.shields.io/npm/v/@oh-my-pi/cli?style=flat&colorA=222222&colorB=CB3837" alt="npm version"></a>
  <a href="https://github.com/can1357/oh-my-pi/blob/main/CHANGELOG.md"><img src="https://img.shields.io/badge/changelog-keep-E05735?style=flat&colorA=222222" alt="Changelog"></a>
  <a href="https://www.npmjs.com/package/@oh-my-pi/cli"><img src="https://img.shields.io/npm/dm/@oh-my-pi/cli?style=flat&colorA=222222&colorB=28A745" alt="npm downloads"></a>
  <a href="https://github.com/can1357/oh-my-pi/actions"><img src="https://img.shields.io/github/actions/workflow/status/can1357/oh-my-pi/ci.yml?style=flat&colorA=222222&colorB=3FB950" alt="CI"></a>
  <a href="https://github.com/can1357/oh-my-pi/blob/main/LICENSE"><img src="https://img.shields.io/github/license/can1357/oh-my-pi?style=flat&colorA=222222&colorB=58A6FF" alt="License"></a>
  <a href="https://www.typescriptlang.org"><img src="https://img.shields.io/badge/TypeScript-3178C6?style=flat&colorA=222222&logo=typescript&logoColor=white" alt="TypeScript"></a>
  <a href="https://github.com/can1357/oh-my-pi/pulls"><img src="https://img.shields.io/badge/PRs-welcome-A855F7?style=flat&colorA=222222" alt="PRs welcome"></a>
  <a href="https://bun.sh"><img src="https://img.shields.io/badge/runtime-Bun-f472b6?style=flat&colorA=222222" alt="Bun"></a>
</p>

---

## Core Plugins

|                                                                                                                                                | Plugin                                                   | Description                                                                    |
| ---------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------ |
| [![npm](https://img.shields.io/badge/npm-FF4F84?style=flat&logo=npm&logoColor=white)](https://npmjs.com/package/@oh-my-pi/subagents)           | **[subagents](./plugins/subagents)**                     | Task delegation with specialized sub-agents (task, planner, explore, reviewer) |
| [![npm](https://img.shields.io/badge/npm-31D6FF?style=flat&logo=npm&logoColor=white)](https://npmjs.com/package/@oh-my-pi/lsp)                 | **[lsp](./plugins/lsp)**                                 | Language Server Protocol for code intelligence, diagnostics, and refactoring   |
| [![npm](https://img.shields.io/badge/npm-00E1B3?style=flat&logo=npm&logoColor=white)](https://npmjs.com/package/@oh-my-pi/basics)              | **[basics](./plugins/basics)**                           | Essential tools: rg (ripgrep), glob (fd), replace-all (sd), ast (ast-grep)     |
| [![npm](https://img.shields.io/badge/npm-FF9638?style=flat&logo=npm&logoColor=white)](https://npmjs.com/package/@oh-my-pi/exa)                 | **[exa](./plugins/exa)**                                 | Exa AI-powered web search, company/people lookup, and websets                  |
| [![npm](https://img.shields.io/badge/npm-BDFF4F?style=flat&logo=npm&logoColor=222)](https://npmjs.com/package/@oh-my-pi/perplexity)            | **[perplexity](./plugins/perplexity)**                   | Perplexity AI search with Sonar models (fast and pro)                          |
| [![npm](https://img.shields.io/badge/npm-A855F7?style=flat&logo=npm&logoColor=white)](https://npmjs.com/package/@oh-my-pi/anthropic-websearch) | **[anthropic-websearch](./plugins/anthropic-websearch)** | Claude web search using Anthropic's built-in web_search tool                   |
| [![npm](https://img.shields.io/badge/npm-D7A6FF?style=flat&logo=npm&logoColor=222)](https://npmjs.com/package/@oh-my-pi/user-prompt)           | **[user-prompt](./plugins/user-prompt)**                 | Interactive user prompting for gathering input during execution                |
| [![npm](https://img.shields.io/badge/npm-4FF1FF?style=flat&logo=npm&logoColor=222)](https://npmjs.com/package/@oh-my-pi/init)                  | **[init](./plugins/init)**                               | `/init` command to generate AGENTS.md documentation for a codebase             |
| [![npm](https://img.shields.io/badge/npm-FFD16C?style=flat&logo=npm&logoColor=222)](https://npmjs.com/package/@oh-my-pi/metal-theme)           | **[metal-theme](./plugins/metal-theme)**                 | A metal theme 🤘                                                               |

---

Install community plugins with a single command. Themes, custom agents, slash commands, tools — sourced through npm/git, all a `omp install` away.

## Installation

```bash
npm install -g @oh-my-pi/cli
```

## Quick Start

```bash
# Install a plugin
omp install @oh-my-pi/subagents

# See what you've got
omp list

# Search for more
omp search agents

# Check for updates
omp outdated

# Update everything
omp update
```

## How It Works

omp installs plugins globally via npm and sets up your pi configuration:

```
~/.pi/
├── agent/                    # Pi's agent directory
│   ├── agents/               # Agent definitions (.md) - symlinked
│   ├── commands/             # Slash commands (.md) - symlinked
│   ├── hooks/omp/            # Hook loader
│   │   └── index.ts          # Generated loader - imports hooks from node_modules
│   ├── tools/omp/            # Tool loader
│   │   └── index.ts          # Generated loader - imports tools from node_modules
│   └── themes/               # Theme files (.json) - symlinked
└── plugins/
    ├── package.json          # Installed plugins manifest
    ├── node_modules/         # Plugin packages (tools/hooks loaded directly from here)
    └── store/                # Runtime configs (survives npm updates)
```

**Non-tool files** (agents, commands, themes) are symlinked via `omp.install` entries.

**Tools and Hooks** are loaded directly from node_modules via generated loaders. Plugins specify `omp.tools` and/or `omp.hooks` pointing to their factory modules. This allows using npm dependencies without workarounds.

## Project-Level Overrides

While plugins are installed globally, you can customize their behavior per-project using `.pi/overrides.json`:

```bash
# Initialize project overrides
omp init

# Disable a plugin for this project only
omp disable @oh-my-pi/subagents -l

# Enable different features in this project
omp features @oh-my-pi/exa --set search -l

# Override config variables for this project
omp config @oh-my-pi/exa apiKey sk-project-specific -l
```

Project overrides are stored in:

- `.pi/overrides.json` - disabled plugins list
- `.pi/store/` - feature and config overrides (merged with global, project takes precedence)

The loader automatically merges project overrides at runtime.

## Commands

| Command                | Alias | Description                                              |
| ---------------------- | ----- | -------------------------------------------------------- |
| `omp install [pkg...]` | `i`   | Install plugin(s). No args = install from package.json   |
| `omp uninstall <pkg>`  | `rm`  | Remove plugin and its symlinks                           |
| `omp update [pkg]`     | `up`  | Update to latest within semver range                     |
| `omp list`             | `ls`  | Show installed plugins                                   |
| `omp search <query>`   |       | Search npm for plugins                                   |
| `omp info <pkg>`       |       | Show plugin details before install                       |
| `omp outdated`         |       | List plugins with newer versions                         |
| `omp doctor`           |       | Check for broken symlinks, conflicts                     |
| `omp link <path>`      |       | Symlink local plugin (dev mode)                          |
| `omp create <name>`    |       | Scaffold new plugin from template                        |
| `omp init`             |       | Create .pi/overrides.json for project-local config       |
| `omp why <file>`       |       | Show which plugin installed a file                       |
| `omp enable <name>`    |       | Enable a disabled plugin (-l for project override)       |
| `omp disable <name>`   |       | Disable plugin without uninstalling (-l for project)     |
| `omp features <name>`  |       | List or configure plugin features (-l for project)       |
| `omp config <name>`    |       | Get or set plugin configuration (-l for project)         |
| `omp env`              |       | Print environment variables for shell eval (-l to merge) |

Commands that modify plugin state (enable, disable, features, config, env) accept `-l`/`--local` to use project-level overrides instead of global config.

## Feature Selection

Plugins can expose optional features that you can selectively enable. Use pip-style bracket syntax during install:

```bash
# Install with default features (plugin decides which are on by default)
omp install @oh-my-pi/exa

# Install with specific features only
omp install @oh-my-pi/exa[search]
omp install @oh-my-pi/exa[search,websets]

# Explicitly all features
omp install @oh-my-pi/exa[*]

# No optional features (core only)
omp install @oh-my-pi/exa[]

# Reinstall preserves feature selection unless you specify new ones
omp install @oh-my-pi/exa              # Keeps existing features
omp install @oh-my-pi/exa[search]      # Reconfigures to search only
```

Plugins define which features are enabled by default via `default: true` in their manifest. Features with `default: false` are opt-in.

Manage features after install with `omp features`:

```bash
# List available features and their current state
omp features @oh-my-pi/exa

# Enable/disable specific features
omp features @oh-my-pi/exa --enable websets
omp features @oh-my-pi/exa --disable search

# Set exact feature list
omp features @oh-my-pi/exa --set search,websets

# Override features for current project only
omp features @oh-my-pi/exa --set search -l
```

## Plugin Configuration

Plugins can define configurable variables. Manage them with `omp config`:

```bash
# List all variables for a plugin
omp config @oh-my-pi/exa

# Get a specific value
omp config @oh-my-pi/exa apiKey

# Set a value
omp config @oh-my-pi/exa apiKey sk-xxx

# Reset to default
omp config @oh-my-pi/exa apiKey --delete

# Override for current project only
omp config @oh-my-pi/exa apiKey sk-project -l
```

Variables with `env` mappings can be exported as environment variables:

```bash
# Print shell exports
eval "$(omp env)"

# Fish shell
omp env --fish | source

# Merge project overrides
eval "$(omp env -l)"

# Persist in your shell config
omp env >> ~/.bashrc
```

## Creating Plugins

Plugins are npm packages with an `omp` field in `package.json`:

```json
{
   "name": "my-cool-plugin",
   "version": "1.0.0",
   "keywords": ["omp-plugin"],
   "omp": {
      "install": [
         { "src": "agents/researcher.md", "dest": "agent/agents/researcher.md" },
         { "src": "commands/research.md", "dest": "agent/commands/research.md" }
      ]
   },
   "files": ["agents", "commands"]
}
```

### Tools

For plugins with custom tools, use the `tools` field instead of `install`:

```json
{
   "name": "@oh-my-pi/my-tools",
   "version": "1.0.0",
   "keywords": ["omp-plugin"],
   "omp": {
      "tools": "tools"
   },
   "files": ["tools"],
   "dependencies": {
      "some-npm-package": "^1.0.0"
   }
}
```

The `tools` field points to a directory containing an `index.ts` that exports a tool factory. Tools are loaded directly from node_modules, so npm dependencies work normally.

### Hooks

For plugins with lifecycle hooks, use the `hooks` field:

```json
{
   "name": "@oh-my-pi/my-hooks",
   "version": "1.0.0",
   "keywords": ["omp-plugin"],
   "omp": {
      "hooks": "hooks"
   },
   "files": ["hooks"]
}
```

The `hooks` field points to a directory containing an `index.ts` that exports a hook factory (`HookFactory`). Hooks subscribe to agent events like `tool_call`, `session`, etc.

### Features and Variables

Plugins can define optional features and configurable variables:

```json
{
   "name": "@oh-my-pi/exa",
   "version": "1.0.0",
   "keywords": ["omp-plugin"],
   "omp": {
      "tools": "tools",
      "runtime": "tools/runtime.json",
      "variables": {
         "apiKey": {
            "type": "string",
            "env": "EXA_API_KEY",
            "description": "Exa API key",
            "required": true
         }
      },
      "features": {
         "search": {
            "description": "Web search capabilities",
            "default": true
         },
         "websets": {
            "description": "Curated content collections",
            "default": false,
            "variables": {
               "defaultCollection": {
                  "type": "string",
                  "default": "general"
               }
            }
         }
      }
   }
}
```

The `runtime` field points to a JSON file that the plugin imports to check feature state. omp stores user's feature selections in `~/.pi/plugins/store/` and injects them at load time, so they persist across npm updates.

### Plugin Structure

```
my-cool-plugin/
├── package.json
├── agents/           # Agent definitions
│   └── researcher.md
├── commands/         # Slash commands
│   └── research.md
├── tools/            # Custom tools
│   └── search/
│       └── index.ts
└── themes/           # Theme files
    └── dark.json
```

### Install Mappings

The `omp.install` array maps source files to their destination in the agent directory:

- `src`: Path relative to the plugin root
- `dest`: Path relative to the pi config dir (usually starts with `agent/`)

### Publishing

1. Add `omp-plugin` to your `keywords` array (required for `omp search` discovery)
2. Include source directories in the `files` array
3. Publish to npm: `npm publish`

Your plugin is now discoverable via `omp search`.

### Development Workflow

```bash
# Scaffold a new plugin
omp create my-plugin

# Link for local development (changes reflect immediately)
omp link ./my-plugin

# Test your plugin
omp list

# When ready, publish
cd my-plugin && npm publish
```

## Troubleshooting

```bash
# Check for broken symlinks and conflicts
omp doctor

# See which plugin installed a specific file
omp why ~/.pi/agent/agents/researcher.md

# Temporarily disable a plugin
omp disable @oh-my-pi/subagents

# Re-enable it later
omp enable @oh-my-pi/subagents

# Disable just for this project
omp disable @oh-my-pi/subagents -l
```

## Credits

Built for [pi](https://github.com/badlogic/pi-mono) by [@badlogic](https://github.com/badlogic).

## License

MIT