# pi-prompt-control

Manage and minimize [Pi](https://github.com/anthropics/pi)'s system prompt — config-driven patches, interactive skill toggle, and probe-based prompt capture.

## Install

```bash
pi install npm:pi-prompt-control
```

## Features

### `/prompt-dump [path]` — Capture the real system prompt

Fires a probe turn so **every** `before_agent_start` handler runs (pi-slim, your own extensions, anything).
Captures the fully-chained system prompt in `turn_start`, writes it to a file, and aborts before the LLM call.

```
/prompt-dump                      # → ./pi-system-prompt-patched.md
/prompt-dump my-prompt.md         # → ./my-prompt.md
```

Works at fresh start — no prior message needed.

### `/skills` — Interactive skill toggle

Opens a TUI checklist of every loaded skill. Toggle with <kbd>Space</kbd>.
Unchecked skills are stripped from the system prompt before each turn, saving context tokens.

Skills remain explicitly invokable via `/skill:<name>` — only their automatic inclusion is toggled off.

```
/skills           # open the TUI checklist
/skills:reset     # re-enable all skills
```

State is persisted to:
- `~/.pi/agent/disabled-skills.json` (user scope)
- `.pi/disabled-skills.json` (project scope, overrides user)

### Config-driven patches — `prompt-patches.json`

Place a config file at `.pi/prompt-patches.json` (project) or `~/.pi/agent/prompt-patches.json` (global):

```json
{
  "patches": [
    {
      "name": "remove bash guidance",
      "op": "remove",
      "find": "- Use bash for file operations like ls, rg, find\n"
    },
    {
      "name": "soften a rule",
      "op": "replace",
      "find": "You must always",
      "replace": "Prefer to",
      "regex": false
    },
    {
      "name": "add house rule",
      "op": "append",
      "text": "\n\nPrefer rg over grep.\n"
    },
    {
      "name": "strip a block (regex)",
      "op": "replace",
      "find": "\\n\\nSome block[\\s\\S]*?end of block",
      "replace": "",
      "regex": true
    }
  ]
}
```

#### Patch operations

| `op` | Required fields | Description |
|------|----------------|-------------|
| `remove` | `find` | Remove the first occurrence of `find` |
| `replace` | `find`, `replace` | Replace the first occurrence of `find` with `replace` |
| `append` | `text` | Append `text` to the end of the prompt |

All `remove` and `replace` patches support `"regex": true` and an optional `"flags"` string (e.g. `"gi"`).

#### Live reload

The config file is watched — edits take effect on the next message without `/reload`.
Parse errors and validation issues are surfaced via notifications.

## How `/prompt-dump` works

Unlike `ctx.getSystemPrompt()` (which returns the **base** prompt), `/prompt-dump` captures the prompt **after all extensions have modified it**:

1. Sets a capture flag
2. Sends a probe user message (`.`)
3. All `before_agent_start` handlers chain naturally
4. In `turn_start`, captures `ctx.getSystemPrompt()` (now fully chained)
5. Writes to file and calls `ctx.abort()` — no LLM call, no cost

This means it works with **any** combination of extensions (pi-slim, custom patches, skill-toggle, future extensions) without knowing about them.

## Publish through GitHub Actions

This package publishes to npm through `.github/workflows/publish.yml`.

1. In npm, create a granular access token with publish access and **2FA bypass** enabled.
2. In GitHub, add it as repository secret `NPM_TOKEN`.
3. Bump the package version:

   ```bash
   npm version patch
   git push --follow-tags
   ```

4. The workflow publishes when a `v*.*.*` tag is pushed, when a GitHub Release is published, or when run manually from the Actions tab.

The workflow runs `npm pack --dry-run`, skips versions that are already published, and publishes with npm provenance.

## License

MIT
