@ory/pi 0.11.0 → 0.12.0
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/README.md +84 -68
- package/dist/cli/main.js +8 -9
- package/dist/cli/setup.js +13 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,126 +1,142 @@
|
|
|
1
1
|
# Ory Agent Plugin: Pi
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Security and developer experience for [Pi](https://pi.dev), powered by [Ory](https://ory.com).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Security.** Pi runs real actions on your machine — editing files, running shell commands, calling APIs. The plugin gives every session a verifiable identity (you sign in once; Pi and any sub-agents it spawns each get their own), checks every tool call against permissions you control, and records each decision as an audit trace you can ship to your observability stack. It starts in watch mode so nothing is blocked on day one, and if Ory is ever unreachable it steps aside rather than locking you out.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**Developer experience.** A single command installs the plugin and walks you through connecting — choose Ory Network, a local Docker stack, or audit-only, and it wires up the project, sign-in client, login, and permissions for you. It also helps you build Ory into your own app: ask in plain language to scaffold login, registration, and recovery pages, run a local Ory, or manage identities and permissions through the bundled MCP server.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## What you'll need
|
|
10
10
|
|
|
11
|
-
[
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
|
|
16
|
-
## What this plugin does
|
|
17
|
-
|
|
18
|
-
Two independent things, and you can use either on its own:
|
|
11
|
+
- [Pi](https://pi.dev) installed (`@earendil-works/pi-coding-agent`)
|
|
12
|
+
- Node.js **22 or newer**
|
|
13
|
+
- [Docker](https://docs.docker.com/get-docker/) — only if you want to run Ory locally
|
|
14
|
+
- macOS or Linux (Windows works via WSL2)
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
2. **Govern the agent itself.** Authenticate Pi's own session and authorize every tool it runs against Ory Permissions, with a full audit trail. See [Agent security](#agent-security).
|
|
16
|
+
Pi loads the plugin from your project's `node_modules`, so add it to your project first:
|
|
22
17
|
|
|
23
|
-
|
|
18
|
+
```bash
|
|
19
|
+
npm install @ory/pi
|
|
20
|
+
```
|
|
24
21
|
|
|
25
|
-
|
|
26
|
-
- Node.js **≥ 22**
|
|
27
|
-
- [Docker](https://docs.docker.com/get-docker/) (only needed for the local Ory stack)
|
|
28
|
-
- macOS or Linux. Windows works via WSL2.
|
|
22
|
+
## Get started
|
|
29
23
|
|
|
30
|
-
|
|
24
|
+
Then run one command. It installs the plugin and walks you through connecting:
|
|
31
25
|
|
|
32
26
|
```bash
|
|
33
27
|
npx -y -p @ory/pi ory-pi install
|
|
34
28
|
```
|
|
35
29
|
|
|
36
|
-
|
|
30
|
+
The installer drops a tiny loader at `<project>/.pi/extensions/ory.js` so Pi discovers the plugin, adds the Ory skills under `<project>/.pi/skills`, and then asks how you want to connect — **press Enter for the default**:
|
|
31
|
+
|
|
32
|
+
- **Ory Network** *(default)* — sign in, or create a free account, in your browser. The project, keys, permissions, and login are all set up for you. Nothing to configure by hand.
|
|
33
|
+
- **Local** — run a complete Ory on your laptop with Docker. No account, no signup, no keys. Great for trying it out.
|
|
34
|
+
- **Audit-only** — skip Ory entirely and just log what Pi does.
|
|
37
35
|
|
|
38
|
-
|
|
36
|
+
That's it. Confirm everything landed with:
|
|
39
37
|
|
|
40
38
|
```bash
|
|
41
|
-
npx -y -p @ory/pi ory-pi
|
|
42
|
-
npx -y -p @ory/pi ory-pi status # confirm the loader + hooks
|
|
43
|
-
npx -y -p @ory/pi ory-pi uninstall # remove the loader and skills
|
|
39
|
+
npx -y -p @ory/pi ory-pi status
|
|
44
40
|
```
|
|
45
41
|
|
|
46
|
-
`status`
|
|
42
|
+
`status` is your one-stop check: what's configured, who's signed in, which tools are covered by permissions, whether the loader is in place, and recent activity. Anything not set up yet shows as `(unset)`.
|
|
43
|
+
|
|
44
|
+
Re-run install with `--reconfigure` to change your connection later, or `--no-configure` to skip the wizard. Add `--global` to install the loader for all projects (at `~/.pi/agent/extensions/ory.js`) instead of just this one.
|
|
47
45
|
|
|
48
|
-
|
|
46
|
+
<details>
|
|
47
|
+
<summary>Prefer to let Pi manage the plugin?</summary>
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
Point Pi's own package installer at the npm package:
|
|
51
50
|
|
|
52
51
|
```bash
|
|
53
52
|
pi install npm:@ory/pi
|
|
54
53
|
```
|
|
55
54
|
|
|
56
|
-
This
|
|
55
|
+
This registers the extension through Pi's package manifest, but skips the guided setup — run `npx -y -p @ory/pi ory-pi install` (or `configure`) in a terminal afterwards to connect.
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
</details>
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
## What you get
|
|
61
60
|
|
|
62
|
-
|
|
63
|
-
2. **Scaffold Ory into your project.** Ask Pi *"add Ory auth to this app"* (the `ory-auth-setup` skill). It installs Ory Elements, wires the SDK, and generates the login / registration / recovery / settings pages, all targeting the local stack.
|
|
64
|
-
3. **Sign in.** Start your app, visit the login page, and sign in with the seeded credentials. You now have a real Ory session backed by a real Ory stack — locally, offline, zero configuration.
|
|
61
|
+
Once connected, every tool Pi runs is governed by Ory — three things happen automatically:
|
|
65
62
|
|
|
66
|
-
|
|
63
|
+
- **Who's driving.** You sign in once in your browser (a secure redirect flow — no passwords touch the plugin), and Pi gets its own identity that it registers automatically on first run. No tokens to copy around, and the "who did what" trail stays queryable later. (Pi's startup can't hard-block, so sign-in there is advisory — it still signs you in and logs it, but never stops the session.)
|
|
64
|
+
- **What it's allowed to do.** Before a tool runs, Ory checks whether it's permitted. It starts in **watch mode** — nothing is blocked, you just *see* what would be — so it never gets in your way on day one.
|
|
65
|
+
- **A record of everything.** Every decision (allowed, denied, skipped) is logged as a trace you can send to a viewer like Jaeger, or just a file.
|
|
67
66
|
|
|
68
|
-
|
|
67
|
+
If Ory is ever unreachable, the plugin gets out of the way and lets Pi keep working — so it can't lock you out.
|
|
69
68
|
|
|
70
|
-
Pi
|
|
69
|
+
> Pi has no MCP support and no sub-agents by design, so there's nothing extra to register — just the plugin itself.
|
|
71
70
|
|
|
72
|
-
|
|
71
|
+
### See what's happening
|
|
73
72
|
|
|
74
|
-
|
|
75
|
-
- **Per-tool decision** — the factory registers a `pi.on("tool_call")` handler that checks the tool against Ory Permissions. In enforce mode a deny **blocks by returning `{ block: true, reason }`**; in observe mode it records a `permission.observe_deny` span and allows.
|
|
76
|
-
- **Post-tool** — a `pi.on("tool_result")` handler records a `tool.complete` trace span. Trace-only.
|
|
73
|
+
Everything the plugin does is observable out of the box — no configuration required:
|
|
77
74
|
|
|
78
|
-
**
|
|
75
|
+
- **Status at a glance.** `npx -y -p @ory/pi ory-pi status` shows what's configured, who's signed in, how many built-in tools your permissions cover, and the most recent tool-call activity.
|
|
76
|
+
- **Live traces.** Every tool call is recorded as an OpenTelemetry-style span. Watch them stream as the agent works:
|
|
79
77
|
|
|
80
|
-
|
|
78
|
+
```bash
|
|
79
|
+
npx -y -p @ory/pi ory-pi watch
|
|
80
|
+
```
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
Spans are also written to `~/.config/ory-agent-plugins/pi/ory-agent-trace.ndjson` (NDJSON, one span per line) — tail that file, or point `OTEL_EXPORTER_OTLP_ENDPOINT` at a collector to ship them straight to Jaeger, Honeycomb, or Grafana.
|
|
83
|
+
- **Debug log.** For a verbose play-by-play, set `ORY_AGENT_DEBUG=true`; structured logs land in `~/.config/ory-agent-plugins/pi/ory-agent-debug.log`.
|
|
83
84
|
|
|
84
|
-
|
|
85
|
+
### Ready to enforce?
|
|
85
86
|
|
|
86
|
-
|
|
87
|
-
- **Authorization.** Before any tool runs, the `tool_call` handler checks [Ory Permissions](https://www.ory.com/docs/keto) (Zanzibar-style relations) against the user's subject and blocks on `deny`.
|
|
88
|
-
- **Audit.** Every decision is recorded as a structured trace span (NDJSON file and/or OTLP export).
|
|
89
|
-
|
|
90
|
-
### Permission modes: observe → enforce
|
|
91
|
-
|
|
92
|
-
After install the plugin runs in **observe mode**: every tool call is checked, but a deny is recorded as a `permission.observe_deny` audit span and the tool runs anyway.
|
|
87
|
+
When the watch-mode logs look right, turn on blocking with one command (setup already granted you the built-in tools):
|
|
93
88
|
|
|
94
89
|
```bash
|
|
95
|
-
# Grant the current user `use` on every built-in tool (idempotent):
|
|
96
|
-
npx -y -p @ory/pi ory-pi permissions bootstrap
|
|
97
|
-
|
|
98
|
-
# See allowed/denied per tool:
|
|
99
|
-
npx -y -p @ory/pi ory-pi permissions status
|
|
100
|
-
|
|
101
|
-
# Turn on hard blocking once the observe-mode logs look right:
|
|
102
90
|
npx -y -p @ory/pi ory-pi permissions enforce
|
|
103
91
|
```
|
|
104
92
|
|
|
105
|
-
|
|
93
|
+
Now a denied tool is actually blocked and Pi shows why (the plugin returns `{ block: true, reason }` on Pi's `tool_call` event). Go back to watch mode anytime with `permissions observe`. Use `permissions status` to see what's covered and `permissions bootstrap` to (re-)grant the built-in tools.
|
|
94
|
+
|
|
95
|
+
## Also: add login to your own app
|
|
96
|
+
|
|
97
|
+
Beyond securing Pi, the plugin helps you build Ory into whatever you're working on. Ask Pi *"add Ory login to this app"* and it scaffolds the login, registration, recovery, and settings pages (using [Ory Elements](https://github.com/ory/elements)) wired to a local Ory — no signup or keys needed. Start that local Ory by asking Pi *"start the local Ory stack"* (the `ory-local-up` skill) — it prints a test email + password to sign in with — and tear it down with `ory-local-down`.
|
|
106
98
|
|
|
107
|
-
|
|
99
|
+
Bundled **skills** (just ask in plain language) cover more: `ory-auth-setup`, `ory-login-flow`, `ory-social-login` (Google, GitHub, Apple…), `ory-permissions-onboarding`, and playbooks for wiring Ory into your own agents, E2B sandboxes, or Temporal workers.
|
|
108
100
|
|
|
109
|
-
|
|
101
|
+
## Configure by hand (CI / advanced)
|
|
102
|
+
|
|
103
|
+
The guided setup covers most people. For scripted or CI setups, or to point at an existing Ory Network project, configure directly. Settings are saved to `~/.config/ory-agent-plugins/config.json` and shared across all your Ory agent plugins; environment variables win when both are set.
|
|
110
104
|
|
|
111
105
|
```bash
|
|
112
106
|
npx -y -p @ory/pi ory-pi configure \
|
|
113
|
-
--project-url https://<
|
|
114
|
-
--oauth2-client-id <
|
|
107
|
+
--project-url https://<slug>.projects.oryapis.com \
|
|
108
|
+
--oauth2-client-id <sign-in client id> \
|
|
109
|
+
--user-login
|
|
115
110
|
```
|
|
116
111
|
|
|
117
|
-
`--oauth2-client-id` is
|
|
112
|
+
Pi's own identity registers itself automatically on first run — nothing to create. The `--oauth2-client-id` is the one piece browser sign-in needs — the public sign-in client, registered with the four loopback URLs `http://127.0.0.1:47823..47826/callback`; the guided setup makes it for you. For logging-only with no checks, use `--audit-only`. The equivalent env vars are `ORY_PROJECT_URL`, `ORY_OAUTH2_CLIENT_ID`, and `ORY_USER_LOGIN`.
|
|
113
|
+
|
|
114
|
+
With nothing configured, the plugin still loads and runs in **pass-through mode**: skills and logging work, but no checks run and nothing is blocked. Perfectly fine if you only want the app-building features.
|
|
115
|
+
|
|
116
|
+
## Commands
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
ory-pi install | uninstall Install/remove; --reconfigure re-runs setup, --no-configure skips it, --global for all projects
|
|
120
|
+
ory-pi status Show configuration, identities, permission coverage, recent activity
|
|
121
|
+
ory-pi watch Tail the live trace stream (OTel spans)
|
|
122
|
+
ory-pi permissions <cmd> status | bootstrap | observe (watch) | enforce (block)
|
|
123
|
+
ory-pi configure <flags> Point at a project by hand (--project-url, --oauth2-client-id, --user-login, --audit-only)
|
|
124
|
+
ory-pi agent <status|unregister> Manage Pi's own auto-created identity
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
All prefixed with `npx -y -p @ory/pi`.
|
|
128
|
+
|
|
129
|
+
## Troubleshooting
|
|
118
130
|
|
|
119
|
-
|
|
131
|
+
- **Local Ory won't start** — make sure Docker is running and ports `4000`, `4100`, `4455`, and `16686` are free.
|
|
132
|
+
- **Browser sign-in loops** — reset with `ory-pi agent unregister` and try again.
|
|
133
|
+
- **`npx` grabbed an old version** — force the latest: `npx -y -p @ory/pi@latest ory-pi …`.
|
|
134
|
+
- **Pi can't find the plugin** — make sure `@ory/pi` is installed in the project (`npm install @ory/pi`) and the loader exists at `.pi/extensions/ory.js`; re-run the installer if not.
|
|
135
|
+
- **Want to see what's happening** — `npx -y -p @ory/pi ory-pi status` for a snapshot, `npx -y -p @ory/pi ory-pi watch` for the live trace stream, or set `ORY_AGENT_DEBUG=true` for a verbose log. Traces and logs live under `~/.config/ory-agent-plugins/pi/` (see [See what's happening](#see-whats-happening)).
|
|
120
136
|
|
|
121
|
-
##
|
|
137
|
+
## Learn more
|
|
122
138
|
|
|
123
|
-
- [Ory documentation](https://www.ory.com/docs/)
|
|
139
|
+
- [Ory documentation](https://www.ory.com/docs/) · [Ory Console](https://console.ory.sh) · [Ory Elements](https://github.com/ory/elements)
|
|
124
140
|
- [Pi repository](https://github.com/badlogic/pi-mono)
|
|
125
141
|
- [Repo README](../../README.md) and [AGENTS.md](../../AGENTS.md) — full env-var and permission-mode reference
|
|
126
142
|
|
package/dist/cli/main.js
CHANGED
|
@@ -52,14 +52,19 @@ function main() {
|
|
|
52
52
|
const [command, ...args] = process.argv.slice(2);
|
|
53
53
|
switch (command) {
|
|
54
54
|
case "install":
|
|
55
|
+
(0, argus_1.beginDeferNextSteps)();
|
|
55
56
|
install(args);
|
|
56
|
-
|
|
57
|
+
(0, argus_1.runPostInstall)("ory-pi", "pi", args).then(() => process.exit(0), (err) => {
|
|
57
58
|
console.error(err.message ?? err);
|
|
58
59
|
process.exit(1);
|
|
59
60
|
});
|
|
60
61
|
break;
|
|
61
62
|
case "uninstall":
|
|
62
63
|
uninstall(args);
|
|
64
|
+
(0, argus_1.clearCredentialsForUninstall)().then(() => process.exit(0), (err) => {
|
|
65
|
+
console.error(err.message ?? err);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
});
|
|
63
68
|
break;
|
|
64
69
|
case "configure":
|
|
65
70
|
(0, argus_1.runConfigureCommand)("ory-pi", args);
|
|
@@ -89,7 +94,7 @@ function main() {
|
|
|
89
94
|
});
|
|
90
95
|
break;
|
|
91
96
|
case "watch":
|
|
92
|
-
(0, argus_1.runWatchCommand)(args);
|
|
97
|
+
(0, argus_1.runWatchCommand)("pi", args);
|
|
93
98
|
break;
|
|
94
99
|
case "help":
|
|
95
100
|
case "--help":
|
|
@@ -103,12 +108,6 @@ function main() {
|
|
|
103
108
|
process.exit(1);
|
|
104
109
|
}
|
|
105
110
|
}
|
|
106
|
-
async function postInstallPermissions(binName, harness) {
|
|
107
|
-
const bootstrapped = await (0, argus_1.maybeAutoBootstrap)(binName, harness);
|
|
108
|
-
(0, argus_1.printPermissionsOnboardingHelp)(binName, harness, {
|
|
109
|
-
bootstrappedAutomatically: bootstrapped,
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
111
|
function parseProjectDir(args) {
|
|
113
112
|
const idx = args.indexOf("--project-dir");
|
|
114
113
|
if (idx !== -1 && args[idx + 1])
|
|
@@ -186,7 +185,7 @@ After installing, the plugin hooks into these Pi lifecycle events:
|
|
|
186
185
|
|
|
187
186
|
Examples:
|
|
188
187
|
npx -y -p @ory/pi ory-pi install
|
|
189
|
-
npx -y -p @ory/pi ory-pi configure --project-url https://<
|
|
188
|
+
npx -y -p @ory/pi ory-pi configure --project-url https://<slug>.projects.oryapis.com --api-key ory_pat_...
|
|
190
189
|
npx -y -p @ory/pi ory-pi permissions bootstrap
|
|
191
190
|
npx -y -p @ory/pi ory-pi local up
|
|
192
191
|
npx -y -p @ory/pi ory-pi status
|
package/dist/cli/setup.js
CHANGED
|
@@ -93,6 +93,18 @@ function main() {
|
|
|
93
93
|
(0, assets_js_1.installPiOryAssets)(args.projectDir);
|
|
94
94
|
console.log(`Ory extension loader installed at ${loaderPath}`);
|
|
95
95
|
console.log(`Ory skills installed to ${path.join(args.projectDir, ".pi", "skills")}`);
|
|
96
|
-
(0, argus_1.printNextSteps)("Pi", "npx ory-pi-setup --uninstall"
|
|
96
|
+
(0, argus_1.printNextSteps)("Pi", "npx -y -p @ory/pi ory-pi-setup --uninstall", {
|
|
97
|
+
binName: "ory-pi",
|
|
98
|
+
harness: "pi",
|
|
99
|
+
});
|
|
97
100
|
}
|
|
98
101
|
main();
|
|
102
|
+
// When invoked directly as the `-setup` bin with `--uninstall`, also clear
|
|
103
|
+
// stored Ory credentials. When required by the plugin's main CLI, that
|
|
104
|
+
// command owns the purge, so the `require.main` guard prevents a double run.
|
|
105
|
+
if (require.main === module && process.argv.includes("--uninstall")) {
|
|
106
|
+
(0, argus_1.clearCredentialsForUninstall)().then(() => process.exit(0), (err) => {
|
|
107
|
+
console.error(err.message ?? err);
|
|
108
|
+
process.exit(1);
|
|
109
|
+
});
|
|
110
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ory/pi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Ory plugin for Pi (the minimal coding agent): scaffolding skills, a local Ory instance, and authentication, authorization, and audit for every tool call",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://ory.com",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"!dist/**/*.tsbuildinfo"
|
|
73
73
|
],
|
|
74
74
|
"dependencies": {
|
|
75
|
-
"@ory/argus": "0.
|
|
75
|
+
"@ory/argus": "0.12.0"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"typescript": "^6.0.2",
|