@sna-sdk/core 0.7.2 → 0.8.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.
@@ -401,6 +401,9 @@ class ClaudeCodeProvider {
401
401
  args.push(...extraArgsClean);
402
402
  }
403
403
  const cleanEnv = { ...process.env, ...options.env };
404
+ if (options.configDir) {
405
+ cleanEnv.CLAUDE_CONFIG_DIR = options.configDir;
406
+ }
404
407
  delete cleanEnv.CLAUDECODE;
405
408
  delete cleanEnv.CLAUDE_CODE_ENTRYPOINT;
406
409
  delete cleanEnv.CLAUDE_CODE_SESSION_ACCESS_TOKEN;
@@ -61,6 +61,12 @@ interface SpawnOptions {
61
61
  model?: string;
62
62
  permissionMode?: "default" | "acceptEdits" | "bypassPermissions" | "plan";
63
63
  env?: Record<string, string>;
64
+ /**
65
+ * Override CLAUDE_CONFIG_DIR for this session.
66
+ * Isolates Claude config (permissions, theme, API keys, etc.) per session.
67
+ * If omitted, inherits the process-level CLAUDE_CONFIG_DIR or default (~/).
68
+ */
69
+ configDir?: string;
64
70
  /**
65
71
  * Conversation history to inject before the first prompt.
66
72
  * Written to stdin as NDJSON — Claude Code treats these as prior conversation turns.
@@ -1008,7 +1008,9 @@ Run "sna help submit" for data submission patterns.`);
1008
1008
  cmdApiUp();
1009
1009
  break;
1010
1010
  case "tu":
1011
- cmdTu(args);
1011
+ console.log(' "sna tu" has moved to @sna-sdk/testing.');
1012
+ console.log(' Install it and use "sna-test" instead.');
1013
+ console.log(' e.g. sna-test api:up, sna-test claude "hello"');
1012
1014
  break;
1013
1015
  case "restart":
1014
1016
  cmdDown();
@@ -49,7 +49,7 @@ interface ApiResponses {
49
49
  };
50
50
  "agent.set-permission-mode": {
51
51
  status: "updated" | "no_session";
52
- permissionMode: string;
52
+ permissionMode?: string;
53
53
  };
54
54
  "agent.kill": {
55
55
  status: "killed" | "no_session";
@@ -69,7 +69,7 @@ interface ApiResponses {
69
69
  config: {
70
70
  provider: string;
71
71
  model: string;
72
- permissionMode: string;
72
+ permissionMode?: string;
73
73
  extraArgs?: string[];
74
74
  } | null;
75
75
  };
@@ -142,7 +142,8 @@ function createAgentRoutes(sessionManager) {
142
142
  }
143
143
  const providerName = body.provider ?? "claude-code";
144
144
  const model = body.model ?? "claude-sonnet-4-6";
145
- const permissionMode = body.permissionMode ?? "acceptEdits";
145
+ const permissionMode = body.permissionMode;
146
+ const configDir = body.configDir;
146
147
  const extraArgs = body.extraArgs;
147
148
  try {
148
149
  const proc = provider.spawn({
@@ -150,12 +151,13 @@ function createAgentRoutes(sessionManager) {
150
151
  prompt: body.prompt,
151
152
  model,
152
153
  permissionMode,
154
+ configDir,
153
155
  env: { SNA_SESSION_ID: sessionId },
154
156
  history: body.history,
155
157
  extraArgs
156
158
  });
157
159
  sessionManager.setProcess(sessionId, proc);
158
- sessionManager.saveStartConfig(sessionId, { provider: providerName, model, permissionMode, extraArgs });
160
+ sessionManager.saveStartConfig(sessionId, { provider: providerName, model, permissionMode, configDir, extraArgs });
159
161
  logger.log("route", `POST /start?session=${sessionId} \u2192 started`);
160
162
  return httpJson(c, "agent.start", {
161
163
  status: "started",
@@ -294,6 +296,7 @@ function createAgentRoutes(sessionManager) {
294
296
  cwd: sessionManager.getSession(sessionId).cwd,
295
297
  model: cfg.model,
296
298
  permissionMode: cfg.permissionMode,
299
+ configDir: cfg.configDir,
297
300
  env: { SNA_SESSION_ID: sessionId },
298
301
  extraArgs: [...cfg.extraArgs ?? [], ...resumeArgs]
299
302
  });
@@ -322,7 +325,8 @@ function createAgentRoutes(sessionManager) {
322
325
  }
323
326
  const providerName = body.provider ?? "claude-code";
324
327
  const model = body.model ?? session.lastStartConfig?.model ?? "claude-sonnet-4-6";
325
- const permissionMode = body.permissionMode ?? session.lastStartConfig?.permissionMode ?? "acceptEdits";
328
+ const permissionMode = body.permissionMode ?? session.lastStartConfig?.permissionMode;
329
+ const configDir = body.configDir ?? session.lastStartConfig?.configDir;
326
330
  const extraArgs = body.extraArgs ?? session.lastStartConfig?.extraArgs;
327
331
  const provider = getProvider(providerName);
328
332
  try {
@@ -331,12 +335,13 @@ function createAgentRoutes(sessionManager) {
331
335
  prompt: body.prompt,
332
336
  model,
333
337
  permissionMode,
338
+ configDir,
334
339
  env: { SNA_SESSION_ID: sessionId },
335
340
  history: history.length > 0 ? history : void 0,
336
341
  extraArgs
337
342
  });
338
343
  sessionManager.setProcess(sessionId, proc, "resumed");
339
- sessionManager.saveStartConfig(sessionId, { provider: providerName, model, permissionMode, extraArgs });
344
+ sessionManager.saveStartConfig(sessionId, { provider: providerName, model, permissionMode, configDir, extraArgs });
340
345
  logger.log("route", `POST /resume?session=${sessionId} \u2192 resumed (${history.length} history msgs)`);
341
346
  return httpJson(c, "agent.resume", {
342
347
  status: "resumed",
@@ -11,7 +11,8 @@ type SessionState = "idle" | "processing" | "waiting" | "permission";
11
11
  interface StartConfig {
12
12
  provider: string;
13
13
  model: string;
14
- permissionMode: string;
14
+ permissionMode?: string;
15
+ configDir?: string;
15
16
  extraArgs?: string[];
16
17
  }
17
18
  interface Session {
@@ -776,6 +776,9 @@ var ClaudeCodeProvider = class {
776
776
  args.push(...extraArgsClean);
777
777
  }
778
778
  const cleanEnv = { ...process.env, ...options.env };
779
+ if (options.configDir) {
780
+ cleanEnv.CLAUDE_CONFIG_DIR = options.configDir;
781
+ }
779
782
  delete cleanEnv.CLAUDECODE;
780
783
  delete cleanEnv.CLAUDE_CODE_ENTRYPOINT;
781
784
  delete cleanEnv.CLAUDE_CODE_SESSION_ACCESS_TOKEN;
@@ -1004,7 +1007,8 @@ function createAgentRoutes(sessionManager2) {
1004
1007
  }
1005
1008
  const providerName = body.provider ?? "claude-code";
1006
1009
  const model = body.model ?? "claude-sonnet-4-6";
1007
- const permissionMode2 = body.permissionMode ?? "acceptEdits";
1010
+ const permissionMode2 = body.permissionMode;
1011
+ const configDir = body.configDir;
1008
1012
  const extraArgs = body.extraArgs;
1009
1013
  try {
1010
1014
  const proc = provider2.spawn({
@@ -1012,12 +1016,13 @@ function createAgentRoutes(sessionManager2) {
1012
1016
  prompt: body.prompt,
1013
1017
  model,
1014
1018
  permissionMode: permissionMode2,
1019
+ configDir,
1015
1020
  env: { SNA_SESSION_ID: sessionId },
1016
1021
  history: body.history,
1017
1022
  extraArgs
1018
1023
  });
1019
1024
  sessionManager2.setProcess(sessionId, proc);
1020
- sessionManager2.saveStartConfig(sessionId, { provider: providerName, model, permissionMode: permissionMode2, extraArgs });
1025
+ sessionManager2.saveStartConfig(sessionId, { provider: providerName, model, permissionMode: permissionMode2, configDir, extraArgs });
1021
1026
  logger.log("route", `POST /start?session=${sessionId} \u2192 started`);
1022
1027
  return httpJson(c, "agent.start", {
1023
1028
  status: "started",
@@ -1156,6 +1161,7 @@ function createAgentRoutes(sessionManager2) {
1156
1161
  cwd: sessionManager2.getSession(sessionId).cwd,
1157
1162
  model: cfg.model,
1158
1163
  permissionMode: cfg.permissionMode,
1164
+ configDir: cfg.configDir,
1159
1165
  env: { SNA_SESSION_ID: sessionId },
1160
1166
  extraArgs: [...cfg.extraArgs ?? [], ...resumeArgs]
1161
1167
  });
@@ -1184,7 +1190,8 @@ function createAgentRoutes(sessionManager2) {
1184
1190
  }
1185
1191
  const providerName = body.provider ?? "claude-code";
1186
1192
  const model = body.model ?? session.lastStartConfig?.model ?? "claude-sonnet-4-6";
1187
- const permissionMode2 = body.permissionMode ?? session.lastStartConfig?.permissionMode ?? "acceptEdits";
1193
+ const permissionMode2 = body.permissionMode ?? session.lastStartConfig?.permissionMode;
1194
+ const configDir = body.configDir ?? session.lastStartConfig?.configDir;
1188
1195
  const extraArgs = body.extraArgs ?? session.lastStartConfig?.extraArgs;
1189
1196
  const provider2 = getProvider(providerName);
1190
1197
  try {
@@ -1193,12 +1200,13 @@ function createAgentRoutes(sessionManager2) {
1193
1200
  prompt: body.prompt,
1194
1201
  model,
1195
1202
  permissionMode: permissionMode2,
1203
+ configDir,
1196
1204
  env: { SNA_SESSION_ID: sessionId },
1197
1205
  history: history.length > 0 ? history : void 0,
1198
1206
  extraArgs
1199
1207
  });
1200
1208
  sessionManager2.setProcess(sessionId, proc, "resumed");
1201
- sessionManager2.saveStartConfig(sessionId, { provider: providerName, model, permissionMode: permissionMode2, extraArgs });
1209
+ sessionManager2.saveStartConfig(sessionId, { provider: providerName, model, permissionMode: permissionMode2, configDir, extraArgs });
1202
1210
  logger.log("route", `POST /resume?session=${sessionId} \u2192 resumed (${history.length} history msgs)`);
1203
1211
  return httpJson(c, "agent.resume", {
1204
1212
  status: "resumed",
@@ -2105,7 +2113,8 @@ function handleAgentStart(ws, msg, sm) {
2105
2113
  }
2106
2114
  const providerName = msg.provider ?? "claude-code";
2107
2115
  const model = msg.model ?? "claude-sonnet-4-6";
2108
- const permissionMode2 = msg.permissionMode ?? "acceptEdits";
2116
+ const permissionMode2 = msg.permissionMode;
2117
+ const configDir = msg.configDir;
2109
2118
  const extraArgs = msg.extraArgs;
2110
2119
  try {
2111
2120
  const proc = provider2.spawn({
@@ -2113,12 +2122,13 @@ function handleAgentStart(ws, msg, sm) {
2113
2122
  prompt: msg.prompt,
2114
2123
  model,
2115
2124
  permissionMode: permissionMode2,
2125
+ configDir,
2116
2126
  env: { SNA_SESSION_ID: sessionId },
2117
2127
  history: msg.history,
2118
2128
  extraArgs
2119
2129
  });
2120
2130
  sm.setProcess(sessionId, proc);
2121
- sm.saveStartConfig(sessionId, { provider: providerName, model, permissionMode: permissionMode2, extraArgs });
2131
+ sm.saveStartConfig(sessionId, { provider: providerName, model, permissionMode: permissionMode2, configDir, extraArgs });
2122
2132
  wsReply(ws, msg, { status: "started", provider: provider2.name, sessionId: session.id });
2123
2133
  } catch (e) {
2124
2134
  replyError(ws, msg, e.message);
@@ -2180,7 +2190,8 @@ function handleAgentResume(ws, msg, sm) {
2180
2190
  }
2181
2191
  const providerName = msg.provider ?? session.lastStartConfig?.provider ?? "claude-code";
2182
2192
  const model = msg.model ?? session.lastStartConfig?.model ?? "claude-sonnet-4-6";
2183
- const permissionMode2 = msg.permissionMode ?? session.lastStartConfig?.permissionMode ?? "acceptEdits";
2193
+ const permissionMode2 = msg.permissionMode ?? session.lastStartConfig?.permissionMode;
2194
+ const configDir = msg.configDir ?? session.lastStartConfig?.configDir;
2184
2195
  const extraArgs = msg.extraArgs ?? session.lastStartConfig?.extraArgs;
2185
2196
  const provider2 = getProvider(providerName);
2186
2197
  try {
@@ -2189,12 +2200,13 @@ function handleAgentResume(ws, msg, sm) {
2189
2200
  prompt: msg.prompt,
2190
2201
  model,
2191
2202
  permissionMode: permissionMode2,
2203
+ configDir,
2192
2204
  env: { SNA_SESSION_ID: sessionId },
2193
2205
  history: history.length > 0 ? history : void 0,
2194
2206
  extraArgs
2195
2207
  });
2196
2208
  sm.setProcess(sessionId, proc, "resumed");
2197
- sm.saveStartConfig(sessionId, { provider: providerName, model, permissionMode: permissionMode2, extraArgs });
2209
+ sm.saveStartConfig(sessionId, { provider: providerName, model, permissionMode: permissionMode2, configDir, extraArgs });
2198
2210
  wsReply(ws, msg, {
2199
2211
  status: "resumed",
2200
2212
  provider: providerName,
@@ -2215,6 +2227,7 @@ function handleAgentRestart(ws, msg, sm) {
2215
2227
  provider: msg.provider,
2216
2228
  model: msg.model,
2217
2229
  permissionMode: msg.permissionMode,
2230
+ configDir: msg.configDir,
2218
2231
  extraArgs: msg.extraArgs
2219
2232
  },
2220
2233
  (cfg) => {
@@ -2224,6 +2237,7 @@ function handleAgentRestart(ws, msg, sm) {
2224
2237
  cwd: sm.getSession(sessionId).cwd,
2225
2238
  model: cfg.model,
2226
2239
  permissionMode: cfg.permissionMode,
2240
+ configDir: cfg.configDir,
2227
2241
  env: { SNA_SESSION_ID: sessionId },
2228
2242
  extraArgs: [...cfg.extraArgs ?? [], ...resumeArgs]
2229
2243
  });
@@ -2587,7 +2601,7 @@ try {
2587
2601
  process.exit(1);
2588
2602
  }
2589
2603
  var port = parseInt(process.env.SNA_PORT ?? "3099", 10);
2590
- var permissionMode = process.env.SNA_PERMISSION_MODE ?? "acceptEdits";
2604
+ var permissionMode = process.env.SNA_PERMISSION_MODE;
2591
2605
  var defaultModel = process.env.SNA_MODEL ?? "claude-sonnet-4-6";
2592
2606
  var maxSessions = parseInt(process.env.SNA_MAX_SESSIONS ?? "5", 10);
2593
2607
  var root = new Hono4();
package/dist/server/ws.js CHANGED
@@ -217,7 +217,8 @@ function handleAgentStart(ws, msg, sm) {
217
217
  }
218
218
  const providerName = msg.provider ?? "claude-code";
219
219
  const model = msg.model ?? "claude-sonnet-4-6";
220
- const permissionMode = msg.permissionMode ?? "acceptEdits";
220
+ const permissionMode = msg.permissionMode;
221
+ const configDir = msg.configDir;
221
222
  const extraArgs = msg.extraArgs;
222
223
  try {
223
224
  const proc = provider.spawn({
@@ -225,12 +226,13 @@ function handleAgentStart(ws, msg, sm) {
225
226
  prompt: msg.prompt,
226
227
  model,
227
228
  permissionMode,
229
+ configDir,
228
230
  env: { SNA_SESSION_ID: sessionId },
229
231
  history: msg.history,
230
232
  extraArgs
231
233
  });
232
234
  sm.setProcess(sessionId, proc);
233
- sm.saveStartConfig(sessionId, { provider: providerName, model, permissionMode, extraArgs });
235
+ sm.saveStartConfig(sessionId, { provider: providerName, model, permissionMode, configDir, extraArgs });
234
236
  wsReply(ws, msg, { status: "started", provider: provider.name, sessionId: session.id });
235
237
  } catch (e) {
236
238
  replyError(ws, msg, e.message);
@@ -292,7 +294,8 @@ function handleAgentResume(ws, msg, sm) {
292
294
  }
293
295
  const providerName = msg.provider ?? session.lastStartConfig?.provider ?? "claude-code";
294
296
  const model = msg.model ?? session.lastStartConfig?.model ?? "claude-sonnet-4-6";
295
- const permissionMode = msg.permissionMode ?? session.lastStartConfig?.permissionMode ?? "acceptEdits";
297
+ const permissionMode = msg.permissionMode ?? session.lastStartConfig?.permissionMode;
298
+ const configDir = msg.configDir ?? session.lastStartConfig?.configDir;
296
299
  const extraArgs = msg.extraArgs ?? session.lastStartConfig?.extraArgs;
297
300
  const provider = getProvider(providerName);
298
301
  try {
@@ -301,12 +304,13 @@ function handleAgentResume(ws, msg, sm) {
301
304
  prompt: msg.prompt,
302
305
  model,
303
306
  permissionMode,
307
+ configDir,
304
308
  env: { SNA_SESSION_ID: sessionId },
305
309
  history: history.length > 0 ? history : void 0,
306
310
  extraArgs
307
311
  });
308
312
  sm.setProcess(sessionId, proc, "resumed");
309
- sm.saveStartConfig(sessionId, { provider: providerName, model, permissionMode, extraArgs });
313
+ sm.saveStartConfig(sessionId, { provider: providerName, model, permissionMode, configDir, extraArgs });
310
314
  wsReply(ws, msg, {
311
315
  status: "resumed",
312
316
  provider: providerName,
@@ -327,6 +331,7 @@ function handleAgentRestart(ws, msg, sm) {
327
331
  provider: msg.provider,
328
332
  model: msg.model,
329
333
  permissionMode: msg.permissionMode,
334
+ configDir: msg.configDir,
330
335
  extraArgs: msg.extraArgs
331
336
  },
332
337
  (cfg) => {
@@ -336,6 +341,7 @@ function handleAgentRestart(ws, msg, sm) {
336
341
  cwd: sm.getSession(sessionId).cwd,
337
342
  model: cfg.model,
338
343
  permissionMode: cfg.permissionMode,
344
+ configDir: cfg.configDir,
339
345
  env: { SNA_SESSION_ID: sessionId },
340
346
  extraArgs: [...cfg.extraArgs ?? [], ...resumeArgs]
341
347
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sna-sdk/core",
3
- "version": "0.7.2",
3
+ "version": "0.8.1",
4
4
  "description": "Skills-Native Application runtime — server, providers, session management, database, and CLI",
5
5
  "type": "module",
6
6
  "bin": {