@freesyntax/notch-cli 0.5.21 → 0.5.23

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.
Files changed (38) hide show
  1. package/dist/{apply-patch-D5PDUXUC.js → apply-patch-U6K67CMT.js} +1 -0
  2. package/dist/auth-UAMMP5IJ.js +29 -0
  3. package/dist/{chunk-TU465P2P.js → chunk-474TAHDN.js} +50 -8
  4. package/dist/{chunk-OSWUX6TC.js → chunk-4HPRBCSY.js} +1 -1
  5. package/dist/{chunk-QKM27RHS.js → chunk-6NKRMZTX.js} +1 -1
  6. package/dist/{chunk-443G6HCC.js → chunk-JVFOAPYV.js} +331 -79
  7. package/dist/chunk-KCAR5DOB.js +52 -0
  8. package/dist/chunk-KFQGP6VL.js +33 -0
  9. package/dist/chunk-O6AKZ4OH.js +0 -0
  10. package/dist/{chunk-FIFC4V2R.js → chunk-PPEBWOMJ.js} +91 -7
  11. package/dist/chunk-UHK6SI4H.js +206 -0
  12. package/dist/{chunk-MMBFNIKE.js → chunk-YNYVQ7ZI.js} +10 -8
  13. package/dist/{compression-SQAIQ2UU.js → compression-YJLWEHCC.js} +1 -0
  14. package/dist/config-set-5F4VK7IT.js +111 -0
  15. package/dist/{edit-JEFEK43H.js → edit-6QYAXVNU.js} +1 -0
  16. package/dist/{git-5T5TSQTX.js → git-DNQ5EELH.js} +1 -0
  17. package/dist/{github-DWRGWX6U.js → github-34T4QQIH.js} +1 -0
  18. package/dist/{glob-BI3P4C7Q.js → glob-XT43LEJ4.js} +1 -0
  19. package/dist/{grep-VZ3I5GNW.js → grep-T2CXYNRI.js} +1 -0
  20. package/dist/index.js +878 -428
  21. package/dist/{lsp-UPY6I3L7.js → lsp-JXQVU7NP.js} +1 -0
  22. package/dist/model-download-KCQJCEPW.js +176 -0
  23. package/dist/{notebook-FXJBTSPA.js → notebook-MFODW345.js} +1 -0
  24. package/dist/{ollama-bench-QQHBIG2D.js → ollama-bench-JLC5POG3.js} +8 -4
  25. package/dist/{ollama-launch-2ASVER3S.js → ollama-launch-3IKB2A3Z.js} +6 -2
  26. package/dist/{ollama-usage-2WPCZJJI.js → ollama-usage-3PROM2WC.js} +1 -0
  27. package/dist/{plugins-OG2P75K5.js → plugins-PNGRZLFW.js} +1 -0
  28. package/dist/{read-OVJG2XKW.js → read-B64XE7N3.js} +1 -0
  29. package/dist/server-GMF4WV67.js +187 -0
  30. package/dist/{session-index-SSGOOZXK.js → session-index-7FWEVP6E.js} +3 -2
  31. package/dist/{shell-4X545EVN.js → shell-BOZTHQUT.js} +1 -0
  32. package/dist/{task-OS3E5F3X.js → task-67G4KLYC.js} +1 -0
  33. package/dist/{tools-7WAWS6V4.js → tools-ABRZPCEJ.js} +6 -3
  34. package/dist/{web-fetch-KNIV3Z3W.js → web-fetch-OTNDICGJ.js} +1 -0
  35. package/dist/{write-NNHLOTYK.js → write-ZOSB7I4J.js} +1 -0
  36. package/package.json +60 -57
  37. package/dist/auth-JQX6MHJG.js +0 -16
  38. package/dist/server-7UQKCB2Z.js +0 -1477
@@ -1,12 +1,29 @@
1
+ import {
2
+ __esm,
3
+ __export,
4
+ __require
5
+ } from "./chunk-KFQGP6VL.js";
6
+
1
7
  // src/auth.ts
8
+ var auth_exports = {};
9
+ __export(auth_exports, {
10
+ clearCredentials: () => clearCredentials,
11
+ getByokSyncPath: () => getByokSyncPath,
12
+ getConfigDir: () => getConfigDir,
13
+ getCredentialsPath: () => getCredentialsPath,
14
+ invalidateSyncedKeysCache: () => invalidateSyncedKeysCache,
15
+ loadCredentials: () => loadCredentials,
16
+ loadSyncedByokKeys: () => loadSyncedByokKeys,
17
+ loadSyncedByokKeysSync: () => loadSyncedByokKeysSync,
18
+ login: () => login,
19
+ saveCredentials: () => saveCredentials,
20
+ syncByokKeys: () => syncByokKeys
21
+ });
2
22
  import http from "http";
3
23
  import { exec } from "child_process";
4
24
  import os from "os";
5
25
  import path from "path";
6
26
  import fs from "fs/promises";
7
- var FREESYNTAX_URL = "https://freesyntax.dev";
8
- var PREFERRED_PORT = 9721;
9
- var AUTH_TIMEOUT_MS = 5 * 60 * 1e3;
10
27
  function getConfigDir() {
11
28
  if (process.platform === "win32") {
12
29
  return path.join(process.env["APPDATA"] ?? os.homedir(), "notch");
@@ -45,6 +62,58 @@ async function clearCredentials() {
45
62
  } catch {
46
63
  }
47
64
  }
65
+ function getByokSyncPath() {
66
+ return path.join(getConfigDir(), "byok-sync.json");
67
+ }
68
+ async function syncByokKeys(token, baseUrl = FREESYNTAX_URL) {
69
+ const url = `${baseUrl.replace(/\/$/, "")}/api/cli/keys`;
70
+ const res = await fetch(url, {
71
+ method: "GET",
72
+ headers: { Authorization: `Bearer ${token}` }
73
+ });
74
+ if (!res.ok) {
75
+ const body = await res.text().catch(() => "");
76
+ throw new Error(`Key sync failed (${res.status}): ${body.slice(0, 200) || res.statusText}`);
77
+ }
78
+ const data = await res.json();
79
+ const dir = getConfigDir();
80
+ await fs.mkdir(dir, { recursive: true });
81
+ await fs.writeFile(
82
+ getByokSyncPath(),
83
+ JSON.stringify({ ...data, syncedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2),
84
+ { encoding: "utf-8", mode: 384 }
85
+ );
86
+ return data;
87
+ }
88
+ async function loadSyncedByokKeys() {
89
+ try {
90
+ const raw = await fs.readFile(getByokSyncPath(), "utf-8");
91
+ const parsed = JSON.parse(raw);
92
+ if (parsed && typeof parsed === "object" && parsed.keys) return parsed;
93
+ return null;
94
+ } catch {
95
+ return null;
96
+ }
97
+ }
98
+ function loadSyncedByokKeysSync() {
99
+ if (syncedKeysCache !== void 0) return syncedKeysCache;
100
+ try {
101
+ const fsSync = __require("fs");
102
+ const raw = fsSync.readFileSync(getByokSyncPath(), "utf-8");
103
+ const parsed = JSON.parse(raw);
104
+ if (parsed && typeof parsed === "object" && parsed.keys) {
105
+ syncedKeysCache = parsed;
106
+ } else {
107
+ syncedKeysCache = null;
108
+ }
109
+ } catch {
110
+ syncedKeysCache = null;
111
+ }
112
+ return syncedKeysCache;
113
+ }
114
+ function invalidateSyncedKeysCache() {
115
+ syncedKeysCache = void 0;
116
+ }
48
117
  function openBrowser(url) {
49
118
  let cmd;
50
119
  if (process.platform === "win32") {
@@ -130,7 +199,13 @@ async function login() {
130
199
  }, AUTH_TIMEOUT_MS);
131
200
  });
132
201
  }
133
- var HTML_BASE = (body) => `<!DOCTYPE html>
202
+ var FREESYNTAX_URL, PREFERRED_PORT, AUTH_TIMEOUT_MS, syncedKeysCache, HTML_BASE, HTML_SUCCESS, HTML_ERROR;
203
+ var init_auth = __esm({
204
+ "src/auth.ts"() {
205
+ FREESYNTAX_URL = "https://freesyntax.dev";
206
+ PREFERRED_PORT = 9721;
207
+ AUTH_TIMEOUT_MS = 5 * 60 * 1e3;
208
+ HTML_BASE = (body) => `<!DOCTYPE html>
134
209
  <html lang="en">
135
210
  <head>
136
211
  <meta charset="utf-8">
@@ -157,16 +232,18 @@ var HTML_BASE = (body) => `<!DOCTYPE html>
157
232
  </head>
158
233
  <body><div class="card">${body}</div></body>
159
234
  </html>`;
160
- var HTML_SUCCESS = HTML_BASE(`
235
+ HTML_SUCCESS = HTML_BASE(`
161
236
  <div class="brand">notch_</div>
162
237
  <h1>CLI authorized</h1>
163
238
  <p>You can close this tab and return to your terminal.</p>
164
239
  `);
165
- var HTML_ERROR = HTML_BASE(`
240
+ HTML_ERROR = HTML_BASE(`
166
241
  <div class="brand">notch_</div>
167
242
  <h1>Authorization failed</h1>
168
243
  <p style="color:#CE2127">Run <code>notch login</code> again to retry.</p>
169
244
  `);
245
+ }
246
+ });
170
247
 
171
248
  export {
172
249
  getConfigDir,
@@ -174,5 +251,12 @@ export {
174
251
  loadCredentials,
175
252
  saveCredentials,
176
253
  clearCredentials,
177
- login
254
+ getByokSyncPath,
255
+ syncByokKeys,
256
+ loadSyncedByokKeys,
257
+ loadSyncedByokKeysSync,
258
+ invalidateSyncedKeysCache,
259
+ login,
260
+ auth_exports,
261
+ init_auth
178
262
  };
@@ -0,0 +1,206 @@
1
+ import {
2
+ readOllamaCreds
3
+ } from "./chunk-KCAR5DOB.js";
4
+ import {
5
+ findByokProvider,
6
+ isByokRef,
7
+ isValidModel,
8
+ listByokProviders,
9
+ parseByokRef
10
+ } from "./chunk-JVFOAPYV.js";
11
+ import {
12
+ OLLAMA_LOCAL_BASE_URL,
13
+ listModels
14
+ } from "./chunk-GFVLHUSS.js";
15
+ import {
16
+ init_auth,
17
+ loadCredentials,
18
+ loadSyncedByokKeys
19
+ } from "./chunk-PPEBWOMJ.js";
20
+
21
+ // src/config.ts
22
+ import fs from "fs/promises";
23
+ import path from "path";
24
+ init_auth();
25
+ var DEFAULT_MODEL = {
26
+ model: "openrouter/anthropic/claude-sonnet-4-6",
27
+ temperature: 0.3
28
+ };
29
+ var DEFAULTS = {
30
+ models: { chat: DEFAULT_MODEL },
31
+ projectRoot: process.cwd(),
32
+ autoConfirm: false,
33
+ maxIterations: 25,
34
+ useRepoMap: true,
35
+ renderMarkdown: true,
36
+ enableMemory: true,
37
+ enableHooks: true,
38
+ permissionMode: "auto",
39
+ theme: "default"
40
+ };
41
+ async function loadConfig(overrides = {}) {
42
+ const config = { ...DEFAULTS, models: { chat: { ...DEFAULT_MODEL } } };
43
+ let explicitModelConfig = false;
44
+ const configPath = path.resolve(config.projectRoot, ".notch.json");
45
+ try {
46
+ const raw = await fs.readFile(configPath, "utf-8");
47
+ const fileConfig = JSON.parse(raw);
48
+ if (fileConfig.model && (isValidModel(fileConfig.model) || isByokRef(fileConfig.model))) {
49
+ config.models.chat.model = fileConfig.model;
50
+ explicitModelConfig = true;
51
+ }
52
+ if (fileConfig.baseUrl) config.models.chat.baseUrl = fileConfig.baseUrl;
53
+ if (fileConfig.apiKey) config.models.chat.apiKey = fileConfig.apiKey;
54
+ const providerBlock = fileConfig.provider && typeof fileConfig.provider === "object" ? fileConfig.provider : fileConfig.byok;
55
+ if (providerBlock && typeof providerBlock === "object") {
56
+ const byok = providerBlock;
57
+ config.byok = { ...byok };
58
+ if (byok.provider && findByokProvider(byok.provider === "custom" ? "__custom__" : byok.provider)) {
59
+ config.models.chat.byokProvider = byok.provider === "custom" ? "__custom__" : byok.provider;
60
+ if (byok.model) config.models.chat.model = byok.model;
61
+ if (byok.baseUrl) config.models.chat.baseUrl = byok.baseUrl;
62
+ if (byok.headers) {
63
+ config.models.chat.byokHeaders = { ...config.models.chat.byokHeaders, ...byok.headers };
64
+ }
65
+ if (byok.apiShape === "openai" || byok.apiShape === "anthropic") {
66
+ config.models.chat.byokApiShape = byok.apiShape;
67
+ }
68
+ explicitModelConfig = true;
69
+ }
70
+ }
71
+ if (fileConfig.hybrid && typeof fileConfig.hybrid === "object") {
72
+ const hybrid = fileConfig.hybrid;
73
+ config.hybrid = hybrid;
74
+ }
75
+ if (fileConfig.maxIterations) config.maxIterations = fileConfig.maxIterations;
76
+ if (fileConfig.useRepoMap !== void 0) config.useRepoMap = fileConfig.useRepoMap;
77
+ if (fileConfig.temperature !== void 0) config.models.chat.temperature = fileConfig.temperature;
78
+ if (fileConfig.renderMarkdown !== void 0) config.renderMarkdown = fileConfig.renderMarkdown;
79
+ if (fileConfig.enableMemory !== void 0) config.enableMemory = fileConfig.enableMemory;
80
+ if (fileConfig.enableHooks !== void 0) config.enableHooks = fileConfig.enableHooks;
81
+ if (fileConfig.permissionMode) config.permissionMode = fileConfig.permissionMode;
82
+ if (fileConfig.shellTimeout) config.shellTimeout = fileConfig.shellTimeout;
83
+ if (fileConfig.theme) config.theme = fileConfig.theme;
84
+ } catch {
85
+ }
86
+ if (process.env.NOTCH_PROVIDER) {
87
+ const providerId = process.env.NOTCH_PROVIDER === "custom" ? "__custom__" : process.env.NOTCH_PROVIDER;
88
+ const provider = findByokProvider(providerId);
89
+ if (provider) {
90
+ config.models.chat.byokProvider = providerId;
91
+ config.models.chat.model = process.env.NOTCH_MODEL || provider.defaultModel;
92
+ explicitModelConfig = true;
93
+ }
94
+ } else if (process.env.NOTCH_MODEL) {
95
+ const envModel = process.env.NOTCH_MODEL;
96
+ if (isValidModel(envModel)) {
97
+ config.models.chat.model = envModel;
98
+ config.models.chat.byokProvider = void 0;
99
+ explicitModelConfig = true;
100
+ } else if (isByokRef(envModel)) {
101
+ config.models.chat.model = envModel;
102
+ config.models.chat.byokProvider = void 0;
103
+ explicitModelConfig = true;
104
+ }
105
+ }
106
+ if (!explicitModelConfig) {
107
+ const inferred = await inferDefaultProviderConfig();
108
+ config.models.chat.model = inferred.modelRef;
109
+ config.models.chat.byokProvider = void 0;
110
+ if (inferred.baseUrl) config.models.chat.baseUrl = inferred.baseUrl;
111
+ if (inferred.apiShape) config.models.chat.byokApiShape = inferred.apiShape;
112
+ }
113
+ const activeProviderId = config.models.chat.byokProvider ?? (typeof config.models.chat.model === "string" && isByokRef(config.models.chat.model) ? parseByokRef(config.models.chat.model).provider : void 0);
114
+ const isOllamaProvider = activeProviderId === "ollama" || activeProviderId === "ollama-cloud" || activeProviderId === "ollama-anthropic";
115
+ if (isOllamaProvider) {
116
+ if (!config.models.chat.apiKey && !process.env.OLLAMA_API_KEY) {
117
+ const ollamaCreds = await readOllamaCreds();
118
+ if (ollamaCreds?.apiKey) {
119
+ config.models.chat.apiKey = ollamaCreds.apiKey;
120
+ }
121
+ }
122
+ } else if (!activeProviderId) {
123
+ const creds = await loadCredentials();
124
+ if (creds?.token) {
125
+ config.models.chat.apiKey = creds.token;
126
+ }
127
+ }
128
+ if (process.env.NOTCH_BASE_URL) {
129
+ config.models.chat.baseUrl = process.env.NOTCH_BASE_URL;
130
+ }
131
+ if (process.env.NOTCH_API_KEY && !activeProviderId) {
132
+ config.models.chat.apiKey = process.env.NOTCH_API_KEY;
133
+ }
134
+ if (config.models.chat.temperature !== void 0) {
135
+ config.models.chat.temperature = Math.max(0, Math.min(2, config.models.chat.temperature));
136
+ }
137
+ config.maxIterations = Math.max(1, Math.min(100, config.maxIterations));
138
+ return { ...config, ...overrides };
139
+ }
140
+ async function inferDefaultProviderConfig() {
141
+ const providers = listByokProviders();
142
+ const envMatch = providers.find((p) => p.apiKeyEnv && process.env[p.apiKeyEnv]);
143
+ if (envMatch) return { modelRef: `${envMatch.id}/${envMatch.defaultModel}` };
144
+ const synced = await loadSyncedByokKeys();
145
+ if (synced) {
146
+ const syncedMatch = providers.find((p) => {
147
+ const key = synced.keys[p.id];
148
+ return typeof key === "string" && key.length > 0;
149
+ });
150
+ if (syncedMatch) return { modelRef: `${syncedMatch.id}/${syncedMatch.defaultModel}` };
151
+ if (synced.localEndpoint) {
152
+ return {
153
+ modelRef: "custom/local-model",
154
+ baseUrl: synced.localEndpoint,
155
+ apiShape: "openai"
156
+ };
157
+ }
158
+ }
159
+ const localOllama = await inferLocalOllamaModel();
160
+ if (localOllama) return localOllama;
161
+ const openrouter = findByokProvider("openrouter");
162
+ if (openrouter) return { modelRef: `${openrouter.id}/${openrouter.defaultModel}` };
163
+ const first = providers[0];
164
+ return { modelRef: first ? `${first.id}/${first.defaultModel}` : DEFAULT_MODEL.model };
165
+ }
166
+ async function inferLocalOllamaModel() {
167
+ try {
168
+ const baseUrl = process.env.OLLAMA_HOST?.startsWith("http") ? process.env.OLLAMA_HOST : OLLAMA_LOCAL_BASE_URL;
169
+ const rows = await listModels(baseUrl, { timeoutMs: 300 });
170
+ const modelName = rows[0]?.name;
171
+ if (!modelName) return null;
172
+ return {
173
+ modelRef: `ollama/${modelName}`,
174
+ baseUrl: `${baseUrl.replace(/\/+$/, "")}/v1`
175
+ };
176
+ } catch {
177
+ return null;
178
+ }
179
+ }
180
+ async function persistConfigPatch(projectRoot, patch) {
181
+ const configPath = path.resolve(projectRoot, ".notch.json");
182
+ let current = {};
183
+ try {
184
+ const raw = await fs.readFile(configPath, "utf-8");
185
+ const parsed = JSON.parse(raw);
186
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
187
+ current = parsed;
188
+ }
189
+ } catch {
190
+ }
191
+ const merged = { ...current };
192
+ for (const [k, v] of Object.entries(patch)) {
193
+ if (v === void 0) delete merged[k];
194
+ else merged[k] = v;
195
+ }
196
+ const serialised = JSON.stringify(merged, null, 2) + "\n";
197
+ const tmpPath = `${configPath}.tmp`;
198
+ await fs.writeFile(tmpPath, serialised, "utf-8");
199
+ await fs.rename(tmpPath, configPath);
200
+ return merged;
201
+ }
202
+
203
+ export {
204
+ loadConfig,
205
+ persistConfigPatch
206
+ };
@@ -1,3 +1,12 @@
1
+ import {
2
+ clearOllamaCreds,
3
+ ollamaCredsPath,
4
+ readOllamaCreds,
5
+ writeOllamaCreds
6
+ } from "./chunk-KCAR5DOB.js";
7
+ import {
8
+ findByokProvider
9
+ } from "./chunk-JVFOAPYV.js";
1
10
  import {
2
11
  OLLAMA_CLOUD_BASE_URL,
3
12
  OLLAMA_LOCAL_BASE_URL,
@@ -9,13 +18,6 @@ import {
9
18
  pullModel,
10
19
  showModel
11
20
  } from "./chunk-GFVLHUSS.js";
12
- import {
13
- clearOllamaCreds,
14
- findByokProvider,
15
- ollamaCredsPath,
16
- readOllamaCreds,
17
- writeOllamaCreds
18
- } from "./chunk-443G6HCC.js";
19
21
 
20
22
  // src/commands/ollama-launch.ts
21
23
  import fs from "fs/promises";
@@ -486,7 +488,7 @@ async function runOllamaCli(argv, cwd) {
486
488
  case "logout":
487
489
  return cmdLogout(subFlags);
488
490
  case "bench": {
489
- const { runOllamaBench } = await import("./ollama-bench-QQHBIG2D.js");
491
+ const { runOllamaBench } = await import("./ollama-bench-JLC5POG3.js");
490
492
  return runOllamaBench(subFlags, { projectRoot: cwd });
491
493
  }
492
494
  case "help":
@@ -14,6 +14,7 @@ import {
14
14
  setArtifactStore,
15
15
  snip
16
16
  } from "./chunk-PKZKVOAN.js";
17
+ import "./chunk-KFQGP6VL.js";
17
18
  export {
18
19
  autoCompactSummarize,
19
20
  autoCompress,
@@ -0,0 +1,111 @@
1
+ import {
2
+ persistConfigPatch
3
+ } from "./chunk-UHK6SI4H.js";
4
+ import "./chunk-KCAR5DOB.js";
5
+ import "./chunk-JVFOAPYV.js";
6
+ import "./chunk-GFVLHUSS.js";
7
+ import "./chunk-PPEBWOMJ.js";
8
+ import "./chunk-KFQGP6VL.js";
9
+
10
+ // src/commands/config-set.ts
11
+ import fs from "fs/promises";
12
+ import path from "path";
13
+ var HELP = `notch config \u2014 manage .notch.json settings
14
+
15
+ Usage:
16
+ notch config get [key]
17
+ notch config set <key> <value>
18
+ notch config unset <key>
19
+ notch config yolo [on|off] # auto-allow every tool call (sticks)
20
+
21
+ Examples:
22
+ notch config set permissionMode trust
23
+ notch config set autoConfirm true
24
+ notch config set model pyre
25
+ notch config yolo on
26
+ notch config yolo off
27
+ `;
28
+ function parseValue(raw) {
29
+ try {
30
+ return JSON.parse(raw);
31
+ } catch {
32
+ return raw;
33
+ }
34
+ }
35
+ async function readCurrent(projectRoot) {
36
+ const p = path.resolve(projectRoot, ".notch.json");
37
+ try {
38
+ const raw = await fs.readFile(p, "utf-8");
39
+ const parsed = JSON.parse(raw);
40
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
41
+ return parsed;
42
+ }
43
+ } catch {
44
+ }
45
+ return {};
46
+ }
47
+ async function runConfigCli(argv, projectRoot) {
48
+ const sub = argv[0];
49
+ if (!sub || sub === "-h" || sub === "--help" || sub === "help") {
50
+ process.stdout.write(HELP);
51
+ return 0;
52
+ }
53
+ if (sub === "get") {
54
+ const key = argv[1];
55
+ const cur = await readCurrent(projectRoot);
56
+ if (!key) {
57
+ process.stdout.write(JSON.stringify(cur, null, 2) + "\n");
58
+ return 0;
59
+ }
60
+ if (key in cur) {
61
+ process.stdout.write(JSON.stringify(cur[key]) + "\n");
62
+ return 0;
63
+ }
64
+ process.stderr.write(`notch: no such key: ${key}
65
+ `);
66
+ return 1;
67
+ }
68
+ if (sub === "set") {
69
+ const key = argv[1];
70
+ const value = argv.slice(2).join(" ");
71
+ if (!key || value.length === 0) {
72
+ process.stderr.write("usage: notch config set <key> <value>\n");
73
+ return 2;
74
+ }
75
+ const parsed = parseValue(value);
76
+ const merged = await persistConfigPatch(projectRoot, { [key]: parsed });
77
+ process.stdout.write(`${key} = ${JSON.stringify(merged[key])}
78
+ `);
79
+ return 0;
80
+ }
81
+ if (sub === "unset") {
82
+ const key = argv[1];
83
+ if (!key) {
84
+ process.stderr.write("usage: notch config unset <key>\n");
85
+ return 2;
86
+ }
87
+ await persistConfigPatch(projectRoot, { [key]: void 0 });
88
+ process.stdout.write(`removed ${key}
89
+ `);
90
+ return 0;
91
+ }
92
+ if (sub === "yolo") {
93
+ const arg = (argv[1] ?? "").toLowerCase();
94
+ const cur = await readCurrent(projectRoot);
95
+ const currentlyOn = cur.permissionMode === "trust";
96
+ const turnOn = arg === "" ? !currentlyOn : arg === "on" || arg === "true" || arg === "1" || arg === "yes";
97
+ await persistConfigPatch(projectRoot, {
98
+ permissionMode: turnOn ? "trust" : "auto",
99
+ autoConfirm: turnOn ? true : void 0
100
+ });
101
+ process.stdout.write(turnOn ? "YOLO mode ON \u2014 every tool call auto-allowed. Saved to .notch.json.\n" : "YOLO mode OFF \u2014 prompts restored. Saved to .notch.json.\n");
102
+ return 0;
103
+ }
104
+ process.stderr.write(`notch: unknown config subcommand: ${sub}
105
+ `);
106
+ process.stderr.write(HELP);
107
+ return 2;
108
+ }
109
+ export {
110
+ runConfigCli
111
+ };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  editTool
3
3
  } from "./chunk-YAYPQTOU.js";
4
+ import "./chunk-KFQGP6VL.js";
4
5
  export {
5
6
  editTool
6
7
  };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  gitTool
3
3
  } from "./chunk-FAULT7VE.js";
4
+ import "./chunk-KFQGP6VL.js";
4
5
  export {
5
6
  gitTool
6
7
  };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  githubTool
3
3
  } from "./chunk-GBZGR6ID.js";
4
+ import "./chunk-KFQGP6VL.js";
4
5
  export {
5
6
  githubTool
6
7
  };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  globTool
3
3
  } from "./chunk-6U3ZAGYA.js";
4
+ import "./chunk-KFQGP6VL.js";
4
5
  export {
5
6
  globTool
6
7
  };
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  grepTool
3
3
  } from "./chunk-6CZCFY6H.js";
4
+ import "./chunk-KFQGP6VL.js";
4
5
  export {
5
6
  grepTool
6
7
  };