runshift 0.0.3 → 0.0.5

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.
@@ -10,8 +10,9 @@ export function showBanner() {
10
10
  horizontalLayout: "default",
11
11
  });
12
12
  console.log(amber(banner));
13
- console.log(muted(" v0.0.2"));
14
- console.log(muted(" the control plane for agents, wherever they run.\n"));
13
+ console.log(muted(" v0.0.3"));
14
+ console.log(muted(" the control plane for agents, wherever they run."));
15
+ console.log(dim(" usage: npx runshift init [--dry-run] [--branch <name>]\n"));
15
16
  console.log(divider + "\n");
16
17
  }
17
18
  export function showNotGitRepo() {
@@ -55,12 +56,16 @@ export function showScanResults(context) {
55
56
  detections.push(`supabase/migrations/ — ${context.migrationCount} migration file${context.migrationCount === 1 ? "" : "s"} found`);
56
57
  }
57
58
  const existingRuleKeys = Object.keys(context.existingRules);
59
+ const protectedSet = new Set(context.protectedPaths);
58
60
  const cursorRules = existingRuleKeys.filter((k) => k.startsWith(".cursor/rules/"));
59
61
  if (cursorRules.length > 0) {
60
- detections.push(`.cursor/rules/ ${cursorRules.length} existing file${cursorRules.length === 1 ? "" : "s"} detected`);
62
+ const protectedCount = cursorRules.filter((k) => protectedSet.has(k)).length;
63
+ const suffix = protectedCount > 0 ? ` (${protectedCount} protected)` : "";
64
+ detections.push(`.cursor/rules/ — ${cursorRules.length} existing file${cursorRules.length === 1 ? "" : "s"} detected${suffix}`);
61
65
  }
62
66
  if (existingRuleKeys.includes("CLAUDE.md")) {
63
- detections.push("existing CLAUDE.md detected");
67
+ const claudeProtected = protectedSet.has("CLAUDE.md") ? " (protected — human-written)" : "";
68
+ detections.push(`existing CLAUDE.md detected${claudeProtected}`);
64
69
  }
65
70
  if (context.tsconfig) {
66
71
  detections.push("tsconfig.json detected");
@@ -105,12 +110,35 @@ export function showFileList(files) {
105
110
  }
106
111
  console.log(dim("\n + = create, ~ = update existing file\n"));
107
112
  }
113
+ export function showSelectedFiles(allFiles, selectedPaths) {
114
+ const selected = new Set(selectedPaths);
115
+ console.log(amber(" relay understood:\n"));
116
+ for (const file of allFiles) {
117
+ if (selected.has(file.path)) {
118
+ console.log(dim(" ✓ ") + file.path + dim(" (included)"));
119
+ }
120
+ else {
121
+ console.log(dim(" ✗ ") + muted(file.path) + dim(" (excluded)"));
122
+ }
123
+ }
124
+ console.log();
125
+ }
108
126
  export function showWriting(filePath) {
109
127
  console.log(dim(" ✓ ") + filePath);
110
128
  }
111
129
  export function showCommit() {
112
130
  console.log(dim(" ✓ ") + "committed");
113
131
  }
132
+ export function showProtectedFiles(protectedPaths) {
133
+ if (protectedPaths.length === 0)
134
+ return;
135
+ console.log();
136
+ console.log(amber(" relay preserved your existing files:"));
137
+ for (const p of protectedPaths) {
138
+ console.log(dim(` ~ ${p} — human-written, not overwritten`));
139
+ }
140
+ console.log(dim(" run npx runshift update to review suggested changes.\n"));
141
+ }
114
142
  export function showSummary(summary) {
115
143
  console.log(muted(` ${summary.replace(/\n/g, "\n ")}\n`));
116
144
  }
@@ -123,6 +151,30 @@ export function showSuccess() {
123
151
  console.log(muted(" connect to the runshift control plane: ") + amber("runshift.ai"));
124
152
  console.log("\n" + divider + "\n");
125
153
  }
154
+ export function showDataPolicy() {
155
+ console.log(amber(" relay will send to runshift.ai:\n"));
156
+ console.log(dim(" ✓ package.json (dependencies and scripts only)"));
157
+ console.log(dim(" ✓ directory structure (top 2 levels, folder names only)"));
158
+ console.log(dim(" ✓ .env.example (key names only — values are never read)"));
159
+ console.log(dim(" ✓ existing CLAUDE.md (if present)"));
160
+ console.log(dim(" ✓ existing .cursor/rules/ (if present)"));
161
+ console.log(dim(" ✓ migration file names (no file contents)"));
162
+ console.log(dim("\n no source code is sent."));
163
+ console.log(dim(" no secret values are ever read.\n"));
164
+ }
165
+ export function showDryRunComplete() {
166
+ console.log("\n" + divider + "\n");
167
+ console.log(amber(" dry run complete — no files written."));
168
+ console.log(dim(" run npx runshift init to install.\n"));
169
+ console.log(divider + "\n");
170
+ }
171
+ export function showCancelled() {
172
+ console.log();
173
+ console.log(amber(" no changes made."));
174
+ console.log(dim(" run npx runshift init when you're ready."));
175
+ console.log();
176
+ console.log(divider + "\n");
177
+ }
126
178
  export function showError(type, message) {
127
179
  console.log();
128
180
  switch (type) {
@@ -1 +1 @@
1
- {"version":3,"file":"display.js","sourceRoot":"","sources":["../../src/ui/display.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAG5B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACnC,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACnC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;AACtB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAE7C,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE;QACzC,IAAI,EAAE,UAAU;QAChB,gBAAgB,EAAE,SAAS;KAC5B,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC;IAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,sDAAsD,CAAC,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAoB;IAClD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAC;IAEzD,MAAM,IAAI,GAA2B;QACnC,GAAG,OAAO,CAAC,WAAW,CAAC,YAAY;QACnC,GAAG,OAAO,CAAC,WAAW,CAAC,eAAe;KACvC,CAAC;IAEF,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,IAAI,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,MAAM,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,IAAI,CAAC,uBAAuB,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnF,IAAI,IAAI,CAAC,aAAa,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChD,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,gBAAgB,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnE,IAAI,IAAI,CAAC,aAAa,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/C,IAAI,IAAI,CAAC,QAAQ,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC;QAC7E,UAAU,CAAC,IAAI,CAAC,kBAAkB,KAAK,EAAE,CAAC,CAAC;IAC7C,CAAC;IAED,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,UAAU,CAAC,IAAI,CAAC,kBAAkB,OAAO,CAAC,OAAO,CAAC,MAAM,wBAAwB,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;IACnI,CAAC;IAED,IAAI,OAAO,CAAC,cAAc,GAAG,CAAC,EAAE,CAAC;QAC/B,UAAU,CAAC,IAAI,CAAC,0BAA0B,OAAO,CAAC,cAAc,kBAAkB,OAAO,CAAC,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;IACrI,CAAC;IAED,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IAC5D,MAAM,WAAW,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACnF,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,UAAU,CAAC,IAAI,CAAC,oBAAoB,WAAW,CAAC,MAAM,iBAAiB,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC;IACzH,CAAC;IAED,IAAI,gBAAgB,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3C,UAAU,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,UAAU,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC;IAC5D,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACpB,UAAU,CAAC,IAAI,CAAC,GAAG,WAAW,eAAe,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;IACrF,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAkB;IAC7C,MAAM,QAAQ,GAAyB;QACrC,CAAC,cAAc,EAAE,QAAQ,CAAC,WAAW,CAAC;QACtC,CAAC,eAAe,EAAE,QAAQ,CAAC,YAAY,CAAC;QACxC,CAAC,wBAAwB,EAAE,QAAQ,CAAC,oBAAoB,CAAC;QACzD,CAAC,4BAA4B,EAAE,QAAQ,CAAC,yBAAyB,CAAC;QAClE,CAAC,qBAAqB,EAAE,QAAQ,CAAC,kBAAkB,CAAC;KACrD,CAAC;IAEF,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACnE,IAAI,CAAC,WAAW;QAAE,OAAO;IAEzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC,CAAC;IAE/D,KAAK,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,QAAQ,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACjC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC;QACjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAsB;IACjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,sBAAsB,KAAK,CAAC,MAAM,QAAQ,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IACjG,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;QAC5F,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC,CAAC;IACpF,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC,CAAC;IACvF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,2CAA2C,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;IACvF,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAwD,EAAE,OAAgB;IAClG,OAAO,CAAC,GAAG,EAAE,CAAC;IACd,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,SAAS;YACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;YAC/C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC,CAAC;YAC7D,MAAM;QACR,KAAK,YAAY;YACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,qDAAqD,CAAC,CAAC,CAAC;YAC1E,MAAM;QACR,KAAK,YAAY;YACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC,CAAC;YAC9D,IAAI,OAAO;gBAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC;YAChD,MAAM;QACR,KAAK,QAAQ;YACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,gEAAgE,CAAC,CAAC,CAAC;YACrF,IAAI,OAAO;gBAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC;YAChD,MAAM;IACV,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"display.js","sourceRoot":"","sources":["../../src/ui/display.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,6 @@
1
1
  export declare function confirm(question: string): Promise<boolean>;
2
2
  export declare function promptChoice(question: string): Promise<"y" | "a" | "n">;
3
3
  export declare function promptFilePath(question: string): Promise<string>;
4
+ export declare function promptFileSelection(question: string): Promise<"a" | "s" | "n">;
5
+ export declare function promptPreview(message: string): Promise<boolean>;
4
6
  //# sourceMappingURL=prompt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/ui/prompt.ts"],"names":[],"mappings":"AAgBA,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAIhE;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAM7E;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEtE"}
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/ui/prompt.ts"],"names":[],"mappings":"AAgBA,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAIhE;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAM7E;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAEtE;AAED,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,CAMpF;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgC/D"}
package/dist/ui/prompt.js CHANGED
@@ -28,4 +28,41 @@ export async function promptChoice(question) {
28
28
  export async function promptFilePath(question) {
29
29
  return ask(question);
30
30
  }
31
+ export async function promptFileSelection(question) {
32
+ const answer = await ask(question);
33
+ const normalized = answer.toLowerCase();
34
+ if (normalized === "a" || normalized === "accept")
35
+ return "a";
36
+ if (normalized === "s" || normalized === "select")
37
+ return "s";
38
+ return "n";
39
+ }
40
+ export function promptPreview(message) {
41
+ return new Promise((resolve) => {
42
+ process.stdout.write(message);
43
+ const wasRaw = process.stdin.isRaw;
44
+ process.stdin.setRawMode(true);
45
+ process.stdin.resume();
46
+ const onData = (key) => {
47
+ process.stdin.setRawMode(wasRaw ?? false);
48
+ process.stdin.pause();
49
+ process.stdin.removeListener("data", onData);
50
+ const ch = key.toString();
51
+ // ctrl-c
52
+ if (ch === "\x03") {
53
+ console.log();
54
+ process.exit(0);
55
+ }
56
+ if (ch.toLowerCase() === "o") {
57
+ console.log("o\n");
58
+ resolve(true);
59
+ }
60
+ else {
61
+ console.log("\n");
62
+ resolve(false);
63
+ }
64
+ };
65
+ process.stdin.on("data", onData);
66
+ });
67
+ }
31
68
  //# sourceMappingURL=prompt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/ui/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,SAAS,GAAG,CAAC,QAAgB;IAC3B,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;QAClC,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IAEH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;YAC/B,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,QAAgB;IAC5C,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACxC,OAAO,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,KAAK,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IACxC,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,KAAK;QAAE,OAAO,GAAG,CAAC;IAC3D,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,KAAK;QAAE,OAAO,GAAG,CAAC;IAC3D,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB;IACnD,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/ui/prompt.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "runshift",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "The control plane for agents, wherever they run.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,4 +1,5 @@
1
1
  import ora from "ora";
2
+ import { exec, execSync } from "node:child_process";
2
3
  import { collectRepoContext, addFileToContext } from "../context/collector.js";
3
4
  import { getGitState } from "../context/git.js";
4
5
  import {
@@ -7,24 +8,77 @@ import {
7
8
  showDirtyWarning,
8
9
  showBranchInfo,
9
10
  showScanResults,
11
+ showDataPolicy,
10
12
  showFindings,
11
13
  showFileList,
14
+ showSelectedFiles,
15
+ showProtectedFiles,
12
16
  showSummary,
13
17
  showSuccess,
18
+ showDryRunComplete,
19
+ showCancelled,
14
20
  showError,
15
21
  } from "../ui/display.js";
16
- import { confirm, promptChoice, promptFilePath } from "../ui/prompt.js";
22
+ import { confirm, promptChoice, promptFilePath, promptFileSelection, promptPreview } from "../ui/prompt.js";
17
23
  import { writeFiles, commitFiles } from "../writer.js";
18
24
  import type { InitResponse } from "../types.js";
19
25
 
20
- const API_URL =
21
- process.env.RUNSHIFT_DEV === "true"
22
- ? "http://localhost:3000/api/cli/init"
23
- : "https://runshift.ai/api/cli/init";
26
+ const IS_DEV = process.env.RUNSHIFT_DEV === "true";
24
27
 
25
- const TIMEOUT_MS = 240_000;
28
+ const API_URL = IS_DEV
29
+ ? "http://localhost:3000/api/cli/init"
30
+ : "https://runshift.ai/api/cli/init";
31
+
32
+ const BASE_URL = IS_DEV
33
+ ? "http://localhost:3000"
34
+ : "https://runshift.ai";
35
+
36
+ const TIMEOUT_MS = 180_000;
37
+
38
+ interface InitFlags {
39
+ dryRun: boolean;
40
+ branch: string | null;
41
+ help: boolean;
42
+ }
43
+
44
+ function parseFlags(args: string[]): InitFlags {
45
+ const flags: InitFlags = { dryRun: false, branch: null, help: false };
46
+
47
+ for (let i = 0; i < args.length; i++) {
48
+ const arg = args[i];
49
+ if (arg === "--dry-run") {
50
+ flags.dryRun = true;
51
+ } else if (arg === "--branch") {
52
+ const next = args[i + 1];
53
+ flags.branch = next && !next.startsWith("--") ? next : "relay-init";
54
+ if (next && !next.startsWith("--")) i++;
55
+ } else if (arg === "--help") {
56
+ flags.help = true;
57
+ }
58
+ }
59
+
60
+ return flags;
61
+ }
62
+
63
+ function showInitHelp(): void {
64
+ console.log(`
65
+ npx runshift init [options]
66
+
67
+ options:
68
+ --dry-run preview changes without writing files
69
+ --branch <name> run on a new branch (default: relay-init)
70
+ --help show this help
71
+ `);
72
+ }
73
+
74
+ export async function init(args: string[] = []): Promise<void> {
75
+ const flags = parseFlags(args);
76
+
77
+ if (flags.help) {
78
+ showInitHelp();
79
+ return;
80
+ }
26
81
 
27
- export async function init(): Promise<void> {
28
82
  showBanner();
29
83
 
30
84
  // ── 1. Git safety ─────────────────────────────────────────────────
@@ -41,16 +95,33 @@ export async function init(): Promise<void> {
41
95
  showDirtyWarning();
42
96
  const proceed = await confirm(" continue with uncommitted changes? (y/n) ");
43
97
  if (!proceed) {
98
+ showCancelled();
44
99
  process.exit(0);
45
100
  }
46
101
  }
47
102
 
103
+ // ── 1b. Branch flag — create and switch ───────────────────────────
104
+ if (flags.branch) {
105
+ try {
106
+ execSync(`git rev-parse --verify ${flags.branch}`, { stdio: "pipe" });
107
+ console.log(` branch ${flags.branch} already exists.\n`);
108
+ process.exit(1);
109
+ } catch {
110
+ // branch doesn't exist — good
111
+ }
112
+
113
+ execSync(`git checkout -b ${flags.branch}`, { stdio: "pipe" });
114
+ console.log(` switched to new branch ${flags.branch}\n`);
115
+ }
116
+
48
117
  // ── 2. Collect context ────────────────────────────────────────────
49
118
  const root = process.cwd();
50
119
  const context = collectRepoContext(root);
51
120
 
52
- // ── 3. Show scan results + prompt ─────────────────────────────────
121
+ // ── 3. Show scan results + protected files + data policy + prompt
53
122
  showScanResults(context);
123
+ showProtectedFiles(context.protectedPaths);
124
+ showDataPolicy();
54
125
 
55
126
  let choice = await promptChoice(" proceed? [y] add more files? [a] cancel? [n] ");
56
127
 
@@ -63,10 +134,12 @@ export async function init(): Promise<void> {
63
134
  }
64
135
  }
65
136
  showScanResults(context);
137
+ showDataPolicy();
66
138
  choice = await promptChoice(" proceed? [y] add more files? [a] cancel? [n] ");
67
139
  }
68
140
 
69
141
  if (choice === "n") {
142
+ showCancelled();
70
143
  process.exit(0);
71
144
  }
72
145
 
@@ -76,7 +149,16 @@ export async function init(): Promise<void> {
76
149
  color: "yellow",
77
150
  }).start();
78
151
 
79
- console.log("calling:", API_URL);
152
+ const spinnerMessages = [
153
+ { delay: 8000, text: "relay is analyzing your stack..." },
154
+ { delay: 20000, text: "generating governance rules..." },
155
+ { delay: 45000, text: "reviewing with second model..." },
156
+ { delay: 70000, text: "synthesizing final rules..." },
157
+ ];
158
+
159
+ const spinnerTimeouts = spinnerMessages.map(({ delay, text }) =>
160
+ setTimeout(() => { spinner.text = text; }, delay),
161
+ );
80
162
 
81
163
  let response: Response;
82
164
  try {
@@ -91,10 +173,12 @@ export async function init(): Promise<void> {
91
173
  });
92
174
 
93
175
  clearTimeout(timeout);
176
+ spinnerTimeouts.forEach((t) => clearTimeout(t));
94
177
  } catch (err) {
178
+ spinnerTimeouts.forEach((t) => clearTimeout(t));
95
179
  spinner.stop();
96
180
  if (err instanceof Error && err.name === "AbortError") {
97
- showError("network", "request timed out after 120s");
181
+ showError("network", "request timed out after 180s");
98
182
  } else {
99
183
  showError("network");
100
184
  }
@@ -133,31 +217,109 @@ export async function init(): Promise<void> {
133
217
  showFindings(data.findings);
134
218
  showFileList(data.files);
135
219
 
136
- // ── 6. Confirm write ──────────────────────────────────────────────
137
- const writeConfirm = await confirm(" write these files? (y/n) ");
138
- if (!writeConfirm) {
220
+ // ── 6. Preview link ───────────────────────────────────────────────
221
+ if (data.previewId) {
222
+ const previewUrl = `${BASE_URL}/preview/${data.previewId}`;
223
+ const open = await promptPreview(` preview ready — ${previewUrl}\n\n [o] open in browser [enter] continue `);
224
+ if (open) {
225
+ exec(`open ${previewUrl}`);
226
+ }
227
+ }
228
+
229
+ // ── 7. Dry run exit ───────────────────────────────────────────────
230
+ if (flags.dryRun) {
231
+ showDryRunComplete();
232
+ return;
233
+ }
234
+
235
+ // ── 8. File selection ────────────────────────────────────────────
236
+ const fileChoice = await promptFileSelection(" [a] accept all [s] select files [n] don't change anything ");
237
+
238
+ if (fileChoice === "n") {
239
+ showCancelled();
139
240
  process.exit(0);
140
241
  }
141
242
 
142
- // ── 7. Re-check git before writing ────────────────────────────────
243
+ let filesToWrite = data.files;
244
+
245
+ if (fileChoice === "a") {
246
+ const preserved = context.protectedPaths.length;
247
+ if (preserved > 0) {
248
+ console.log(`\n relay will write ${data.files.length} files.`);
249
+ console.log(` ${preserved} file${preserved === 1 ? " was" : "s were"} preserved (human-written).\n`);
250
+ } else {
251
+ console.log(`\n relay will write all ${data.files.length} files.\n`);
252
+ }
253
+ const acceptConfirm = await confirm(" confirm? (y/n) ");
254
+ if (!acceptConfirm) {
255
+ showCancelled();
256
+ process.exit(0);
257
+ }
258
+ } else if (fileChoice === "s") {
259
+ console.log("\n which files do you want? you can say things like:");
260
+ console.log(" 'all except CLAUDE.md'");
261
+ console.log(" 'only the cursor rules'");
262
+ console.log(" 'just core.mdc and worktrees'\n");
263
+
264
+ const instruction = await promptFilePath(" → ");
265
+
266
+ const selectUrl = `${BASE_URL}/api/cli/select`;
267
+ let selectedPaths: string[];
268
+
269
+ try {
270
+ const selectRes = await fetch(selectUrl, {
271
+ method: "POST",
272
+ headers: { "Content-Type": "application/json" },
273
+ body: JSON.stringify({
274
+ files: data.files.map((f) => f.path),
275
+ instruction,
276
+ }),
277
+ });
278
+
279
+ if (!selectRes.ok) {
280
+ showError("server", "file selection failed");
281
+ process.exit(1);
282
+ }
283
+
284
+ const selectData = (await selectRes.json()) as { selectedPaths: string[] };
285
+ selectedPaths = selectData.selectedPaths;
286
+ } catch {
287
+ showError("network");
288
+ process.exit(1);
289
+ }
290
+
291
+ filesToWrite = data.files.filter((f) => selectedPaths.includes(f.path));
292
+
293
+ showSelectedFiles(data.files, selectedPaths);
294
+ console.log(` relay will write ${filesToWrite.length} of ${data.files.length} files.\n`);
295
+
296
+ const selectConfirm = await confirm(" confirm? (y/n) ");
297
+ if (!selectConfirm) {
298
+ showCancelled();
299
+ process.exit(0);
300
+ }
301
+ }
302
+
303
+ // ── 9. Re-check git before writing ────────────────────────────────
143
304
  const gitNow = getGitState();
144
305
  if (gitNow.isDirty && !git.isDirty) {
145
306
  const proceed = await confirm(" working tree changed since scan — continue? (y/n) ");
146
307
  if (!proceed) {
308
+ showCancelled();
147
309
  process.exit(0);
148
310
  }
149
311
  }
150
312
 
151
- // ── 8. Write + commit ─────────────────────────────────────────────
313
+ // ── 10. Write + commit ────────────────────────────────────────────
152
314
  console.log();
153
- writeFiles(root, data.files);
315
+ writeFiles(root, filesToWrite);
154
316
  console.log();
155
317
 
156
- const committed = commitFiles(root, data.files);
318
+ const committed = commitFiles(root, filesToWrite);
157
319
  if (!committed) {
158
320
  console.log(" ⚠ files written but git commit failed\n");
159
321
  }
160
322
 
161
- // ── 9. Success ────────────────────────────────────────────────────
323
+ // ── 11. Success ───────────────────────────────────────────────────
162
324
  showSuccess();
163
325
  }
@@ -0,0 +1,59 @@
1
+ import { execSync } from "node:child_process";
2
+ import chalk from "chalk";
3
+ import { showBanner, showCancelled } from "../ui/display.js";
4
+ import { confirm } from "../ui/prompt.js";
5
+
6
+ const amber = chalk.hex("#f5a623");
7
+ const dim = chalk.dim;
8
+
9
+ const COMMIT_GREP = "install runshift agent governance rules";
10
+
11
+ export async function remove(): Promise<void> {
12
+ showBanner();
13
+
14
+ // ── Find the most recent runshift commit ──────────────────────────
15
+ let logLine: string;
16
+ try {
17
+ logLine = execSync(
18
+ `git log --oneline --grep="${COMMIT_GREP}" -1 --format="%H %s %ad" --date=short`,
19
+ { stdio: "pipe" },
20
+ )
21
+ .toString()
22
+ .trim();
23
+ } catch {
24
+ console.log(amber(" no runshift commit found in this repository.\n"));
25
+ return;
26
+ }
27
+
28
+ if (!logLine) {
29
+ console.log(amber(" no runshift commit found in this repository.\n"));
30
+ return;
31
+ }
32
+
33
+ const spaceIdx = logLine.indexOf(" ");
34
+ const hash = logLine.slice(0, spaceIdx);
35
+ const rest = logLine.slice(spaceIdx + 1);
36
+
37
+ // Split rest into message and date (date is last 10 chars: YYYY-MM-DD)
38
+ const date = rest.slice(-10);
39
+ const message = rest.slice(0, -11).trim();
40
+
41
+ console.log(amber(" relay will revert commit:\n"));
42
+ console.log(dim(` ${hash.slice(0, 7)}`));
43
+ console.log(dim(` ${message}`));
44
+ console.log(dim(` ${date}\n`));
45
+
46
+ const proceed = await confirm(" revert this commit? (y/n) ");
47
+ if (!proceed) {
48
+ showCancelled();
49
+ return;
50
+ }
51
+
52
+ try {
53
+ execSync(`git revert ${hash} --no-edit`, { stdio: "pipe" });
54
+ console.log(amber("\n ✓ reverted — runshift governance rules removed\n"));
55
+ } catch (err) {
56
+ console.log(amber("\n revert failed."));
57
+ console.log(dim(` ${err instanceof Error ? err.message : err}\n`));
58
+ }
59
+ }
@@ -1,5 +1,6 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
+ import { execSync } from "node:child_process";
3
4
  import type { RepoContext } from "../types.js";
4
5
  import { getGitState } from "./git.js";
5
6
 
@@ -96,6 +97,45 @@ function getRootConfigs(root: string): string[] {
96
97
  }
97
98
  }
98
99
 
100
+ function getProtectedPaths(root: string, existingRules: Record<string, string>): string[] {
101
+ const protectedPaths: string[] = [];
102
+
103
+ for (const filePath of Object.keys(existingRules)) {
104
+ // CLAUDE.md is always protected regardless of git history
105
+ if (filePath === "CLAUDE.md") {
106
+ protectedPaths.push(filePath);
107
+ continue;
108
+ }
109
+
110
+ try {
111
+ const lastCommitMsg = execSync(
112
+ `git log --follow -1 --pretty=format:"%s" -- "${filePath}"`,
113
+ { cwd: root, stdio: "pipe" },
114
+ ).toString().trim();
115
+
116
+ if (!lastCommitMsg) {
117
+ // Not in git → human created → protect
118
+ protectedPaths.push(filePath);
119
+ continue;
120
+ }
121
+
122
+ const isRelay =
123
+ lastCommitMsg.includes("install runshift agent governance rules") ||
124
+ lastCommitMsg.includes("runshift update");
125
+
126
+ if (!isRelay) {
127
+ // Last commit was by a human → protect
128
+ protectedPaths.push(filePath);
129
+ }
130
+ } catch {
131
+ // git log failed → protect to be safe
132
+ protectedPaths.push(filePath);
133
+ }
134
+ }
135
+
136
+ return protectedPaths;
137
+ }
138
+
99
139
  export function collectRepoContext(root: string): RepoContext {
100
140
  // ── package.json ──
101
141
  const pkgJson = readJsonSafe(path.join(root, "package.json"));
@@ -163,6 +203,9 @@ export function collectRepoContext(root: string): RepoContext {
163
203
  existingRules["CLAUDE.md"] = claudeMd;
164
204
  }
165
205
 
206
+ // ── Protected paths ──
207
+ const protectedPaths = getProtectedPaths(root, existingRules);
208
+
166
209
  // ── Migrations ──
167
210
  let migrationCount = 0;
168
211
  let migrationNames: string[] = [];
@@ -192,6 +235,7 @@ export function collectRepoContext(root: string): RepoContext {
192
235
  migrationCount,
193
236
  migrationNames,
194
237
  rootConfigs,
238
+ protectedPaths,
195
239
  gitState,
196
240
  };
197
241
  }