@ory/pi 0.11.1 → 0.12.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/README.md CHANGED
@@ -1,126 +1,142 @@
1
1
  # Ory Agent Plugin: Pi
2
2
 
3
- [Ory](https://ory.com) bundled into [Pi](https://pi.dev) ([badlogic/pi-mono](https://github.com/badlogic/pi-mono), a minimal coding agent): skills and commands that scaffold Ory authentication into your codebase, a local Ory stack you can spin up in one command, and (when pointed at an Ory project) authentication, authorization, and audit for every tool Pi runs.
3
+ Security and developer experience for [Pi](https://pi.dev), powered by [Ory](https://ory.com).
4
4
 
5
- You don't need an Ory account or any prior Ory experience to start.
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
- The extension contract is verified against `@earendil-works/pi-coding-agent` v0.80.2 — the `session_start`/`tool_call`/`tool_result` events, the `tool_call` block signature (`{ block?, reason? }`), the `~/.pi/agent` config root, the `.pi/extensions/` auto-discovery loader, and the `.pi/skills/` location all match.
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
- ## New to Ory?
9
+ ## What you'll need
10
10
 
11
- [Ory](https://www.ory.com/docs/) is an open-source identity and access platform — login, registration, sessions, social sign-in, multi-factor auth, and fine-grained permissions, so you don't have to build any of that yourself. Two things make it easy to try with no prior experience:
12
-
13
- - **Ory Elements** are prebuilt, themeable UI components for the auth pages. The scaffolding skills wire them into your app for you.
14
- - **The local Ory stack** is a complete Ory running on your laptop in Docker — no account, no signup, no API key.
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
- 1. **Build auth into your app.** Have Pi scaffold Ory login, registration, social sign-in, and permissions into the project you're working on, backed by the local stack. This needs nothing but Docker.
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
- ## Prerequisites
18
+ ```bash
19
+ npm install @ory/pi
20
+ ```
24
21
 
25
- - [Pi](https://pi.dev) installed (`@earendil-works/pi-coding-agent`)
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
- ## Install
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
- `install` drops a tiny loader file at `<project>/.pi/extensions/ory.js` (project scope, the default) — Pi auto-discovers every `*.js`/`*.ts` file under `.pi/extensions/` and runs its default export as an extension factory, so the loader simply re-exports the installed `@ory/pi` package's factory (`export { default } from "@ory/pi";`). No `settings.json` entry is needed. With `--global` the loader lands at `~/.pi/agent/extensions/ory.js` instead. Install also materializes the Ory skills and commands under `<project>/.pi/skills`.
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
- The plugin must be resolvable from the project's `node_modules`, so install `@ory/pi` first (`npm install @ory/pi` or add it to your project's dependencies) before running `ory-pi install`.
36
+ That's it. Confirm everything landed with:
39
37
 
40
38
  ```bash
41
- npx -y -p @ory/pi ory-pi install --global # install the loader for all projects
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, skills, and commands
39
+ npx -y -p @ory/pi ory-pi status
44
40
  ```
45
41
 
46
- `status` prints configuration, user and agent identity, per-tool permission coverage, whether the extension loader is installed, the hooks it wires up, and a tail of recent debug logs.
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
- ### Alternative: install via Pi's package manager
46
+ <details>
47
+ <summary>Prefer to let Pi manage the plugin?</summary>
49
48
 
50
- If you prefer Pi to manage the extension, point its package installer at the npm package:
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 records the package under `settings.packages` and reads the `pi.extensions` manifest from `@ory/pi`'s `package.json` (which points at `dist/index.js`, the default-exported factory). Either path leads to the same extension; pick whichever fits your workflow.
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
- ## Quickstart (≈ 3 minutes)
57
+ </details>
59
58
 
60
- From any project where you'd like Ory authentication, inside Pi:
59
+ ## What you get
61
60
 
62
- 1. **Start a local Ory instance.** Ask Pi *"start the local Ory stack"* or invoke the `ory-local-up` skill. A banner prints the seeded test user's email and password — note them.
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
- Continue to [Agent security](#agent-security) when you're ready to enforce.
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
- ## How the integration works
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 loads in-process **TypeScript/JavaScript extensions** auto-discovered from `.pi/extensions/` (project) and `~/.pi/agent/extensions/` (global), loaded with [jiti](https://github.com/unjs/jiti). Each file's **default export** is invoked as a factory function at startup; the installed loader re-exports `@ory/pi`'s default factory.
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
- The phases map as:
71
+ ### See what's happening
73
72
 
74
- - **Session start** (factory body) — run the user and agent auth gates. Advisory only: Pi's factory has no return-value channel to hard-block at session start, so user login refreshes tokens and emits an audit span but the session always proceeds.
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
- **Pi excludes MCP and sub-agents by design**, so this plugin has **no MCP server registration and no sub-agent identity path** — unlike the Claude Code or Continue plugins, there is nothing to register beyond the extension itself.
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
- The plugin is **fail-open** on its own infrastructure failures (network errors, rate limits, missing config): the agent always starts, and enforcement is only as strong as your permission grants.
78
+ ```bash
79
+ npx -y -p @ory/pi ory-pi watch
80
+ ```
81
81
 
82
- ## Agent security
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
- Once pointed at an Ory project (local or hosted), Pi's session and every tool call can be governed by Ory.
85
+ ### Ready to enforce?
85
86
 
86
- - **Authentication.** The human at the keyboard (the **user**) authenticates interactively via Ory Identities when user login is on (`ORY_USER_LOGIN=true`, off by default — browser PKCE flow on first session, persisted thereafter). The Pi process (the **agent**) gets its own OAuth2 identity via [Dynamic Client Registration (RFC 7591)](https://datatracker.ietf.org/doc/html/rfc7591) on first run.
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
- Switch back any time with `permissions observe`. To disable Ory entirely (audit logging only), run `ory-pi configure --audit-only`.
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
- ## Pointing at a real Ory project
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
- The Quickstart uses the local stack. To point at a hosted [Ory Network](https://console.ory.sh) project:
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://<id>.projects.oryapis.com \
114
- --oauth2-client-id <public 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 required whenever `--project-url` is set — the user PKCE flow needs a public OAuth2 client registered with the four loopback redirect URIs (`http://127.0.0.1:47823..47826/callback`). See the [repo README](../../README.md) and [`AGENTS.md`](../../AGENTS.md) for the full environment-variable reference and permission-mode semantics. Config is shared across every Ory agent plugin at `~/.config/ory-agent-plugins/config.json`.
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
- Without configuration the plugin still loads cleanly and runs in **pass-through mode**: skills and commands work, but nothing is blocked.
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
- ## Links
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
- postInstallPermissions("ory-pi", "pi").then(() => process.exit(0), (err) => {
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://<id>.projects.oryapis.com --api-key ory_pat_...
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.11.1",
3
+ "version": "0.12.1",
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,8 @@
72
72
  "!dist/**/*.tsbuildinfo"
73
73
  ],
74
74
  "dependencies": {
75
- "@ory/argus": "0.11.1"
75
+ "reo-census": "^1.2.8",
76
+ "@ory/argus": "0.12.1"
76
77
  },
77
78
  "devDependencies": {
78
79
  "typescript": "^6.0.2",