@ory/gemini-cli 0.1.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 ADDED
@@ -0,0 +1,100 @@
1
+ # Ory Agent Extension: Gemini CLI
2
+
3
+ [Ory](https://ory.com) bundled into [Gemini CLI](https://github.com/google-gemini/gemini-cli): skills and TOML slash 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 Gemini runs.
4
+
5
+ ## Install
6
+
7
+ Try these in order; the first that works is the simplest path:
8
+
9
+ **1. Google's public extension registry.** Find **Ory Agent Extension** and install:
10
+
11
+ ```bash
12
+ gemini extensions install ory-agent-extension
13
+ ```
14
+
15
+ **2. The Ory-hosted extension source:**
16
+
17
+ ```bash
18
+ gemini extensions install https://github.com/ory/gemini-cli-extension
19
+ ```
20
+
21
+ **3. The Ory installer.** No prior `npm install` required:
22
+
23
+ ```bash
24
+ npx @ory/gemini-cli install
25
+ npx @ory/gemini-cli uninstall
26
+ ```
27
+
28
+ Every flow installs the same extension: skills, TOML slash commands, hooks, and the Ory MCP server. If the `gemini` binary isn't on your `PATH`, `npx ory-gemini-setup` writes the extension config directly.
29
+
30
+ ## Developer experience
31
+
32
+ This extension is a productivity layer for Ory itself. You don't need a real Ory project, an account, or any prior Ory experience to start using it.
33
+
34
+ ### Skills for scaffolding Ory into your application
35
+
36
+ Ask Gemini to add Ory auth to your codebase. The extension bundles four skills that the model auto-invokes by description:
37
+
38
+ - **`ory-auth-setup`**: full project setup. Install the Ory CLI, create an Ory Network project, add Ory Elements, configure the SDK, build the auth pages, wire session middleware.
39
+ - **`ory-login-flow`**: login, registration, recovery, verification, and settings pages with Ory Elements. Next.js App Router and React SPA variants.
40
+ - **`ory-social-login`**: Google, GitHub, Apple, Microsoft, Discord, and other OIDC providers with Jsonnet data mappers.
41
+ - **`ory-local-dev`**: drive the local Ory stack (below) from within Gemini to prototype and test against without a remote project.
42
+
43
+ Skills are versioned with the extension so guidance stays in sync as Ory APIs evolve.
44
+
45
+ ### Ory MCP server
46
+
47
+ Bundled and registered automatically. It exposes the Ory CLI and the Ory Network REST API as MCP tools so Gemini can manage identities, OAuth2 clients, projects, permission tuples, and configuration without ever leaving the chat. Useful for seeding test data, verifying a scaffolded integration, or running one-off admin tasks.
48
+
49
+ ### Local Ory stack in one command
50
+
51
+ ```
52
+ /ory:local-up # start a local Ory instance in Docker
53
+ /ory:local-down # tear it all down
54
+ ```
55
+
56
+ `local up` runs a local Ory instance in Docker, covering everything the extension and your scaffolded application need. It also brings up a login UI on `:3000` and Jaeger on `:16686`, all reachable through `http://localhost:4000`. A test user identity is seeded and the credentials are printed for you. Use it to:
57
+
58
+ - **Learn Ory hands-on** without signing up for a hosted project.
59
+ - **Prototype** flows (login, social, MFA, recovery, permission tuples) against a real Ory backend in your local dev loop.
60
+ - **Test** an auth integration end-to-end before pushing anything to a real environment.
61
+ - **Develop** your application against the same identity, OAuth2, and permission surfaces you'll ship with.
62
+
63
+ Point `ORY_PROJECT_URL` at `http://localhost:4000` (or run `npx ory-gemini configure`) and the security features below run against the local stack.
64
+
65
+ ## Configure
66
+
67
+ ```bash
68
+ npx ory-gemini configure --project-url https://<id>.projects.oryapis.com --api-key ory_pat_...
69
+ ```
70
+
71
+ Config is saved to `~/.config/ory-agent-plugins/config.json` and shared across every Ory agent plugin or extension on the machine. Without it the extension still loads cleanly and runs in **pass-through mode**: skills and commands work, but nothing is blocked.
72
+
73
+ ## Agent security (Argus)
74
+
75
+ Once the extension is pointed at an Ory project (local or hosted), Gemini's session and every tool call are governed by Ory.
76
+
77
+ - **Authentication.** Two identities. The human at the keyboard (the **user**) authenticates interactively via Ory Identities when `ORY_AUTH_GATE=1`. The Gemini process (the **agent**) gets its own OAuth2 identity, self-registered via Dynamic Client Registration on first run.
78
+ - **Authorization.** Before any tool runs, the extension checks Ory Permissions against the user's subject and blocks the call on `deny`. MCP tool calls additionally get a server-level check.
79
+ - **Audit.** Every decision (allow, deny, fallback) is recorded as a structured trace span: NDJSON file output and/or OTLP/HTTP export to Jaeger, Honeycomb, Grafana, and similar collectors. The user-to-agent delegation is written to Ory as a Zanzibar tuple so "agent X acting on behalf of user Y" stays queryable after tokens expire.
80
+
81
+ The extension is **fail-open** on its own infrastructure failures (network errors, rate limits, missing config), so enforcement is only as strong as your tuples; grant explicit `invoke` relations for the tools each user should be able to run.
82
+
83
+ ## CLI
84
+
85
+ ```
86
+ npx ory-gemini install [--link]
87
+ npx ory-gemini uninstall
88
+ npx ory-gemini configure [--project-url <url>] [--api-key <key>] [--audit-only]
89
+ npx ory-gemini agent <status|unregister> Manage the agent's OAuth2 identity
90
+ npx ory-gemini local <up|down|status|seed|logs|env|configure|reset>
91
+ npx ory-gemini status
92
+ ```
93
+
94
+ ## Links
95
+
96
+ - [ory.com](https://ory.com)
97
+
98
+ ## License
99
+
100
+ Apache-2.0
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Materialize / clean the Ory skill catalog and slash commands for the
3
+ * Gemini CLI plugin. Used both by the primary install path (which seeds
4
+ * the bundled extension dir before `gemini extensions install`) and by
5
+ * the manual-setup fallback (which writes into the project's `.gemini/`
6
+ * tree).
7
+ */
8
+ /**
9
+ * Write all Ory skills (4 guide skills) and TOML slash commands (local-up,
10
+ * local-down) under a Gemini-conventional root containing `skills/` and
11
+ * `commands/`. For the bundled extension that's the `gemini-extension`
12
+ * directory; for the manual-setup fallback it's `<projectDir>/.gemini`.
13
+ */
14
+ export declare function installGeminiOryAssets(root: string): void;
15
+ /** Remove every skill + command this plugin installed under `root`. */
16
+ export declare function uninstallGeminiOryAssets(root: string): void;
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ /**
3
+ * Materialize / clean the Ory skill catalog and slash commands for the
4
+ * Gemini CLI plugin. Used both by the primary install path (which seeds
5
+ * the bundled extension dir before `gemini extensions install`) and by
6
+ * the manual-setup fallback (which writes into the project's `.gemini/`
7
+ * tree).
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.installGeminiOryAssets = installGeminiOryAssets;
44
+ exports.uninstallGeminiOryAssets = uninstallGeminiOryAssets;
45
+ const fs = __importStar(require("node:fs"));
46
+ const path = __importStar(require("node:path"));
47
+ const argus_1 = require("@ory/argus");
48
+ const RENDER_OPTS = {
49
+ binName: "ory-gemini",
50
+ packageName: "@ory/gemini-cli",
51
+ };
52
+ /**
53
+ * Subdir under `commands/` for our TOML files. The folder name becomes the
54
+ * slash-command namespace, so files at `commands/ory/local-up.toml` are
55
+ * exposed as `/ory:local-up`.
56
+ */
57
+ const CMD_SUBDIR = "ory";
58
+ /**
59
+ * Write all Ory skills (4 guide skills) and TOML slash commands (local-up,
60
+ * local-down) under a Gemini-conventional root containing `skills/` and
61
+ * `commands/`. For the bundled extension that's the `gemini-extension`
62
+ * directory; for the manual-setup fallback it's `<projectDir>/.gemini`.
63
+ */
64
+ function installGeminiOryAssets(root) {
65
+ const skillsDir = path.join(root, "skills");
66
+ fs.rmSync(skillsDir, { recursive: true, force: true });
67
+ (0, argus_1.writeSkillTree)(skillsDir, (0, argus_1.renderOrySkills)("gemini-cli", RENDER_OPTS));
68
+ const cmdDir = path.join(root, "commands", CMD_SUBDIR);
69
+ fs.rmSync(cmdDir, { recursive: true, force: true });
70
+ fs.mkdirSync(cmdDir, { recursive: true });
71
+ for (const cmd of (0, argus_1.renderOryCommands)("gemini-cli", RENDER_OPTS)) {
72
+ fs.writeFileSync(path.join(cmdDir, `${cmd.slug}.toml`), (0, argus_1.commandToToml)(cmd));
73
+ }
74
+ }
75
+ function safeRmEmpty(dir) {
76
+ try {
77
+ if (fs.existsSync(dir) && fs.readdirSync(dir).length === 0) {
78
+ fs.rmdirSync(dir);
79
+ }
80
+ }
81
+ catch {
82
+ /* ignore — leave the dir if removal fails. */
83
+ }
84
+ }
85
+ /** Remove every skill + command this plugin installed under `root`. */
86
+ function uninstallGeminiOryAssets(root) {
87
+ const skillsDir = path.join(root, "skills");
88
+ if (fs.existsSync(skillsDir)) {
89
+ (0, argus_1.removeSkillDirs)(skillsDir, argus_1.ORY_SKILL_NAMES);
90
+ safeRmEmpty(skillsDir);
91
+ }
92
+ const cmdDir = path.join(root, "commands", CMD_SUBDIR);
93
+ if (fs.existsSync(cmdDir)) {
94
+ for (const slug of argus_1.ORY_COMMAND_SLUGS) {
95
+ const f = path.join(cmdDir, `${slug}.toml`);
96
+ if (fs.existsSync(f))
97
+ fs.unlinkSync(f);
98
+ }
99
+ safeRmEmpty(cmdDir);
100
+ safeRmEmpty(path.join(root, "commands"));
101
+ }
102
+ }
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Main CLI for @ory/gemini-cli.
4
+ *
5
+ * Usage:
6
+ * npx ory-gemini install [--link] Install as Gemini CLI extension
7
+ * npx ory-gemini uninstall Remove extension
8
+ * npx ory-gemini configure Set or view Ory credentials
9
+ * npx ory-gemini setup [--project-dir] Write hooks to settings.json directly
10
+ * npx ory-gemini status Show plugin status
11
+ */
12
+ export {};
@@ -0,0 +1,202 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Main CLI for @ory/gemini-cli.
5
+ *
6
+ * Usage:
7
+ * npx ory-gemini install [--link] Install as Gemini CLI extension
8
+ * npx ory-gemini uninstall Remove extension
9
+ * npx ory-gemini configure Set or view Ory credentials
10
+ * npx ory-gemini setup [--project-dir] Write hooks to settings.json directly
11
+ * npx ory-gemini status Show plugin status
12
+ */
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ Object.defineProperty(exports, "__esModule", { value: true });
47
+ const path = __importStar(require("node:path"));
48
+ const fs = __importStar(require("node:fs"));
49
+ const node_child_process_1 = require("node:child_process");
50
+ const argus_1 = require("@ory/argus");
51
+ const assets_js_1 = require("./assets.js");
52
+ const EXTENSION_DIR = path.resolve(__dirname, "..", "..", "gemini-extension");
53
+ const PACKAGE_ROOT = path.resolve(__dirname, "..", "..");
54
+ function main() {
55
+ const [command, ...args] = process.argv.slice(2);
56
+ switch (command) {
57
+ case "install":
58
+ install(args);
59
+ break;
60
+ case "uninstall":
61
+ uninstall(args);
62
+ break;
63
+ case "configure":
64
+ (0, argus_1.runConfigureCommand)("ory-gemini", args);
65
+ break;
66
+ case "agent":
67
+ (0, argus_1.runAgentCommand)("ory-gemini", args).then((code) => process.exit(code), (err) => {
68
+ console.error(err.message ?? err);
69
+ process.exit(1);
70
+ });
71
+ break;
72
+ case "setup":
73
+ require("./setup.js");
74
+ break;
75
+ case "status":
76
+ status();
77
+ break;
78
+ case "local":
79
+ (0, argus_1.runLocalCommand)("ory-gemini", args).catch((err) => {
80
+ console.error(err.message ?? err);
81
+ process.exit(1);
82
+ });
83
+ break;
84
+ case "help":
85
+ case "--help":
86
+ case "-h":
87
+ case undefined:
88
+ help();
89
+ break;
90
+ default:
91
+ console.error(`Unknown command: ${command}`);
92
+ help();
93
+ process.exit(1);
94
+ }
95
+ }
96
+ function install(args) {
97
+ const isLink = args.includes("--link");
98
+ // Materialize the Ory skill catalog and slash commands into the bundled
99
+ // extension dir before handing it to `gemini extensions install/link`,
100
+ // which copies/symlinks the whole tree into ~/.gemini/extensions/ory.
101
+ console.log("Materializing Ory skills and commands into the extension...");
102
+ (0, assets_js_1.installGeminiOryAssets)(EXTENSION_DIR);
103
+ const geminiAvailable = (0, node_child_process_1.spawnSync)("gemini", ["--version"], {
104
+ stdio: "pipe",
105
+ }).status === 0;
106
+ if (geminiAvailable) {
107
+ if (isLink) {
108
+ console.log("Linking Ory extension for development...");
109
+ const result = (0, node_child_process_1.spawnSync)("gemini", ["extensions", "link", EXTENSION_DIR], { stdio: "inherit" });
110
+ if (result.status === 0) {
111
+ console.log("");
112
+ console.log("Ory extension linked for development.");
113
+ (0, argus_1.printEnvHelp)("ory-gemini");
114
+ }
115
+ else {
116
+ console.error("gemini extensions link failed. Falling back to manual setup...");
117
+ manualSetup(args);
118
+ }
119
+ }
120
+ else {
121
+ console.log("Installing Ory extension...");
122
+ const result = (0, node_child_process_1.spawnSync)("gemini", ["extensions", "install", EXTENSION_DIR], { stdio: "inherit" });
123
+ if (result.status === 0) {
124
+ console.log("");
125
+ console.log("Ory extension installed.");
126
+ (0, argus_1.printEnvHelp)("ory-gemini");
127
+ }
128
+ else {
129
+ console.error("");
130
+ console.error("gemini extensions install failed. Falling back to manual setup...");
131
+ manualSetup(args);
132
+ }
133
+ }
134
+ }
135
+ else {
136
+ console.log("Gemini CLI not found on PATH. Using manual setup...");
137
+ manualSetup(args);
138
+ }
139
+ }
140
+ function uninstall(args) {
141
+ const geminiAvailable = (0, node_child_process_1.spawnSync)("gemini", ["--version"], {
142
+ stdio: "pipe",
143
+ }).status === 0;
144
+ if (geminiAvailable) {
145
+ console.log("Uninstalling Ory extension...");
146
+ (0, node_child_process_1.spawnSync)("gemini", ["extensions", "uninstall", "ory"], { stdio: "inherit" });
147
+ }
148
+ else {
149
+ const setupArgs = ["--uninstall", ...args];
150
+ process.argv = ["node", "setup.js", ...setupArgs];
151
+ require("./setup.js");
152
+ }
153
+ }
154
+ function manualSetup(args) {
155
+ process.argv = ["node", "setup.js", ...args];
156
+ require("./setup.js");
157
+ }
158
+ function status() {
159
+ console.log("Ory Agent Plugin Status (Gemini CLI)");
160
+ console.log("====================================");
161
+ console.log("");
162
+ (0, argus_1.printOryConfig)();
163
+ (0, argus_1.printEnvironment)();
164
+ // Extension-specific status
165
+ console.log("");
166
+ console.log("Extension:");
167
+ console.log(` Directory: ${EXTENSION_DIR}`);
168
+ console.log(` Manifest: ${fs.existsSync(path.join(EXTENSION_DIR, "gemini-extension.json")) ? "found" : "MISSING"}`);
169
+ console.log(` Hook script: ${fs.existsSync(path.join(PACKAGE_ROOT, "dist", "hook.js")) ? "built" : "NOT BUILT (run pnpm build)"}`);
170
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? "~";
171
+ const extensionInstalled = fs.existsSync(path.join(home, ".gemini", "extensions", "ory"));
172
+ console.log(` Installed: ${extensionInstalled ? "yes (~/.gemini/extensions/ory)" : "no"}`);
173
+ (0, argus_1.printLogTail)();
174
+ }
175
+ function help() {
176
+ console.log(`
177
+ ory-gemini — Ory plugin for Gemini CLI
178
+
179
+ Usage:
180
+ npx ory-gemini <command> [options]
181
+
182
+ Commands:
183
+ install [--link] Install the Ory extension into Gemini CLI
184
+ uninstall Remove the Ory extension from Gemini CLI
185
+ configure Set or view Ory project URL and API key
186
+ setup [--project-dir] Write hooks directly to settings.json (fallback)
187
+ status Show plugin status and configuration
188
+ local <cmd> Manage local Ory dev environment (up, down, status, seed, ...)
189
+
190
+ After installing, the extension hooks into these Gemini CLI lifecycle events:
191
+ SessionStart Verify agent session via Ory Identities
192
+ BeforeTool Check tool permissions via Ory Permissions
193
+ AfterTool Audit log tool executions
194
+
195
+ Examples:
196
+ npx ory-gemini install # Install extension
197
+ npx ory-gemini install --link # Link for development
198
+ npx ory-gemini status # Check configuration
199
+ npx ory-gemini uninstall # Remove extension
200
+ `);
201
+ }
202
+ main();
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Setup CLI for the Ory Gemini CLI plugin.
4
+ *
5
+ * Usage:
6
+ * npx ory-gemini-setup # Auto-detect and configure
7
+ * npx ory-gemini-setup --project-dir /path/to/repo
8
+ * npx ory-gemini-setup --print # Print config to stdout without writing
9
+ * npx ory-gemini-setup --uninstall # Remove Ory hooks from settings
10
+ */
11
+ export {};
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Setup CLI for the Ory Gemini CLI plugin.
5
+ *
6
+ * Usage:
7
+ * npx ory-gemini-setup # Auto-detect and configure
8
+ * npx ory-gemini-setup --project-dir /path/to/repo
9
+ * npx ory-gemini-setup --print # Print config to stdout without writing
10
+ * npx ory-gemini-setup --uninstall # Remove Ory hooks from settings
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ const fs = __importStar(require("node:fs"));
47
+ const path = __importStar(require("node:path"));
48
+ const argus_1 = require("@ory/argus");
49
+ const assets_js_1 = require("./assets.js");
50
+ const BIN_NAME = "ory-gemini-hook";
51
+ const PACKAGE_NAME = "@ory/gemini-cli";
52
+ function getSettingsPath(args) {
53
+ return path.join(args.projectDir, ".gemini", "settings.json");
54
+ }
55
+ function generateHooksConfig() {
56
+ const cmd = (0, argus_1.resolveHookCommand)(PACKAGE_NAME, BIN_NAME);
57
+ return {
58
+ SessionStart: (0, argus_1.matcherHookEntry)(cmd),
59
+ SessionEnd: (0, argus_1.matcherHookEntry)(cmd),
60
+ BeforeTool: (0, argus_1.matcherHookEntry)(cmd),
61
+ AfterTool: (0, argus_1.matcherHookEntry)(cmd),
62
+ BeforeToolSelection: (0, argus_1.matcherHookEntry)(cmd),
63
+ Notification: (0, argus_1.matcherHookEntry)(cmd),
64
+ PreCompress: (0, argus_1.matcherHookEntry)(cmd),
65
+ };
66
+ }
67
+ function main() {
68
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
69
+ (0, argus_1.printSetupHelp)("ory-gemini-setup", "Gemini CLI");
70
+ process.exit(0);
71
+ }
72
+ const args = (0, argus_1.parseSetupArgs)();
73
+ const hooksConfig = generateHooksConfig();
74
+ if (args.print) {
75
+ console.log(JSON.stringify({ hooks: hooksConfig }, null, 2));
76
+ return;
77
+ }
78
+ const settingsPath = getSettingsPath(args);
79
+ const existing = (0, argus_1.readJsonFile)(settingsPath);
80
+ const geminiDir = path.join(args.projectDir, ".gemini");
81
+ if (args.uninstall) {
82
+ if (!fs.existsSync(settingsPath)) {
83
+ console.log("No settings file found. Nothing to uninstall.");
84
+ return;
85
+ }
86
+ let updated = (0, argus_1.removeMatcherHooks)(existing, BIN_NAME);
87
+ updated = (0, argus_1.removeMcpServer)(updated);
88
+ (0, argus_1.writeJsonFile)(settingsPath, updated);
89
+ (0, assets_js_1.uninstallGeminiOryAssets)(geminiDir);
90
+ console.log(`Removed Ory hooks and MCP server from ${settingsPath}`);
91
+ console.log(`Removed Ory skills and commands from ${geminiDir}`);
92
+ return;
93
+ }
94
+ let merged = (0, argus_1.mergeMatcherHooks)(existing, hooksConfig, BIN_NAME);
95
+ merged = (0, argus_1.mergeMcpServer)(merged);
96
+ (0, argus_1.writeJsonFile)(settingsPath, merged);
97
+ (0, assets_js_1.installGeminiOryAssets)(geminiDir);
98
+ console.log(`Ory hooks and MCP server installed to ${settingsPath}`);
99
+ console.log(`Ory skills and commands installed to ${geminiDir}`);
100
+ (0, argus_1.printNextSteps)("Gemini CLI", "npx ory-gemini-setup --uninstall");
101
+ }
102
+ main();
@@ -0,0 +1,12 @@
1
+ import { OryAgentClient, ensureUserAuthenticated, ensureAgentIdentity } from "@ory/argus";
2
+ import type { GeminiHookInput, GeminiHookOutput } from "./types.js";
3
+ export interface HandleHookEventDeps {
4
+ /** Test injection point for the user auth gate. */
5
+ authGate?: typeof ensureUserAuthenticated;
6
+ /** Test injection point for the agent identity gate. */
7
+ agentGate?: typeof ensureAgentIdentity;
8
+ }
9
+ /**
10
+ * Route a Gemini CLI hook event to the appropriate Ory integration.
11
+ */
12
+ export declare function handleHookEvent(input: GeminiHookInput, client: OryAgentClient, deps?: HandleHookEventDeps): Promise<GeminiHookOutput>;