@connortessaro/pai 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +308 -0
- package/bin.mjs +14 -0
- package/dist/pai.mjs +3083 -0
- package/package.json +83 -0
- package/skills/phantom-ai/SKILL.md +134 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Connor Tessaro
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset=".github/assets/logo-dark.svg">
|
|
4
|
+
<source media="(prefers-color-scheme: light)" srcset=".github/assets/logo-light.svg">
|
|
5
|
+
<img alt="Phantom Logo" src=".github/assets/logo-dark.svg" width="56" height="62">
|
|
6
|
+
</picture>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<h1 align="center">pai</h1>
|
|
10
|
+
|
|
11
|
+
<p align="center">
|
|
12
|
+
<strong>Keys, money, and subagent controls for AI agents</strong><br>
|
|
13
|
+
Built by <a href="https://phantom.codes">Phantom AI</a>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="https://github.com/connortessaro/pai/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/connortessaro/pai/ci.yml?branch=main&label=CI&color=161b22&labelColor=0d1117" alt="CI"></a>
|
|
18
|
+
<a href="package.json"><img src="https://img.shields.io/badge/version-0.3.0-161b22?labelColor=0d1117" alt="Version 0.3.0"></a>
|
|
19
|
+
<a href="package.json"><img src="https://img.shields.io/badge/node-%3E%3D24-161b22?labelColor=0d1117" alt="Node >= 24"></a>
|
|
20
|
+
<a href="docs/reference.md#mcp-tools"><img src="https://img.shields.io/badge/MCP-16_tools-161b22?labelColor=0d1117" alt="MCP Compatible"></a>
|
|
21
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-161b22?labelColor=0d1117" alt="MIT License"></a>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
<p align="center">
|
|
25
|
+
<a href="#install">Install</a> •
|
|
26
|
+
<a href="#quickstart">Quickstart</a> •
|
|
27
|
+
<a href="#how-it-works">How It Works</a> •
|
|
28
|
+
<a href="#features">Features</a> •
|
|
29
|
+
<a href="#commands">Commands</a> •
|
|
30
|
+
<a href="#use-with-an-mcp-client">MCP Server</a> •
|
|
31
|
+
<a href="docs/reference.md">API Reference</a>
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
`pai` runs on your machine and manages a [Phantom AI](https://phantom.codes) key.
|
|
37
|
+
Your agent can hand each subagent a child key with its own spending limit, lifetime, and rate cap.
|
|
38
|
+
It also sets plans and model routing, pays for credit from an agent wallet, and checks which model answered a call.
|
|
39
|
+
|
|
40
|
+
`pi`, `Claude Code`, `Codex`, and `Cursor` drive it through a skill, and any MCP client can use `pai mcp`.
|
|
41
|
+
|
|
42
|
+
The CLI is MIT licensed. The Phantom AI API it calls is a hosted service.
|
|
43
|
+
|
|
44
|
+
## How It Works
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
┌────────────────────────┐
|
|
48
|
+
│ Main Phantom Key │
|
|
49
|
+
│ (prepaid, no id) │
|
|
50
|
+
└───────────┬────────────┘
|
|
51
|
+
│
|
|
52
|
+
┌───────────────────────┼───────────────────────┐
|
|
53
|
+
│ pai child │ pai child │ pai wallet
|
|
54
|
+
▼ ▼ ▼
|
|
55
|
+
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
56
|
+
│ Researcher │ │ Code Agent │ │ Agent Wallet │
|
|
57
|
+
│ Claude Code │ │ Cursor │ │ (Solana) │
|
|
58
|
+
│ $0.50 limit │ │ $1.00 limit │ │ auto-topup │
|
|
59
|
+
│ 6 hour TTL │ │ $0.10 / min │ │ below $1.00 │
|
|
60
|
+
└──────┬───────┘ └──────┬───────┘ └──────────────┘
|
|
61
|
+
│ │
|
|
62
|
+
└───────────┬───────────┘
|
|
63
|
+
▼
|
|
64
|
+
┌───────────────────────┐
|
|
65
|
+
│ Phantom AI Gateway │ ──> https://phantom.codes/v1
|
|
66
|
+
│ (zero prompt logs) │ ──> Ed25519 signed receipts
|
|
67
|
+
└───────────────────────┘
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Features
|
|
71
|
+
|
|
72
|
+
- **Scoped Subagent Keys** — Create child keys that spend the parent's balance up to a limit, with lifetimes and rate caps (`pai child`). Revoke one with `pai burn`.
|
|
73
|
+
- **Autonomous Agent Wallet** — Local Solana keypairs allow running agents to self-fund inference on chain. Capped by environment-only limits (`PHANTOM_WALLET_MAX_USD`).
|
|
74
|
+
- **Multi-Agent Skill & MCP** — Native skill installation for `pi`, `Claude Code`, `Codex`, and `Cursor`, plus a 16-tool Model Context Protocol (MCP) server over stdio.
|
|
75
|
+
- **Cryptographic Receipts** — Upstream responses return an Ed25519 signature verifying the model served, actual token counts, and cost (`pai verify`).
|
|
76
|
+
- **Local Tooling Suite** — Private local markdown memory notebooks, throwaway Docker sandboxes, and safe IMAP/SMTP mail drafting.
|
|
77
|
+
|
|
78
|
+
## Install
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npm i -g @connortessaro/pai
|
|
82
|
+
# or, without npm's registry:
|
|
83
|
+
npx github:connortessaro/pai --help
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The package also installs the same CLI as `phantom-key`, its earlier name.
|
|
87
|
+
|
|
88
|
+
## Quickstart
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# 1. Login once and install the skill for your installed agents
|
|
92
|
+
pai login # paste your key once; pai saves it with mode 600
|
|
93
|
+
pai setup # configures pi, Claude Code, Codex, and Cursor
|
|
94
|
+
|
|
95
|
+
# 2. Check balance and active caps
|
|
96
|
+
pai balance
|
|
97
|
+
|
|
98
|
+
# 3. Mint a child key for an autonomous subagent
|
|
99
|
+
pai child --limit 0.50 --ttl 6 --rate 0.10 --save researcher
|
|
100
|
+
|
|
101
|
+
# 4. Run the subagent as the scoped child
|
|
102
|
+
PHANTOM_KEY_NAME=researcher claude
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Use It From an Agent
|
|
106
|
+
|
|
107
|
+
`pai setup` installs the `phantom-ai` skill for each agent it finds in your
|
|
108
|
+
home directory (`pi`, `Claude Code`, `Codex`, `Cursor`). You can then prompt your agent in
|
|
109
|
+
plain words, for example:
|
|
110
|
+
|
|
111
|
+
> *"Give a subagent $0.50 for 6 hours with a $0.10/min rate cap."*
|
|
112
|
+
|
|
113
|
+
- `--agent pi` (or `claude`, `codex`, `cursor`) sets up one agent.
|
|
114
|
+
- `--mcp` also registers the MCP server with Claude Code, Codex, and Cursor.
|
|
115
|
+
- `--agent claude --provider` runs Claude Code's own model calls on Phantom AI: it sets `ANTHROPIC_BASE_URL`, turns on tool search, and gives Claude Code the key through `apiKeyHelper` (`pai key show`), so the key never lands in `settings.json`. Add `--model auto` or any model id; `--provider off` undoes it.
|
|
116
|
+
- `pi` has no MCP and uses the CLI through the skill; install there with:
|
|
117
|
+
```bash
|
|
118
|
+
pi install npm:@connortessaro/pai
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Commands
|
|
122
|
+
|
|
123
|
+
`pai --help` prints every command and flag. [docs/reference.md](docs/reference.md)
|
|
124
|
+
has the complete text, the MCP tools, and the environment variables, all generated
|
|
125
|
+
from the code.
|
|
126
|
+
|
|
127
|
+
| Group | Commands | What they do |
|
|
128
|
+
| --- | --- | --- |
|
|
129
|
+
| **Setup** | `login`, `logout`, `setup` | Save your key, and install the skill for your agents |
|
|
130
|
+
| **Keys** | `balance`, `child`, `children`, `key`, `rotate`, `burn` | Show credit, create child keys paid from this key, save keys by name, and replace or revoke a key |
|
|
131
|
+
| **Caps and plans** | `budget`, `plan` | Set a monthly cap and a per-minute cap, or money for a period |
|
|
132
|
+
| **Routing** | `route` | Choose which models `model: "auto"` can run, and the rules that pick one |
|
|
133
|
+
| **Credit** | `buy`, `payment` | Buy credit with crypto |
|
|
134
|
+
| **Agent wallet** | `wallet`, `autotopup`, `buy --pay` | Keep Solana wallets and pay for credit from them. See [Let the agent pay](#let-the-agent-pay) |
|
|
135
|
+
| **Receipts** | `verify` | Check which model answered a call, from its signed receipt |
|
|
136
|
+
| **Local tools** | `memory`, `mail`, `browser`, `sandbox` | See the sections below |
|
|
137
|
+
| **MCP** | `mcp` | Run an MCP server over stdio. See [Use with an MCP client](#use-with-an-mcp-client) |
|
|
138
|
+
|
|
139
|
+
A command runs as the saved key named by `PHANTOM_KEY_NAME` if it is set, then
|
|
140
|
+
as `PHANTOM_API_KEY`, then as the `login` key. A subagent started with
|
|
141
|
+
`PHANTOM_KEY_NAME=<child>` runs as the child even when your parent key is exported.
|
|
142
|
+
|
|
143
|
+
## Memory
|
|
144
|
+
|
|
145
|
+
Each agent gets a private notebook on this machine. Notes are markdown files in
|
|
146
|
+
`~/.config/phantom-key/memory/<space>/`, so you can read, edit, or commit them.
|
|
147
|
+
`pai` sends none of them anywhere.
|
|
148
|
+
|
|
149
|
+
| Command | What it does |
|
|
150
|
+
| --- | --- |
|
|
151
|
+
| `memory add "text" [--tag a,b] [--title t]` | Keeps a note. Pipe long notes on stdin |
|
|
152
|
+
| `memory search <words> [--tag t] [--any] [--limit n]` | Notes with every word (or any word with `--any`), best match first. Returns 10 by default |
|
|
153
|
+
| `memory list [--tag t] [--limit n]` / `memory show <id>` / `memory rm <id>` | The newest notes (50 by default), one note, or delete one |
|
|
154
|
+
| `memory spaces` | Each notebook and how many notes it holds |
|
|
155
|
+
|
|
156
|
+
`pai` picks the notebook from `--space`, then `PAI_MEMORY_SPACE`, then the saved
|
|
157
|
+
key name (`PHANTOM_KEY_NAME`), then `main`, so each subagent keeps its own.
|
|
158
|
+
|
|
159
|
+
## Mail
|
|
160
|
+
|
|
161
|
+
`pai` reads your own mailbox over IMAP and SMTP. It saves the login, with an app
|
|
162
|
+
password, in `~/.config/phantom-key/mail.json` (mode 600). Gmail, Outlook,
|
|
163
|
+
iCloud, and Fastmail addresses have presets; for any other provider, pass
|
|
164
|
+
`--imap host:port --smtp host:port`.
|
|
165
|
+
|
|
166
|
+
| Command | What it does |
|
|
167
|
+
| --- | --- |
|
|
168
|
+
| `mail setup --user you@gmail.com` | Checks the login by listing one message, then saves it. A wrong password is not saved. The password comes from a prompt or `PAI_MAIL_PASSWORD` |
|
|
169
|
+
| `mail status` | Shows the mailbox and whether sending is on |
|
|
170
|
+
| `mail list [--unread] [--from x] [--limit n] [--folder f]` / `mail search <words>` / `mail read <uid>` | Reads mail from `INBOX` by default. `list` returns 20 messages by default. `read` cuts a message at 20,000 characters |
|
|
171
|
+
| `mail draft --to a --subject s [--reply <uid>] [--body "..."]` | Saves a draft in your Drafts folder and sends nothing. Without `--body`, pai reads the body from stdin |
|
|
172
|
+
| `mail send` (same flags) | Sends only when `PAI_MAIL_SEND=1`, to at most `PAI_MAIL_MAX_PER_DAY` recipients (default 10) in 24 hours, and only to `PAI_MAIL_SEND_TO` (addresses or `@domain`s) when set. pai reads all three from the environment, so an agent can't turn sending on with a flag. With sending on, the `create_child_key` tool requires `save_as`, so a new key never lands in the agent's context. SMTP on 587 and IMAP on 143 require STARTTLS |
|
|
173
|
+
|
|
174
|
+
## Browser and Sandbox
|
|
175
|
+
|
|
176
|
+
`pai` wraps two existing tools:
|
|
177
|
+
|
|
178
|
+
| Command | What it does |
|
|
179
|
+
| --- | --- |
|
|
180
|
+
| `browser setup [--install]` | Checks for [agent-browser](https://github.com/vercel-labs/agent-browser), a headless Chrome built for agents. `--install` installs it with npm |
|
|
181
|
+
| `browser <command>` | Runs agent-browser (`open <url>`, `snapshot -i`, `click @e1`, `fill @e2 "text"`, `screenshot`). Each space gets its own session and Chrome profile in `~/.config/phantom-key/browser/<space>/`, so a subagent keeps its own logins. `AGENT_BROWSER_PROFILE=Default` uses your own Chrome profile instead |
|
|
182
|
+
| `sandbox check` | Reports whether Docker or Podman is running |
|
|
183
|
+
| `sandbox run [--image i] [--net] [--write] [--timeout s] -- <command>` | Runs a command in a throwaway container (default image `node:24-slim`). The container has no network unless `--net`, and mounts this folder read-only unless `--write`. It runs as an unprivileged user with all capabilities dropped, 2 CPUs and 2 GB of memory. It stops after 300 seconds by default and exits 124 on timeout |
|
|
184
|
+
|
|
185
|
+
## Output Format
|
|
186
|
+
|
|
187
|
+
Commands print JSON on stdout, so you can pipe into `jq`. `--table` prints
|
|
188
|
+
a formatted table for human inspection. `browser` and `sandbox run` pass through the exit code of the
|
|
189
|
+
command they ran.
|
|
190
|
+
|
|
191
|
+
| Exit code | Meaning |
|
|
192
|
+
| --- | --- |
|
|
193
|
+
| `0` | Success |
|
|
194
|
+
| `1` | Any other error |
|
|
195
|
+
| `2` | Key rejected (401/403). Get a new key; a retry fails the same way |
|
|
196
|
+
|
|
197
|
+
## Use With an MCP Client
|
|
198
|
+
|
|
199
|
+
`pai mcp` starts an MCP server over stdio. Add it to your client's config:
|
|
200
|
+
|
|
201
|
+
```json
|
|
202
|
+
{
|
|
203
|
+
"mcpServers": {
|
|
204
|
+
"phantom": {
|
|
205
|
+
"command": "npx",
|
|
206
|
+
"args": ["-y", "@connortessaro/pai", "mcp"]
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
[docs/reference.md](docs/reference.md#mcp-tools) lists every tool with its
|
|
213
|
+
inputs and whether it is read-only or destructive.
|
|
214
|
+
|
|
215
|
+
`delete_key` authenticates as the key you pass in `api_key` or `key_name` and
|
|
216
|
+
deletes that key. It refuses the key the server runs as; use `pai burn` for
|
|
217
|
+
that.
|
|
218
|
+
|
|
219
|
+
## Let the Agent Pay
|
|
220
|
+
|
|
221
|
+
The agent can maintain its own Solana wallets and buy credit with them. Each wallet
|
|
222
|
+
is a Solana keypair in `~/.config/phantom-key/wallets/` (mode 600). The wallet
|
|
223
|
+
pays Phantom AI's Solana address, and Phantom AI finds the payment on chain.
|
|
224
|
+
|
|
225
|
+
1. **Create a wallet**, and back up its file:
|
|
226
|
+
```bash
|
|
227
|
+
pai wallet create --table # saved as "main"
|
|
228
|
+
pai wallet create --name work --table # a second one
|
|
229
|
+
```
|
|
230
|
+
2. **Fund the address** with USDC on Solana, plus some SOL for fees (at least 0.003 SOL).
|
|
231
|
+
3. **Set the safety cap**:
|
|
232
|
+
```bash
|
|
233
|
+
export PHANTOM_WALLET_MAX_USD=10
|
|
234
|
+
```
|
|
235
|
+
Without this variable, `pai` refuses to pay. The total over 24 hours is
|
|
236
|
+
capped by `PHANTOM_WALLET_MAX_USD_PER_DAY`, which defaults to the same
|
|
237
|
+
amount: one payment a day. Raise it for `autotopup`.
|
|
238
|
+
4. **Pay**:
|
|
239
|
+
```bash
|
|
240
|
+
pai buy --amount 5 --pay
|
|
241
|
+
```
|
|
242
|
+
With more than one wallet saved, `pai` asks in a terminal which one pays. It
|
|
243
|
+
then reports each step:
|
|
244
|
+
1. Getting a payment request from Phantom AI (amount, recipient, and unique reference)
|
|
245
|
+
2. Sending USDC or SOL from your wallet
|
|
246
|
+
3. Confirming on Solana
|
|
247
|
+
4. Phantom AI finding the payment on chain by its reference
|
|
248
|
+
5. Credit balance before and after
|
|
249
|
+
|
|
250
|
+
A payment request expires after 30 minutes.
|
|
251
|
+
|
|
252
|
+
You can also prompt your agent: *"Top up my Phantom AI key with $5 from my Phantom agent wallet."*
|
|
253
|
+
Over MCP it calls `list_wallets`, asks which wallet if not specified, then calls `pay_for_credit`.
|
|
254
|
+
|
|
255
|
+
To refill automatically when the balance runs low:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
pai autotopup --below 1 --amount 5 --wallet main --every 10
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Safeguards
|
|
262
|
+
|
|
263
|
+
- `pai` pays the recipient and exact amount the payment request names, with that request's reference attached.
|
|
264
|
+
- `pai` reads `PHANTOM_WALLET_MAX_USD` and `PHANTOM_WALLET_MAX_USD_PER_DAY` strictly from the environment; no flag or tool argument can raise them.
|
|
265
|
+
- Before signing, `pai` checks the payment request against what it asked for: the coin, the USDC mint, and an amount no more than requested (for SOL, within 10% of Coinbase's price). A wrong or hostile `PHANTOM_BASE_URL` cannot make it sign more.
|
|
266
|
+
- One payment runs at a time, across processes.
|
|
267
|
+
- `pai` verifies the wallet balance before requesting a payment.
|
|
268
|
+
- `pai` records payments in `~/.config/phantom-key` before sending, and keeps the record until Phantom AI reports the payment credited or dead. If a run crashes, times out or loses the connection, the next run waits for that payment instead of paying again.
|
|
269
|
+
- These limits bind an agent that reaches pai through MCP. An agent with its own shell can set environment variables and edit the state folder, so give such an agent a wallet holding only what you are willing for it to spend.
|
|
270
|
+
- Store wallet secrets in a local secrets manager (e.g. [KRU](https://github.com/omaekumiko2-create/kru)) and inject `PHANTOM_WALLET_KEY` at runtime.
|
|
271
|
+
|
|
272
|
+
## Configuration
|
|
273
|
+
|
|
274
|
+
`pai` reads its settings from environment variables. Run `pai --help` or see
|
|
275
|
+
[docs/reference.md#environment-variables](docs/reference.md#environment-variables) for the full list,
|
|
276
|
+
including secrets, environment-only flags, and caps.
|
|
277
|
+
|
|
278
|
+
## Requirements
|
|
279
|
+
|
|
280
|
+
- **Node 24** or newer
|
|
281
|
+
- Runtime dependencies: `@modelcontextprotocol/sdk` and `zod` for `mcp`, `@solana/kit` for wallet payments, and `imapflow`, `mailparser`, `nodemailer` for `mail`.
|
|
282
|
+
|
|
283
|
+
Read [phantom.codes/docs/concepts](https://phantom.codes/docs/concepts) for key lifecycle and subagent hierarchy details.
|
|
284
|
+
|
|
285
|
+
## Development
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
npm ci
|
|
289
|
+
npm test # vitest
|
|
290
|
+
npm run typecheck
|
|
291
|
+
npm run docs # regenerate docs/reference.md
|
|
292
|
+
node src/pai.mts --help # run from source
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Contributing
|
|
296
|
+
|
|
297
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, style, and how to add a
|
|
298
|
+
command or MCP tool. [CHANGELOG.md](CHANGELOG.md) lists changes by release.
|
|
299
|
+
|
|
300
|
+
## Security
|
|
301
|
+
|
|
302
|
+
Report vulnerabilities privately through a
|
|
303
|
+
[GitHub security advisory](https://github.com/connortessaro/pai/security/advisories/new).
|
|
304
|
+
See [SECURITY.md](SECURITY.md).
|
|
305
|
+
|
|
306
|
+
## License
|
|
307
|
+
|
|
308
|
+
[MIT](LICENSE)
|
package/bin.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The installed entry point.
|
|
4
|
+
*
|
|
5
|
+
* Two reasons this is plain JS rather than the .mts itself. Node refuses to
|
|
6
|
+
* strip types from anything under node_modules at all, so a published
|
|
7
|
+
* TypeScript source cannot run in a dependency; and npm links the bin as an
|
|
8
|
+
* extensionless `pai`, which Node would not recognise as TypeScript
|
|
9
|
+
* even if it would. So `npm run build` compiles the source to dist/ and this
|
|
10
|
+
* file, which never needs compiling, is what npm points at.
|
|
11
|
+
*/
|
|
12
|
+
import { main } from './dist/pai.mjs';
|
|
13
|
+
|
|
14
|
+
await main();
|