@ory/cline 0.10.0 → 0.11.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
@@ -41,13 +41,13 @@ npx -y -p @ory/cline ory-cline status # confirm what landed
41
41
  npx -y -p @ory/cline ory-cline uninstall # remove only the Ory shims + skills
42
42
  ```
43
43
 
44
- Uninstall removes only the scripts the Ory installer wrote (matched by a marker comment) it never touches a hook script you authored that happens to share an event name.
44
+ Install and uninstall both respect hook scripts you authored. If an event name is already taken by a script the Ory installer didn't write (matched by a marker comment), install leaves it untouched, skips that event, and prints a warning listing the skipped events — move or remove your script and re-run the install if you want Ory to handle them. Existing Ory shims are refreshed in place, and uninstall removes only the scripts the Ory installer wrote.
45
45
 
46
46
  ## Quickstart (≈ 3 minutes)
47
47
 
48
48
  From any project where you'd like Ory authentication, inside Cline:
49
49
 
50
- 1. **Start a local Ory instance.** Ask Cline *"start the local Ory stack"* or run `/local-up`. A banner prints the seeded test user's email and password — note them.
50
+ 1. **Start a local Ory instance.** Ask Cline *"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.
51
51
  2. **Scaffold Ory into your project.** Ask Cline *"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.
52
52
  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.
53
53
 
package/dist/cli/setup.js CHANGED
@@ -60,44 +60,15 @@ const os = __importStar(require("node:os"));
60
60
  const path = __importStar(require("node:path"));
61
61
  const argus_1 = require("@ory/argus");
62
62
  const assets_js_1 = require("./assets.js");
63
- const PACKAGE_NAME = "@ory/cline";
63
+ const shims_js_1 = require("./shims.js");
64
64
  const HOOK_BIN = "ory-cline-hook";
65
- /**
66
- * Cline hook events we register. Each maps to a script whose filename matches
67
- * the PascalCase event name in the hooks directory (verified against
68
- * cline@3.0.29). At runtime, the payload Cline writes to the script's stdin
69
- * carries the snake_case `hookName` the handler switches on:
70
- *
71
- * TaskStart → agent_start (auth gates)
72
- * TaskResume → agent_resume (trace-only)
73
- * TaskCancel → agent_abort (trace-only)
74
- * TaskComplete → agent_end (trace-only)
75
- * TaskError → agent_error (trace-only)
76
- * PreToolUse → tool_call (permission gate, blocking)
77
- * PostToolUse → tool_result (trace-only)
78
- * UserPromptSubmit → prompt_submit (trace-only)
79
- * PreCompact → pre_compact (trace-only)
80
- * SessionShutdown → session_shutdown (trace-only)
81
- */
82
- const HOOK_EVENTS = [
83
- "TaskStart",
84
- "TaskResume",
85
- "TaskCancel",
86
- "TaskComplete",
87
- "TaskError",
88
- "PreToolUse",
89
- "PostToolUse",
90
- "UserPromptSubmit",
91
- "PreCompact",
92
- "SessionShutdown",
93
- ];
94
65
  /**
95
66
  * The version-pinned npx command that each shim execs. Resolving via npx
96
67
  * keeps the binary off the PATH requirement and pins the version the shim was
97
68
  * generated with (read from this package's own package.json).
98
69
  */
99
70
  function hookCommand() {
100
- return `npx -y -p ${PACKAGE_NAME}@${readPackageVersion()} ${HOOK_BIN}`;
71
+ return `npx -y -p ${shims_js_1.PACKAGE_NAME}@${readPackageVersion()} ${HOOK_BIN}`;
101
72
  }
102
73
  function readPackageVersion() {
103
74
  // dist/cli/setup.js -> package root is two levels up.
@@ -117,7 +88,7 @@ function readPackageVersion() {
117
88
  */
118
89
  function shimBody() {
119
90
  return `#!/bin/sh
120
- # Ory plugin hook shim for Cline. Generated by ${PACKAGE_NAME} — do not edit.
91
+ # Ory plugin hook shim for Cline. Generated by ${shims_js_1.PACKAGE_NAME} — do not edit.
121
92
  # Forwards the event payload (stdin JSON) to the Ory hook and returns its
122
93
  # JSON decision on stdout.
123
94
  exec ${hookCommand()}
@@ -148,19 +119,6 @@ function getRulesRoot(args) {
148
119
  }
149
120
  return path.join(args.projectDir, ".clinerules");
150
121
  }
151
- /**
152
- * Marker so uninstall only removes scripts we wrote — never a hook script the
153
- * user authored that happens to share an event name.
154
- */
155
- const ORY_MARKER = `${PACKAGE_NAME}`;
156
- function isOryShim(file) {
157
- try {
158
- return fs.readFileSync(file, "utf-8").includes(ORY_MARKER);
159
- }
160
- catch {
161
- return false;
162
- }
163
- }
164
122
  function main() {
165
123
  if (process.argv.includes("--help") || process.argv.includes("-h")) {
166
124
  (0, argus_1.printSetupHelp)("ory-cline-setup", "Cline", {
@@ -172,7 +130,7 @@ function main() {
172
130
  const args = (0, argus_1.parseSetupArgs)({ supportsGlobal: true });
173
131
  const body = shimBody();
174
132
  if (args.print) {
175
- for (const event of HOOK_EVENTS) {
133
+ for (const event of shims_js_1.HOOK_EVENTS) {
176
134
  console.log(`# ── ${event} ───────────────────────────────`);
177
135
  console.log(body);
178
136
  }
@@ -186,9 +144,9 @@ function main() {
186
144
  }
187
145
  else {
188
146
  let removed = 0;
189
- for (const event of HOOK_EVENTS) {
147
+ for (const event of shims_js_1.HOOK_EVENTS) {
190
148
  const file = path.join(hooksDir, event);
191
- if (fs.existsSync(file) && isOryShim(file)) {
149
+ if (fs.existsSync(file) && (0, shims_js_1.isOryShim)(file)) {
192
150
  fs.unlinkSync(file);
193
151
  removed++;
194
152
  }
@@ -199,16 +157,18 @@ function main() {
199
157
  console.log(`Removed Ory skills from ${path.join(rulesRoot, "skills")}`);
200
158
  return;
201
159
  }
202
- fs.mkdirSync(hooksDir, { recursive: true });
203
- for (const event of HOOK_EVENTS) {
204
- const file = path.join(hooksDir, event);
205
- fs.writeFileSync(file, body, { mode: 0o755 });
206
- // Re-assert the mode in case a pre-existing file ignored the create mode.
207
- fs.chmodSync(file, 0o755);
208
- }
160
+ // Write the per-event shims, skipping any event whose script the user
161
+ // authored (i.e. it exists but is not an Ory shim). Existing Ory shims
162
+ // are refreshed.
163
+ const { written, skipped } = (0, shims_js_1.writeHookShims)(hooksDir, body);
209
164
  (0, assets_js_1.installClineOryAssets)(rulesRoot);
210
165
  console.log(`Ory hook scripts installed to ${hooksDir}`);
211
- console.log(` Scripts: ${HOOK_EVENTS.join(", ")}`);
166
+ console.log(` Scripts: ${written.length > 0 ? written.join(", ") : "(none)"}`);
167
+ if (skipped.length > 0) {
168
+ console.warn("");
169
+ console.warn((0, shims_js_1.formatSkippedWarning)(skipped));
170
+ console.warn("");
171
+ }
212
172
  console.log(`Ory skills installed to ${path.join(rulesRoot, "skills")}`);
213
173
  (0, argus_1.printNextSteps)("Cline", "npx ory-cline-setup --uninstall");
214
174
  }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Hook-shim writing for the Ory Cline plugin, factored out of the setup
3
+ * CLI so the skip-vs-overwrite logic is directly testable.
4
+ *
5
+ * Cline discovers hooks by filename in the hooks directory, so an install
6
+ * that blindly writes every event shim would clobber hook scripts the
7
+ * user authored. Install therefore only writes a shim when the target is
8
+ * absent or is an Ory-generated shim (detected via a content marker);
9
+ * user-authored scripts are skipped and reported.
10
+ */
11
+ export declare const PACKAGE_NAME = "@ory/cline";
12
+ /**
13
+ * Cline hook events we register. Each maps to a script whose filename matches
14
+ * the PascalCase event name in the hooks directory (verified against
15
+ * cline@3.0.29). At runtime, the payload Cline writes to the script's stdin
16
+ * carries the snake_case `hookName` the handler switches on:
17
+ *
18
+ * TaskStart → agent_start (auth gates)
19
+ * TaskResume → agent_resume (trace-only)
20
+ * TaskCancel → agent_abort (trace-only)
21
+ * TaskComplete → agent_end (trace-only)
22
+ * TaskError → agent_error (trace-only)
23
+ * PreToolUse → tool_call (permission gate, blocking)
24
+ * PostToolUse → tool_result (trace-only)
25
+ * UserPromptSubmit → prompt_submit (trace-only)
26
+ * PreCompact → pre_compact (trace-only)
27
+ * SessionShutdown → session_shutdown (trace-only)
28
+ */
29
+ export declare const HOOK_EVENTS: readonly ["TaskStart", "TaskResume", "TaskCancel", "TaskComplete", "TaskError", "PreToolUse", "PostToolUse", "UserPromptSubmit", "PreCompact", "SessionShutdown"];
30
+ export declare function isOryShim(file: string): boolean;
31
+ export interface WriteShimsResult {
32
+ /** Events whose shim was written (fresh or refreshed Ory shim). */
33
+ written: string[];
34
+ /** Events skipped because a non-Ory (user-authored) script exists. */
35
+ skipped: string[];
36
+ }
37
+ /**
38
+ * Write the per-event hook shims into `hooksDir`. A target that already
39
+ * exists and is NOT an Ory shim is left untouched and reported in
40
+ * `skipped`; existing Ory shims are refreshed in place.
41
+ */
42
+ export declare function writeHookShims(hooksDir: string, body: string, events?: readonly string[]): WriteShimsResult;
43
+ /**
44
+ * Human-readable warning for events whose shims were skipped because a
45
+ * user-authored script already owns the event name.
46
+ */
47
+ export declare function formatSkippedWarning(skipped: readonly string[]): string;
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ /**
3
+ * Hook-shim writing for the Ory Cline plugin, factored out of the setup
4
+ * CLI so the skip-vs-overwrite logic is directly testable.
5
+ *
6
+ * Cline discovers hooks by filename in the hooks directory, so an install
7
+ * that blindly writes every event shim would clobber hook scripts the
8
+ * user authored. Install therefore only writes a shim when the target is
9
+ * absent or is an Ory-generated shim (detected via a content marker);
10
+ * user-authored scripts are skipped and reported.
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
+ exports.HOOK_EVENTS = exports.PACKAGE_NAME = void 0;
47
+ exports.isOryShim = isOryShim;
48
+ exports.writeHookShims = writeHookShims;
49
+ exports.formatSkippedWarning = formatSkippedWarning;
50
+ const fs = __importStar(require("node:fs"));
51
+ const path = __importStar(require("node:path"));
52
+ exports.PACKAGE_NAME = "@ory/cline";
53
+ /**
54
+ * Cline hook events we register. Each maps to a script whose filename matches
55
+ * the PascalCase event name in the hooks directory (verified against
56
+ * cline@3.0.29). At runtime, the payload Cline writes to the script's stdin
57
+ * carries the snake_case `hookName` the handler switches on:
58
+ *
59
+ * TaskStart → agent_start (auth gates)
60
+ * TaskResume → agent_resume (trace-only)
61
+ * TaskCancel → agent_abort (trace-only)
62
+ * TaskComplete → agent_end (trace-only)
63
+ * TaskError → agent_error (trace-only)
64
+ * PreToolUse → tool_call (permission gate, blocking)
65
+ * PostToolUse → tool_result (trace-only)
66
+ * UserPromptSubmit → prompt_submit (trace-only)
67
+ * PreCompact → pre_compact (trace-only)
68
+ * SessionShutdown → session_shutdown (trace-only)
69
+ */
70
+ exports.HOOK_EVENTS = [
71
+ "TaskStart",
72
+ "TaskResume",
73
+ "TaskCancel",
74
+ "TaskComplete",
75
+ "TaskError",
76
+ "PreToolUse",
77
+ "PostToolUse",
78
+ "UserPromptSubmit",
79
+ "PreCompact",
80
+ "SessionShutdown",
81
+ ];
82
+ /**
83
+ * Marker so install/uninstall only ever overwrite or remove scripts we
84
+ * wrote — never a hook script the user authored that happens to share an
85
+ * event name.
86
+ */
87
+ const ORY_MARKER = `${exports.PACKAGE_NAME}`;
88
+ function isOryShim(file) {
89
+ try {
90
+ return fs.readFileSync(file, "utf-8").includes(ORY_MARKER);
91
+ }
92
+ catch {
93
+ return false;
94
+ }
95
+ }
96
+ /**
97
+ * Write the per-event hook shims into `hooksDir`. A target that already
98
+ * exists and is NOT an Ory shim is left untouched and reported in
99
+ * `skipped`; existing Ory shims are refreshed in place.
100
+ */
101
+ function writeHookShims(hooksDir, body, events = exports.HOOK_EVENTS) {
102
+ fs.mkdirSync(hooksDir, { recursive: true });
103
+ const written = [];
104
+ const skipped = [];
105
+ for (const event of events) {
106
+ const file = path.join(hooksDir, event);
107
+ if (fs.existsSync(file) && !isOryShim(file)) {
108
+ skipped.push(event);
109
+ continue;
110
+ }
111
+ fs.writeFileSync(file, body, { mode: 0o755 });
112
+ // Re-assert the mode in case a pre-existing file ignored the create mode.
113
+ fs.chmodSync(file, 0o755);
114
+ written.push(event);
115
+ }
116
+ return { written, skipped };
117
+ }
118
+ /**
119
+ * Human-readable warning for events whose shims were skipped because a
120
+ * user-authored script already owns the event name.
121
+ */
122
+ function formatSkippedWarning(skipped) {
123
+ return [
124
+ `Warning: skipped ${skipped.length} event(s) — an existing hook script not`,
125
+ `written by ${exports.PACKAGE_NAME} already owns each of these names:`,
126
+ ` ${skipped.join(", ")}`,
127
+ "Those scripts were left untouched, so Ory will not see those events.",
128
+ "To let Ory handle an event, move or remove your script from the hooks",
129
+ "directory (or fold this shim's command into it) and re-run the install.",
130
+ ].join("\n");
131
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ory/cline",
3
- "version": "0.10.0",
3
+ "version": "0.11.1",
4
4
  "description": "Ory plugin for Cline: 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",
@@ -66,7 +66,7 @@
66
66
  "!dist/**/*.tsbuildinfo"
67
67
  ],
68
68
  "dependencies": {
69
- "@ory/argus": "0.10.0"
69
+ "@ory/argus": "0.11.1"
70
70
  },
71
71
  "devDependencies": {
72
72
  "typescript": "^6.0.2",