@scotthamilton77/sidekick 0.1.0 → 0.1.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/dist/bin.js CHANGED
@@ -17149,7 +17149,27 @@ var require_persona = __commonJS({
17149
17149
  /** Optional persona-specific snarky welcome examples for returning users (8-10 words max) */
17150
17150
  snarky_welcome_examples: zod_1.z.array(zod_1.z.string()).optional(),
17151
17151
  /** Optional situational context override (default: "You are watching over the shoulder of a software developer as they work.") */
17152
- situation: zod_1.z.string().optional()
17152
+ situation: zod_1.z.string().optional(),
17153
+ /** Optional recommended LLM profile for persona-driven outputs (snarky, resume) */
17154
+ llmProfile: zod_1.z.string().optional()
17155
+ });
17156
+ }
17157
+ });
17158
+
17159
+ // ../types/dist/services/user-profile.js
17160
+ var require_user_profile = __commonJS({
17161
+ "../types/dist/services/user-profile.js"(exports2) {
17162
+ "use strict";
17163
+ Object.defineProperty(exports2, "__esModule", { value: true });
17164
+ exports2.UserProfileSchema = void 0;
17165
+ var zod_1 = require_zod();
17166
+ exports2.UserProfileSchema = zod_1.z.object({
17167
+ /** User's display name */
17168
+ name: zod_1.z.string().min(1),
17169
+ /** User's role (e.g., "Software Architect") */
17170
+ role: zod_1.z.string().min(1),
17171
+ /** User's interests as string array */
17172
+ interests: zod_1.z.array(zod_1.z.string())
17153
17173
  });
17154
17174
  }
17155
17175
  });
@@ -17265,7 +17285,11 @@ var require_state = __commonJS({
17265
17285
  /** Snarky welcome message for returning user */
17266
17286
  snarky_comment: zod_1.z.string(),
17267
17287
  /** ISO8601 timestamp when this was generated */
17268
- timestamp: zod_1.z.string()
17288
+ timestamp: zod_1.z.string(),
17289
+ /** Persona ID that generated this message (null when persona disabled) */
17290
+ persona_id: zod_1.z.string().nullable().default(null),
17291
+ /** Display name for attribution (null when persona disabled) */
17292
+ persona_display_name: zod_1.z.string().nullable().default(null)
17269
17293
  });
17270
17294
  exports2.TranscriptMetricsStateSchema = zod_1.z.object({
17271
17295
  /** Session identifier */
@@ -17581,6 +17605,7 @@ var require_services = __commonJS({
17581
17605
  Object.defineProperty(exports2, "__esModule", { value: true });
17582
17606
  __exportStar(require_config(), exports2);
17583
17607
  __exportStar(require_persona(), exports2);
17608
+ __exportStar(require_user_profile(), exports2);
17584
17609
  __exportStar(require_service_factory(), exports2);
17585
17610
  __exportStar(require_staging(), exports2);
17586
17611
  __exportStar(require_state(), exports2);
@@ -27632,10 +27657,13 @@ var require_config2 = __commonJS({
27632
27657
  "../sidekick-core/dist/config.js"(exports2) {
27633
27658
  "use strict";
27634
27659
  Object.defineProperty(exports2, "__esModule", { value: true });
27635
- exports2.SidekickConfigSchema = exports2.FeaturesConfigSchema = exports2.TranscriptConfigSchema = exports2.LlmConfigSchema = exports2.CoreConfigSchema = void 0;
27660
+ exports2.EXTERNAL_DEFAULTS_FILES = exports2.SidekickConfigSchema = exports2.FeaturesConfigSchema = exports2.TranscriptConfigSchema = exports2.LlmConfigSchema = exports2.CoreConfigSchema = exports2.DOMAIN_FILES = void 0;
27661
+ exports2.deepMerge = deepMerge;
27662
+ exports2.coerceValue = coerceValue;
27663
+ exports2.setNestedValue = setNestedValue;
27664
+ exports2.tryReadYaml = tryReadYaml;
27636
27665
  exports2.loadConfig = loadConfig;
27637
27666
  exports2.createConfigService = createConfigService;
27638
- exports2.parseUnifiedConfig = parseUnifiedConfig;
27639
27667
  var dotenv_1 = require_main();
27640
27668
  var node_fs_1 = require("node:fs");
27641
27669
  var node_os_1 = require("node:os");
@@ -27655,8 +27683,8 @@ var require_config2 = __commonJS({
27655
27683
  }
27656
27684
  return obj;
27657
27685
  }
27658
- var DOMAIN_FILES = {
27659
- core: "config.yaml",
27686
+ exports2.DOMAIN_FILES = {
27687
+ core: "core.yaml",
27660
27688
  llm: "llm.yaml",
27661
27689
  transcript: "transcript.yaml",
27662
27690
  features: "features.yaml"
@@ -27710,14 +27738,17 @@ var require_config2 = __commonJS({
27710
27738
  maxTokens: v4_1.z.number().positive(),
27711
27739
  timeout: v4_1.z.number().min(1).max(300),
27712
27740
  timeoutMaxRetries: v4_1.z.number().min(0).max(10),
27741
+ // Optional fallback profile ID from fallbackProfiles namespace
27742
+ fallbackProfileId: v4_1.z.string().optional(),
27713
27743
  // OpenRouter-specific provider routing (ignored for other providers)
27714
27744
  providerAllowlist: v4_1.z.array(v4_1.z.string()).optional(),
27715
27745
  providerBlocklist: v4_1.z.array(v4_1.z.string()).optional()
27716
27746
  });
27717
27747
  exports2.LlmConfigSchema = v4_1.z.object({
27718
27748
  defaultProfile: v4_1.z.string(),
27749
+ defaultFallbackProfileId: v4_1.z.string().optional(),
27719
27750
  profiles: v4_1.z.record(v4_1.z.string(), LlmProfileSchema),
27720
- fallbacks: v4_1.z.record(v4_1.z.string(), LlmProfileSchema).optional(),
27751
+ fallbackProfiles: v4_1.z.record(v4_1.z.string(), LlmProfileSchema).optional(),
27721
27752
  global: v4_1.z.object({
27722
27753
  debugDumpEnabled: v4_1.z.boolean(),
27723
27754
  emulatedProvider: EmulatedProviderSchema.optional()
@@ -27731,10 +27762,29 @@ var require_config2 = __commonJS({
27731
27762
  input: data.defaultProfile
27732
27763
  });
27733
27764
  }
27765
+ if (data.defaultFallbackProfileId && !data.fallbackProfiles?.[data.defaultFallbackProfileId]) {
27766
+ ctx.addIssue({
27767
+ code: "custom",
27768
+ message: `defaultFallbackProfileId "${data.defaultFallbackProfileId}" not found in fallbackProfiles`,
27769
+ path: ["defaultFallbackProfileId"],
27770
+ input: data.defaultFallbackProfileId
27771
+ });
27772
+ }
27773
+ for (const [profileName, profile] of Object.entries(data.profiles)) {
27774
+ if (profile.fallbackProfileId && !data.fallbackProfiles?.[profile.fallbackProfileId]) {
27775
+ ctx.addIssue({
27776
+ code: "custom",
27777
+ message: `Profile "${profileName}" fallbackProfileId "${profile.fallbackProfileId}" not found in fallbackProfiles`,
27778
+ path: ["profiles", profileName, "fallbackProfileId"],
27779
+ input: profile.fallbackProfileId
27780
+ });
27781
+ }
27782
+ }
27734
27783
  }).transform((val) => ({
27735
27784
  defaultProfile: val.defaultProfile,
27785
+ defaultFallbackProfileId: val.defaultFallbackProfileId,
27736
27786
  profiles: val.profiles,
27737
- fallbacks: val.fallbacks ?? {},
27787
+ fallbackProfiles: val.fallbackProfiles ?? {},
27738
27788
  global: val.global ?? { debugDumpEnabled: false, emulatedProvider: void 0 }
27739
27789
  }));
27740
27790
  exports2.TranscriptConfigSchema = v4_1.z.object({
@@ -27769,43 +27819,6 @@ var require_config2 = __commonJS({
27769
27819
  }
27770
27820
  return result;
27771
27821
  }
27772
- function parseUnifiedConfig(content, sourcePath) {
27773
- const result = {};
27774
- const overrides = [];
27775
- const warnings = [];
27776
- const sourceLabel = sourcePath ?? "sidekick.config";
27777
- const lines = content.split("\n");
27778
- for (let lineNum = 0; lineNum < lines.length; lineNum++) {
27779
- const line = lines[lineNum];
27780
- const trimmed = line.trim();
27781
- if (!trimmed || trimmed.startsWith("#")) {
27782
- continue;
27783
- }
27784
- const eqIndex = trimmed.indexOf("=");
27785
- const colonIndex = trimmed.indexOf(":");
27786
- if (eqIndex === -1 && colonIndex === -1) {
27787
- warnings.push(`${sourceLabel}:${lineNum + 1}: malformed line (missing '=' or ':'): ${trimmed}`);
27788
- continue;
27789
- }
27790
- const delimIndex = eqIndex === -1 ? colonIndex : colonIndex === -1 ? eqIndex : Math.min(eqIndex, colonIndex);
27791
- const key = trimmed.substring(0, delimIndex).trim();
27792
- const rawValue = trimmed.substring(delimIndex + 1).trim();
27793
- const parts = key.split(".");
27794
- if (parts.length < 2) {
27795
- warnings.push(`${sourceLabel}:${lineNum + 1}: invalid key format (need domain.key): ${key}`);
27796
- continue;
27797
- }
27798
- const domain = parts[0];
27799
- const path = parts.slice(1);
27800
- const value = coerceValue(rawValue);
27801
- if (!result[domain]) {
27802
- result[domain] = {};
27803
- }
27804
- setNestedValue(result[domain], path, value);
27805
- overrides.push({ key, value });
27806
- }
27807
- return { config: result, overrides, warnings };
27808
- }
27809
27822
  function coerceValue(raw) {
27810
27823
  if (raw === "true")
27811
27824
  return true;
@@ -27849,13 +27862,6 @@ var require_config2 = __commonJS({
27849
27862
  throw new Error(`Failed to parse YAML at ${filePath}: ${message}`, { cause: err });
27850
27863
  }
27851
27864
  }
27852
- function tryReadUnifiedConfig(filePath) {
27853
- if (!(0, node_fs_1.existsSync)(filePath)) {
27854
- return null;
27855
- }
27856
- const content = (0, node_fs_1.readFileSync)(filePath, "utf8");
27857
- return parseUnifiedConfig(content, filePath);
27858
- }
27859
27865
  function loadEnvFiles(homeDir, projectRoot) {
27860
27866
  const envPaths = [];
27861
27867
  const userEnv = (0, node_path_1.join)(homeDir, ".sidekick", ".env");
@@ -27903,7 +27909,7 @@ var require_config2 = __commonJS({
27903
27909
  }
27904
27910
  return result;
27905
27911
  }
27906
- var EXTERNAL_DEFAULTS_FILES = {
27912
+ exports2.EXTERNAL_DEFAULTS_FILES = {
27907
27913
  core: "defaults/core.defaults.yaml",
27908
27914
  llm: "defaults/llm.defaults.yaml",
27909
27915
  transcript: "defaults/transcript.defaults.yaml",
@@ -27913,16 +27919,16 @@ var require_config2 = __commonJS({
27913
27919
  if (!assets) {
27914
27920
  return null;
27915
27921
  }
27916
- const filePath = EXTERNAL_DEFAULTS_FILES[domain];
27922
+ const filePath = exports2.EXTERNAL_DEFAULTS_FILES[domain];
27917
27923
  return assets.resolveYaml(filePath) ?? null;
27918
27924
  }
27919
- function loadDomainConfig(domain, envConfig, userUnified, userDomainPath, projectUnified, projectDomainPath, projectLocalPath, assets) {
27925
+ function loadDomainConfig(domain, envConfig, userDomainPath, projectDomainPath, projectLocalPath, assets) {
27920
27926
  const sources = [];
27921
27927
  let merged = {};
27922
27928
  const externalDefaults = loadExternalDefaults(domain, assets);
27923
27929
  if (externalDefaults) {
27924
27930
  merged = deepMerge(merged, externalDefaults);
27925
- sources.push({ source: `assets:${EXTERNAL_DEFAULTS_FILES[domain]}`, domain });
27931
+ sources.push({ source: `assets:${exports2.EXTERNAL_DEFAULTS_FILES[domain]}`, domain });
27926
27932
  }
27927
27933
  if (envConfig[domain]) {
27928
27934
  merged = deepMerge(merged, envConfig[domain]);
@@ -27933,10 +27939,6 @@ var require_config2 = __commonJS({
27933
27939
  merged = deepMerge(merged, userDomain);
27934
27940
  sources.push({ source: userDomainPath, domain });
27935
27941
  }
27936
- if (userUnified?.[domain]) {
27937
- merged = deepMerge(merged, userUnified[domain]);
27938
- sources.push({ source: "user:sidekick.config", domain });
27939
- }
27940
27942
  if (projectDomainPath) {
27941
27943
  const projectDomain = tryReadYaml(projectDomainPath);
27942
27944
  if (projectDomain) {
@@ -27944,10 +27946,6 @@ var require_config2 = __commonJS({
27944
27946
  sources.push({ source: projectDomainPath, domain });
27945
27947
  }
27946
27948
  }
27947
- if (projectUnified?.[domain]) {
27948
- merged = deepMerge(merged, projectUnified[domain]);
27949
- sources.push({ source: "project:sidekick.config", domain });
27950
- }
27951
27949
  if (projectLocalPath) {
27952
27950
  const projectLocal = tryReadYaml(projectLocalPath);
27953
27951
  if (projectLocal) {
@@ -27959,7 +27957,7 @@ var require_config2 = __commonJS({
27959
27957
  }
27960
27958
  function validateProfileReferences(config) {
27961
27959
  const validProfiles = new Set(Object.keys(config.llm.profiles));
27962
- const validFallbacks = new Set(Object.keys(config.llm.fallbacks));
27960
+ const validFallbacks = new Set(Object.keys(config.llm.fallbackProfiles));
27963
27961
  const errors = [];
27964
27962
  for (const [featureName, featureConfig] of Object.entries(config.features)) {
27965
27963
  const llmConfig = featureConfig.settings?.llm;
@@ -27992,24 +27990,33 @@ ${errors.join("\n")}`);
27992
27990
  const projectRoot = options.projectRoot;
27993
27991
  loadEnvFiles(homeDir, projectRoot);
27994
27992
  const envConfig = envToConfig(process.env);
27995
- const userUnifiedPath = (0, node_path_1.join)(homeDir, ".sidekick", "sidekick.config");
27996
- const userUnifiedParsed = tryReadUnifiedConfig(userUnifiedPath);
27997
- const projectUnifiedPath = projectRoot ? (0, node_path_1.join)(projectRoot, ".sidekick", "sidekick.config") : null;
27998
- const projectUnifiedParsed = projectUnifiedPath ? tryReadUnifiedConfig(projectUnifiedPath) : null;
27999
- const userUnified = userUnifiedParsed?.config ?? null;
28000
- const projectUnified = projectUnifiedParsed?.config ?? null;
28001
27993
  const userSidekick = (0, node_path_1.join)(homeDir, ".sidekick");
28002
27994
  const projectSidekick = projectRoot ? (0, node_path_1.join)(projectRoot, ".sidekick") : null;
28003
27995
  const domains = ["core", "llm", "transcript", "features"];
28004
27996
  const domainConfigs = {};
28005
27997
  for (const domain of domains) {
28006
- const filename = DOMAIN_FILES[domain];
27998
+ const filename = exports2.DOMAIN_FILES[domain];
28007
27999
  const userDomainPath = (0, node_path_1.join)(userSidekick, filename);
28008
28000
  const projectDomainPath = projectSidekick ? (0, node_path_1.join)(projectSidekick, filename) : null;
28009
- const projectLocalPath = projectSidekick ? (0, node_path_1.join)(projectSidekick, `${filename}.local`) : null;
28010
- const { config } = loadDomainConfig(domain, envConfig, userUnified, userDomainPath, projectUnified, projectDomainPath, projectLocalPath, options.assets);
28001
+ const projectLocalPath = projectSidekick ? (0, node_path_1.join)(projectSidekick, `${filename.replace(".yaml", ".local.yaml")}`) : null;
28002
+ const { config } = loadDomainConfig(domain, envConfig, userDomainPath, projectDomainPath, projectLocalPath, options.assets);
28011
28003
  domainConfigs[domain] = config;
28012
28004
  }
28005
+ const legacyDirs = [userSidekick, projectSidekick].filter(Boolean);
28006
+ for (const dir of legacyDirs) {
28007
+ const legacyPath = (0, node_path_1.join)(dir, "sidekick.config");
28008
+ if ((0, node_fs_1.existsSync)(legacyPath)) {
28009
+ options.logger?.warn(`Legacy sidekick.config found at "${legacyPath}" \u2014 this file is no longer read. Migrate settings to .sidekick/{domain}.yaml files (core.yaml, llm.yaml, transcript.yaml, features.yaml).`);
28010
+ }
28011
+ const oldConfigPath = (0, node_path_1.join)(dir, "config.yaml");
28012
+ if ((0, node_fs_1.existsSync)(oldConfigPath)) {
28013
+ options.logger?.warn(`Renamed config file found at "${oldConfigPath}" \u2014 "config.yaml" has been renamed to "core.yaml". Please rename your file.`);
28014
+ }
28015
+ const oldConfigLocalPath = (0, node_path_1.join)(dir, "config.local.yaml");
28016
+ if ((0, node_fs_1.existsSync)(oldConfigLocalPath)) {
28017
+ options.logger?.warn(`Renamed config file found at "${oldConfigLocalPath}" \u2014 "config.local.yaml" has been renamed to "core.local.yaml". Please rename your file.`);
28018
+ }
28019
+ }
28013
28020
  const result = exports2.SidekickConfigSchema.safeParse(domainConfigs);
28014
28021
  if (!result.success) {
28015
28022
  const issues = result.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ");
@@ -28062,38 +28069,10 @@ ${errors.join("\n")}`);
28062
28069
  if (Object.keys(envConfig).length > 0) {
28063
28070
  sources.push("environment");
28064
28071
  }
28065
- const userUnifiedPath = (0, node_path_1.join)(homeDir, ".sidekick", "sidekick.config");
28066
- const userUnifiedParsed = tryReadUnifiedConfig(userUnifiedPath);
28067
- if (userUnifiedParsed) {
28068
- sources.push(userUnifiedPath);
28069
- for (const warning of userUnifiedParsed.warnings) {
28070
- logger?.warn("Config parse warning", { warning });
28071
- }
28072
- if (userUnifiedParsed.overrides.length > 0 && logger) {
28073
- logger.info("User config overrides loaded", {
28074
- source: userUnifiedPath,
28075
- overrides: userUnifiedParsed.overrides
28076
- });
28077
- }
28078
- }
28079
- const projectUnifiedPath = projectRoot ? (0, node_path_1.join)(projectRoot, ".sidekick", "sidekick.config") : null;
28080
- const projectUnifiedParsed = projectUnifiedPath ? tryReadUnifiedConfig(projectUnifiedPath) : null;
28081
- if (projectUnifiedParsed) {
28082
- sources.push(projectUnifiedPath);
28083
- for (const warning of projectUnifiedParsed.warnings) {
28084
- logger?.warn("Config parse warning", { warning });
28085
- }
28086
- if (projectUnifiedParsed.overrides.length > 0 && logger) {
28087
- logger.info("Project config overrides loaded", {
28088
- source: projectUnifiedPath,
28089
- overrides: projectUnifiedParsed.overrides
28090
- });
28091
- }
28092
- }
28093
28072
  const userSidekick = (0, node_path_1.join)(homeDir, ".sidekick");
28094
28073
  const projectSidekick = projectRoot ? (0, node_path_1.join)(projectRoot, ".sidekick") : null;
28095
- for (const domain of Object.keys(DOMAIN_FILES)) {
28096
- const filename = DOMAIN_FILES[domain];
28074
+ for (const domain of Object.keys(exports2.DOMAIN_FILES)) {
28075
+ const filename = exports2.DOMAIN_FILES[domain];
28097
28076
  const userDomainPath = (0, node_path_1.join)(userSidekick, filename);
28098
28077
  if ((0, node_fs_1.existsSync)(userDomainPath)) {
28099
28078
  sources.push(userDomainPath);
@@ -28103,7 +28082,7 @@ ${errors.join("\n")}`);
28103
28082
  if ((0, node_fs_1.existsSync)(projectDomainPath)) {
28104
28083
  sources.push(projectDomainPath);
28105
28084
  }
28106
- const projectLocalPath = (0, node_path_1.join)(projectSidekick, `${filename}.local`);
28085
+ const projectLocalPath = (0, node_path_1.join)(projectSidekick, `${filename.replace(".yaml", ".local.yaml")}`);
28107
28086
  if ((0, node_fs_1.existsSync)(projectLocalPath)) {
28108
28087
  sources.push(projectLocalPath);
28109
28088
  }
@@ -28168,6 +28147,231 @@ ${errors.join("\n")}`);
28168
28147
  }
28169
28148
  });
28170
28149
 
28150
+ // ../sidekick-core/dist/config-writer.js
28151
+ var require_config_writer = __commonJS({
28152
+ "../sidekick-core/dist/config-writer.js"(exports2) {
28153
+ "use strict";
28154
+ var __importDefault2 = exports2 && exports2.__importDefault || function(mod) {
28155
+ return mod && mod.__esModule ? mod : { "default": mod };
28156
+ };
28157
+ Object.defineProperty(exports2, "__esModule", { value: true });
28158
+ exports2.parseDotPath = parseDotPath;
28159
+ exports2.getNestedValue = getNestedValue;
28160
+ exports2.getScopeFilePath = getScopeFilePath;
28161
+ exports2.configGet = configGet;
28162
+ exports2.configSet = configSet;
28163
+ exports2.configUnset = configUnset;
28164
+ exports2.configList = configList;
28165
+ var node_fs_1 = require("node:fs");
28166
+ var node_os_1 = require("node:os");
28167
+ var node_path_1 = require("node:path");
28168
+ var yaml_1 = __importDefault2(require_dist2());
28169
+ var config_1 = require_config2();
28170
+ var VALID_DOMAINS = /* @__PURE__ */ new Set(["core", "llm", "transcript", "features"]);
28171
+ var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
28172
+ function parseDotPath(dotPath) {
28173
+ if (!dotPath || dotPath.trim() === "") {
28174
+ throw new Error("Config path must not be empty");
28175
+ }
28176
+ const segments = dotPath.split(".");
28177
+ const domainCandidate = segments[0];
28178
+ if (!VALID_DOMAINS.has(domainCandidate)) {
28179
+ throw new Error(`Unknown domain "${domainCandidate}". Valid domains: ${[...VALID_DOMAINS].join(", ")}`);
28180
+ }
28181
+ const keyPath = segments.slice(1);
28182
+ for (const key of keyPath) {
28183
+ if (FORBIDDEN_KEYS.has(key)) {
28184
+ throw new Error(`Invalid key segment "${key}" in config path`);
28185
+ }
28186
+ }
28187
+ return {
28188
+ domain: domainCandidate,
28189
+ keyPath
28190
+ };
28191
+ }
28192
+ function getNestedValue(obj, keyPath) {
28193
+ if (keyPath.length === 0) {
28194
+ return obj;
28195
+ }
28196
+ let current = obj;
28197
+ for (const key of keyPath) {
28198
+ if (current === null || current === void 0 || typeof current !== "object") {
28199
+ return void 0;
28200
+ }
28201
+ current = current[key];
28202
+ }
28203
+ return current;
28204
+ }
28205
+ function getScopeFilePath(domain, scope, projectRoot, homeDir) {
28206
+ const filename = config_1.DOMAIN_FILES[domain];
28207
+ switch (scope) {
28208
+ case "user":
28209
+ return (0, node_path_1.join)(homeDir, ".sidekick", filename);
28210
+ case "project":
28211
+ if (!projectRoot)
28212
+ return null;
28213
+ return (0, node_path_1.join)(projectRoot, ".sidekick", filename);
28214
+ case "local":
28215
+ if (!projectRoot)
28216
+ return null;
28217
+ return (0, node_path_1.join)(projectRoot, ".sidekick", filename.replace(".yaml", ".local.yaml"));
28218
+ }
28219
+ }
28220
+ function configGet(dotPath, options = {}) {
28221
+ const { domain, keyPath } = parseDotPath(dotPath);
28222
+ const home = options.homeDir ?? (0, node_os_1.homedir)();
28223
+ if (options.scope) {
28224
+ const filePath = getScopeFilePath(domain, options.scope, options.projectRoot, home);
28225
+ if (!filePath) {
28226
+ return void 0;
28227
+ }
28228
+ const raw = (0, config_1.tryReadYaml)(filePath);
28229
+ if (!raw || Object.keys(raw).length === 0) {
28230
+ return void 0;
28231
+ }
28232
+ const value2 = getNestedValue(raw, keyPath);
28233
+ if (value2 === void 0) {
28234
+ return void 0;
28235
+ }
28236
+ return { value: value2, domain, path: keyPath };
28237
+ }
28238
+ const config = (0, config_1.loadConfig)({
28239
+ projectRoot: options.projectRoot,
28240
+ homeDir: home,
28241
+ assets: options.assets,
28242
+ logger: options.logger
28243
+ });
28244
+ const domainConfig = config[domain];
28245
+ const value = getNestedValue(domainConfig, keyPath);
28246
+ if (value === void 0) {
28247
+ return void 0;
28248
+ }
28249
+ return { value, domain, path: keyPath };
28250
+ }
28251
+ function configSet(dotPath, rawValue, options = {}) {
28252
+ const { domain, keyPath } = parseDotPath(dotPath);
28253
+ if (keyPath.length === 0) {
28254
+ throw new Error('Cannot set an entire domain. Specify a key path (e.g., "core.logging.level")');
28255
+ }
28256
+ const home = options.homeDir ?? (0, node_os_1.homedir)();
28257
+ const scope = options.scope ?? "project";
28258
+ const coercedValue = (0, config_1.coerceValue)(rawValue);
28259
+ const projectRoot = options.projectRoot ?? (scope !== "user" ? process.cwd() : void 0);
28260
+ const filePath = getScopeFilePath(domain, scope, projectRoot, home);
28261
+ if (!filePath) {
28262
+ throw new Error(`Cannot resolve file path for domain "${domain}" at scope "${scope}". Is projectRoot set?`);
28263
+ }
28264
+ const fileExisted = (0, node_fs_1.existsSync)(filePath);
28265
+ const originalContent = fileExisted ? (0, node_fs_1.readFileSync)(filePath, "utf8") : null;
28266
+ let doc;
28267
+ if (fileExisted) {
28268
+ doc = yaml_1.default.parseDocument(originalContent);
28269
+ throwOnYamlErrors(doc, `Failed to parse YAML at "${filePath}"`);
28270
+ } else {
28271
+ doc = seedDocumentFromDefaults(domain, options.assets) ?? new yaml_1.default.Document({});
28272
+ }
28273
+ doc.setIn(keyPath, coercedValue);
28274
+ const dir = (0, node_path_1.dirname)(filePath);
28275
+ if (!(0, node_fs_1.existsSync)(dir)) {
28276
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
28277
+ }
28278
+ (0, node_fs_1.writeFileSync)(filePath, doc.toString(), "utf8");
28279
+ try {
28280
+ (0, config_1.loadConfig)({
28281
+ projectRoot,
28282
+ homeDir: home,
28283
+ assets: options.assets,
28284
+ logger: options.logger
28285
+ });
28286
+ } catch (err) {
28287
+ if (fileExisted) {
28288
+ (0, node_fs_1.writeFileSync)(filePath, originalContent, "utf8");
28289
+ } else {
28290
+ try {
28291
+ (0, node_fs_1.unlinkSync)(filePath);
28292
+ } catch {
28293
+ }
28294
+ }
28295
+ const message = err instanceof Error ? err.message : String(err);
28296
+ throw new Error(`Configuration validation failed after setting "${dotPath}": ${message}`, { cause: err });
28297
+ }
28298
+ return {
28299
+ domain,
28300
+ path: keyPath,
28301
+ value: coercedValue,
28302
+ filePath
28303
+ };
28304
+ }
28305
+ function configUnset(dotPath, options = {}) {
28306
+ const { domain, keyPath } = parseDotPath(dotPath);
28307
+ if (keyPath.length === 0) {
28308
+ throw new Error('Cannot unset an entire domain. Specify a key path (e.g., "core.logging.level")');
28309
+ }
28310
+ const home = options.homeDir ?? (0, node_os_1.homedir)();
28311
+ const scope = options.scope ?? "project";
28312
+ const filePath = getScopeFilePath(domain, scope, options.projectRoot, home);
28313
+ if (!filePath) {
28314
+ throw new Error(`Cannot resolve file path for domain "${domain}" at scope "${scope}". Is projectRoot set?`);
28315
+ }
28316
+ if (!(0, node_fs_1.existsSync)(filePath)) {
28317
+ return { domain, path: keyPath, filePath, existed: false };
28318
+ }
28319
+ const content = (0, node_fs_1.readFileSync)(filePath, "utf8");
28320
+ const doc = yaml_1.default.parseDocument(content);
28321
+ throwOnYamlErrors(doc, `Failed to parse YAML at "${filePath}"`);
28322
+ const existed = doc.getIn(keyPath) !== void 0;
28323
+ if (existed) {
28324
+ doc.deleteIn(keyPath);
28325
+ (0, node_fs_1.writeFileSync)(filePath, doc.toString(), "utf8");
28326
+ }
28327
+ return { domain, path: keyPath, filePath, existed };
28328
+ }
28329
+ function configList(options = {}) {
28330
+ const home = options.homeDir ?? (0, node_os_1.homedir)();
28331
+ const scope = options.scope ?? "project";
28332
+ const entries = [];
28333
+ for (const domain of VALID_DOMAINS) {
28334
+ const filePath = getScopeFilePath(domain, scope, options.projectRoot, home);
28335
+ if (!filePath)
28336
+ continue;
28337
+ const raw = (0, config_1.tryReadYaml)(filePath);
28338
+ if (!raw || Object.keys(raw).length === 0)
28339
+ continue;
28340
+ flattenObject(raw, domain, entries);
28341
+ }
28342
+ return { scope, entries };
28343
+ }
28344
+ function flattenObject(obj, prefix, entries) {
28345
+ for (const [key, value] of Object.entries(obj)) {
28346
+ const path = `${prefix}.${key}`;
28347
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
28348
+ flattenObject(value, path, entries);
28349
+ } else {
28350
+ entries.push({ path, value });
28351
+ }
28352
+ }
28353
+ }
28354
+ function throwOnYamlErrors(doc, context) {
28355
+ if (doc.errors.length > 0) {
28356
+ const messages = doc.errors.map((e) => e.message).join("; ");
28357
+ throw new Error(`${context}: ${messages}`);
28358
+ }
28359
+ }
28360
+ function seedDocumentFromDefaults(domain, assets) {
28361
+ if (!assets)
28362
+ return null;
28363
+ const defaultsRelPath = config_1.EXTERNAL_DEFAULTS_FILES[domain];
28364
+ const defaultsAbsPath = assets.resolvePath(defaultsRelPath);
28365
+ if (!defaultsAbsPath || !(0, node_fs_1.existsSync)(defaultsAbsPath))
28366
+ return null;
28367
+ const raw = (0, node_fs_1.readFileSync)(defaultsAbsPath, "utf8");
28368
+ const doc = yaml_1.default.parseDocument(raw);
28369
+ throwOnYamlErrors(doc, `Invalid bundled defaults YAML for domain "${domain}"`);
28370
+ return doc;
28371
+ }
28372
+ }
28373
+ });
28374
+
28171
28375
  // ../sidekick-core/dist/feature-registry.js
28172
28376
  var require_feature_registry = __commonJS({
28173
28377
  "../sidekick-core/dist/feature-registry.js"(exports2) {
@@ -28773,7 +28977,7 @@ var require_ipc_service = __commonJS({
28773
28977
  this.client = new client_js_1.IpcClient((0, transport_js_1.getSocketPath)(projectDir), logger, options);
28774
28978
  }
28775
28979
  /**
28776
- * Create IpcService from CoreConfig, using IPC settings from config.yaml.
28980
+ * Create IpcService from CoreConfig, using IPC settings from core.yaml.
28777
28981
  *
28778
28982
  * @param projectDir - Project directory path
28779
28983
  * @param logger - Logger instance
@@ -56425,7 +56629,13 @@ var require_profile_factory = __commonJS({
56425
56629
  }
56426
56630
  /**
56427
56631
  * Creates a provider for a profile, reading config at call time.
56428
- * Wraps with FallbackProvider if fallbackProfile specified.
56632
+ * Wraps with FallbackProvider if a fallback is resolved.
56633
+ *
56634
+ * Fallback resolution cascade:
56635
+ * 1. Explicit fallbackProfileId parameter (caller override)
56636
+ * 2. Profile-level fallbackProfileId (per-profile config)
56637
+ * 3. Global defaultFallbackProfileId (llm config level)
56638
+ * 4. No fallback
56429
56639
  */
56430
56640
  createForProfile(profileId, fallbackProfileId) {
56431
56641
  const profile = this.configService.llm.profiles[profileId];
@@ -56433,13 +56643,14 @@ var require_profile_factory = __commonJS({
56433
56643
  throw new Error(`Profile "${profileId}" not found`);
56434
56644
  }
56435
56645
  const primary = this.createProvider(profile, profileId);
56436
- if (!fallbackProfileId)
56646
+ const resolvedFallbackId = fallbackProfileId ?? profile.fallbackProfileId ?? this.configService.llm.defaultFallbackProfileId;
56647
+ if (!resolvedFallbackId)
56437
56648
  return primary;
56438
- const fallback = this.configService.llm.fallbacks[fallbackProfileId];
56649
+ const fallback = this.configService.llm.fallbackProfiles[resolvedFallbackId];
56439
56650
  if (!fallback) {
56440
- throw new Error(`Fallback profile "${fallbackProfileId}" not found`);
56651
+ throw new Error(`Fallback profile "${resolvedFallbackId}" not found`);
56441
56652
  }
56442
- return new fallback_1.FallbackProvider(primary, [this.createProvider(fallback, fallbackProfileId)], this.logger);
56653
+ return new fallback_1.FallbackProvider(primary, [this.createProvider(fallback, resolvedFallbackId)], this.logger);
56443
56654
  }
56444
56655
  /**
56445
56656
  * Creates provider for the default profile.
@@ -56642,7 +56853,8 @@ var require_gitignore = __commonJS({
56642
56853
  ".sidekick/.env",
56643
56854
  ".sidekick/.env.local",
56644
56855
  ".sidekick/sidekick*.pid",
56645
- ".sidekick/sidekick*.token"
56856
+ ".sidekick/sidekick*.token",
56857
+ ".sidekick/*.local.yaml"
56646
56858
  ];
56647
56859
  async function installGitignoreSection(projectDir) {
56648
56860
  const gitignorePath = path.join(projectDir, ".gitignore");
@@ -63124,6 +63336,46 @@ var require_git_status = __commonJS({
63124
63336
  }
63125
63337
  });
63126
63338
 
63339
+ // ../sidekick-core/dist/user-profile-loader.js
63340
+ var require_user_profile_loader = __commonJS({
63341
+ "../sidekick-core/dist/user-profile-loader.js"(exports2) {
63342
+ "use strict";
63343
+ Object.defineProperty(exports2, "__esModule", { value: true });
63344
+ exports2.loadUserProfile = loadUserProfile;
63345
+ var node_fs_1 = require("node:fs");
63346
+ var node_os_1 = require("node:os");
63347
+ var node_path_1 = require("node:path");
63348
+ var yaml_1 = require_dist2();
63349
+ var types_1 = require_dist();
63350
+ function loadUserProfile(options) {
63351
+ const home = options?.homeDir ?? (0, node_os_1.homedir)();
63352
+ const filePath = (0, node_path_1.join)(home, ".sidekick", "user.yaml");
63353
+ if (!(0, node_fs_1.existsSync)(filePath)) {
63354
+ return null;
63355
+ }
63356
+ try {
63357
+ const content = (0, node_fs_1.readFileSync)(filePath, "utf-8");
63358
+ const parsed = (0, yaml_1.parse)(content);
63359
+ const result = types_1.UserProfileSchema.safeParse(parsed);
63360
+ if (!result.success) {
63361
+ options?.logger?.warn("Invalid user profile, ignoring", {
63362
+ path: filePath,
63363
+ errors: result.error.issues.map((i) => i.message)
63364
+ });
63365
+ return null;
63366
+ }
63367
+ return result.data;
63368
+ } catch (err) {
63369
+ options?.logger?.warn("Failed to read user profile", {
63370
+ path: filePath,
63371
+ error: err instanceof Error ? err.message : String(err)
63372
+ });
63373
+ return null;
63374
+ }
63375
+ }
63376
+ }
63377
+ });
63378
+
63127
63379
  // ../sidekick-core/dist/index.js
63128
63380
  var require_dist4 = __commonJS({
63129
63381
  "../sidekick-core/dist/index.js"(exports2) {
@@ -63146,7 +63398,7 @@ var require_dist4 = __commonJS({
63146
63398
  };
63147
63399
  Object.defineProperty(exports2, "__esModule", { value: true });
63148
63400
  exports2.SIDEKICK_SECTION_START = exports2.detectGitignoreStatus = exports2.removeGitignoreSection = exports2.installGitignoreSection = exports2.validateOpenAIKey = exports2.validateOpenRouterKey = exports2.createSetupStatusService = exports2.SetupStatusService = exports2.DaemonClient = exports2.findZombieDaemons = exports2.killZombieDaemons = exports2.killAllDaemons = exports2.logEvent = exports2.LogEvents = exports2.DEFAULT_MAX_FILES = exports2.DEFAULT_ROTATE_SIZE_BYTES = exports2.getComponentLogLevel = exports2.setupGlobalErrorHandlers = exports2.createLoggerFacade = exports2.createLogManager = exports2.createConsoleLogger = exports2.getUserDaemonsDir = exports2.getUserPidPath = exports2.getTokenPath = exports2.getSocketPath = exports2.getProjectHash = exports2.getPidPath = exports2.getLockPath = exports2.IpcService = exports2.IpcServer = exports2.loadPersonaFile = exports2.getDefaultPersonasDir = exports2.discoverPersonas = exports2.createPersonaLoader = exports2.reconstructTranscriptPath = exports2.encodeProjectPath = exports2.isPreCompactEvent = exports2.isStopEvent = exports2.isPostToolUseEvent = exports2.isPreToolUseEvent = exports2.isUserPromptSubmitEvent = exports2.isSessionEndEvent = exports2.isSessionStartEvent = exports2.isTranscriptEvent = exports2.isHookEvent = exports2.MetricsPersistPayloadSchema = exports2.CleanupPayloadSchema = exports2.ResumeGenerationPayloadSchema = exports2.SessionSummaryPayloadSchema = exports2.TaskTypes = void 0;
63149
- exports2.parseGitStatusOutput = exports2.getGitFileStatus = exports2.isInSandbox = exports2.updateDaemonHealth = exports2.readDaemonHealth = exports2.DaemonGlobalLogMetricsDescriptor = exports2.CliLogMetricsDescriptor = exports2.DaemonLogMetricsDescriptor = exports2.CompactionHistoryDescriptor = exports2.TranscriptMetricsDescriptor = exports2.GlobalStateAccessor = exports2.SessionStateAccessor = exports2.globalState = exports2.sessionState = exports2.StateCorruptError = exports2.StateNotFoundError = exports2.StateService = exports2.createHookableLogger = exports2.InstrumentedProfileProviderFactory = exports2.InstrumentedLLMProvider = exports2.ServiceFactoryImpl = exports2.TranscriptServiceImpl = exports2.createDefaultTokenUsage = exports2.createDefaultMetrics = exports2.copyWithTimestampSync = exports2.renameWithTimestampSync = exports2.renameWithTimestamp = exports2.copyWithTimestamp = exports2.getTimestampedPath = exports2.extractToolResultPreview = exports2.extractToolCallPreview = exports2.extractTextFromContent = exports2.extractContentPreview = exports2.HandlerRegistryImpl = exports2.extractConsumedTimestamp = exports2.createConsumedFilePattern = exports2.CONSUMED_FILE_PATTERN = exports2.filterActiveReminderFiles = exports2.validatePathSegment = exports2.isValidPathSegment = exports2.getReminderPath = exports2.getHookDir = exports2.getStagingRoot = exports2.SessionScopedStagingService = exports2.StagingServiceCore = exports2.GITIGNORE_ENTRIES = exports2.SIDEKICK_SECTION_END = void 0;
63401
+ exports2.loadUserProfile = exports2.parseGitStatusOutput = exports2.getGitFileStatus = exports2.isInSandbox = exports2.updateDaemonHealth = exports2.readDaemonHealth = exports2.DaemonGlobalLogMetricsDescriptor = exports2.CliLogMetricsDescriptor = exports2.DaemonLogMetricsDescriptor = exports2.CompactionHistoryDescriptor = exports2.TranscriptMetricsDescriptor = exports2.GlobalStateAccessor = exports2.SessionStateAccessor = exports2.globalState = exports2.sessionState = exports2.StateCorruptError = exports2.StateNotFoundError = exports2.StateService = exports2.createHookableLogger = exports2.InstrumentedProfileProviderFactory = exports2.InstrumentedLLMProvider = exports2.ServiceFactoryImpl = exports2.TranscriptServiceImpl = exports2.createDefaultTokenUsage = exports2.createDefaultMetrics = exports2.copyWithTimestampSync = exports2.renameWithTimestampSync = exports2.renameWithTimestamp = exports2.copyWithTimestamp = exports2.getTimestampedPath = exports2.extractToolResultPreview = exports2.extractToolCallPreview = exports2.extractTextFromContent = exports2.extractContentPreview = exports2.HandlerRegistryImpl = exports2.extractConsumedTimestamp = exports2.createConsumedFilePattern = exports2.CONSUMED_FILE_PATTERN = exports2.filterActiveReminderFiles = exports2.validatePathSegment = exports2.isValidPathSegment = exports2.getReminderPath = exports2.getHookDir = exports2.getStagingRoot = exports2.SessionScopedStagingService = exports2.StagingServiceCore = exports2.GITIGNORE_ENTRIES = exports2.SIDEKICK_SECTION_END = void 0;
63150
63402
  var types_1 = require_dist();
63151
63403
  Object.defineProperty(exports2, "TaskTypes", { enumerable: true, get: function() {
63152
63404
  return types_1.TaskTypes;
@@ -63213,6 +63465,7 @@ var require_dist4 = __commonJS({
63213
63465
  return persona_loader_1.loadPersonaFile;
63214
63466
  } });
63215
63467
  __exportStar(require_config2(), exports2);
63468
+ __exportStar(require_config_writer(), exports2);
63216
63469
  __exportStar(require_feature_registry(), exports2);
63217
63470
  __exportStar(require_feature_types(), exports2);
63218
63471
  __exportStar(require_client(), exports2);
@@ -63473,6 +63726,10 @@ var require_dist4 = __commonJS({
63473
63726
  Object.defineProperty(exports2, "parseGitStatusOutput", { enumerable: true, get: function() {
63474
63727
  return git_status_1.parseGitStatusOutput;
63475
63728
  } });
63729
+ var user_profile_loader_1 = require_user_profile_loader();
63730
+ Object.defineProperty(exports2, "loadUserProfile", { enumerable: true, get: function() {
63731
+ return user_profile_loader_1.loadUserProfile;
63732
+ } });
63476
63733
  }
63477
63734
  });
63478
63735
 
@@ -70879,7 +71136,8 @@ var require_types2 = __commonJS({
70879
71136
  PAUSE_AND_REFLECT: "pause-and-reflect",
70880
71137
  VERIFY_COMPLETION: "verify-completion",
70881
71138
  REMEMBER_YOUR_PERSONA: "remember-your-persona",
70882
- PERSONA_CHANGED: "persona-changed"
71139
+ PERSONA_CHANGED: "persona-changed",
71140
+ USER_PROFILE: "user-profile"
70883
71141
  };
70884
71142
  }
70885
71143
  });
@@ -72965,6 +73223,66 @@ var require_stage_persona_reminders = __commonJS({
72965
73223
  }
72966
73224
  });
72967
73225
 
73226
+ // ../feature-reminders/dist/handlers/staging/stage-user-profile-reminders.js
73227
+ var require_stage_user_profile_reminders = __commonJS({
73228
+ "../feature-reminders/dist/handlers/staging/stage-user-profile-reminders.js"(exports2) {
73229
+ "use strict";
73230
+ Object.defineProperty(exports2, "__esModule", { value: true });
73231
+ exports2.stageUserProfileRemindersForSession = stageUserProfileRemindersForSession;
73232
+ exports2.registerStageUserProfileReminders = registerStageUserProfileReminders;
73233
+ var core_1 = require_dist4();
73234
+ var types_1 = require_dist();
73235
+ var reminder_utils_js_1 = require_reminder_utils();
73236
+ var types_js_1 = require_types2();
73237
+ var USER_PROFILE_REMINDER_HOOKS = ["UserPromptSubmit", "SessionStart"];
73238
+ async function stageUserProfileRemindersForSession(ctx, sessionId) {
73239
+ const profile = (0, core_1.loadUserProfile)({ logger: ctx.logger });
73240
+ if (!profile) {
73241
+ for (const hook of USER_PROFILE_REMINDER_HOOKS) {
73242
+ await ctx.staging.deleteReminder(hook, types_js_1.ReminderIds.USER_PROFILE);
73243
+ }
73244
+ return;
73245
+ }
73246
+ const templateContext = {
73247
+ user_name: profile.name,
73248
+ user_role: profile.role,
73249
+ user_interests: profile.interests.join(", ")
73250
+ };
73251
+ const reminder = (0, reminder_utils_js_1.resolveReminder)(types_js_1.ReminderIds.USER_PROFILE, {
73252
+ context: templateContext,
73253
+ assets: ctx.assets
73254
+ });
73255
+ if (reminder) {
73256
+ for (const targetHook of USER_PROFILE_REMINDER_HOOKS) {
73257
+ await (0, reminder_utils_js_1.stageReminder)(ctx, targetHook, reminder);
73258
+ }
73259
+ ctx.logger.debug("Staged user profile reminders", { sessionId, userName: profile.name });
73260
+ } else {
73261
+ ctx.logger.warn("Failed to resolve user-profile reminder", { sessionId });
73262
+ }
73263
+ }
73264
+ function registerStageUserProfileReminders(context) {
73265
+ if (!(0, types_1.isDaemonContext)(context))
73266
+ return;
73267
+ context.handlers.register({
73268
+ id: "reminders:stage-user-profile-reminders",
73269
+ priority: 39,
73270
+ // Run after persona reminders (priority 40)
73271
+ filter: { kind: "hook", hooks: ["SessionStart"] },
73272
+ handler: async (event, ctx) => {
73273
+ if (!(0, types_1.isDaemonContext)(ctx))
73274
+ return;
73275
+ if (!(0, types_1.isHookEvent)(event) || !(0, types_1.isSessionStartEvent)(event))
73276
+ return;
73277
+ const daemonCtx = ctx;
73278
+ const sessionId = event.context.sessionId;
73279
+ await stageUserProfileRemindersForSession(daemonCtx, sessionId);
73280
+ }
73281
+ });
73282
+ }
73283
+ }
73284
+ });
73285
+
72968
73286
  // ../feature-reminders/dist/handlers/staging/index.js
72969
73287
  var require_staging2 = __commonJS({
72970
73288
  "../feature-reminders/dist/handlers/staging/index.js"(exports2) {
@@ -72977,6 +73295,7 @@ var require_staging2 = __commonJS({
72977
73295
  var stage_stop_bash_changes_1 = require_stage_stop_bash_changes();
72978
73296
  var unstage_verify_completion_1 = require_unstage_verify_completion();
72979
73297
  var stage_persona_reminders_1 = require_stage_persona_reminders();
73298
+ var stage_user_profile_reminders_1 = require_stage_user_profile_reminders();
72980
73299
  function registerStagingHandlers(context) {
72981
73300
  (0, stage_default_user_prompt_1.registerStageDefaultUserPrompt)(context);
72982
73301
  (0, stage_pause_and_reflect_1.registerStagePauseAndReflect)(context);
@@ -72984,6 +73303,7 @@ var require_staging2 = __commonJS({
72984
73303
  (0, stage_stop_bash_changes_1.registerStageBashChanges)(context);
72985
73304
  (0, unstage_verify_completion_1.registerUnstageVerifyCompletion)(context);
72986
73305
  (0, stage_persona_reminders_1.registerStagePersonaReminders)(context);
73306
+ (0, stage_user_profile_reminders_1.registerStageUserProfileReminders)(context);
72987
73307
  }
72988
73308
  }
72989
73309
  });
@@ -74296,11 +74616,11 @@ var require_hook_command = __commonJS({
74296
74616
  }
74297
74617
  var DEGRADED_MODE_MESSAGES = {
74298
74618
  "not-run": {
74299
- additionalContext: `Sidekick plugin detected but not configured. Features like reminders, personas, and statusline are unavailable until setup is complete. If you haven't already, ask the user if you should execute the sidekick-config skill.`,
74619
+ additionalContext: `Sidekick plugin detected but not configured. Features like reminders, personas, and statusline are unavailable until setup is complete. If you haven't already, ask the user if you should execute the sidekick-setup skill.`,
74300
74620
  userMessage: `Sidekick is installed but not configured. Run 'sidekick setup' to configure.`
74301
74621
  },
74302
74622
  partial: {
74303
- additionalContext: `Sidekick user setup is complete but this project is not configured. Features like reminders, personas, and statusline are unavailable until project setup is complete. If you haven't already, ask the user if you should execute the sidekick-config skill.`,
74623
+ additionalContext: `Sidekick user setup is complete but this project is not configured. Features like reminders, personas, and statusline are unavailable until project setup is complete. If you haven't already, ask the user if you should execute the sidekick-setup skill.`,
74304
74624
  userMessage: `Sidekick project setup incomplete. Run 'sidekick setup' in this project to configure.`
74305
74625
  },
74306
74626
  unhealthy: {
@@ -74889,7 +75209,10 @@ var require_types4 = __commonJS({
74889
75209
  allowList: "",
74890
75210
  blockList: "disabled",
74891
75211
  resumeFreshnessHours: 4,
74892
- injectPersonaIntoClaude: true
75212
+ injectPersonaIntoClaude: true,
75213
+ defaultLlmProfile: "",
75214
+ llmProfiles: {},
75215
+ weights: {}
74893
75216
  }
74894
75217
  };
74895
75218
  exports2.RESUME_MIN_CONFIDENCE = 0.7;
@@ -74941,12 +75264,28 @@ var require_persona_selection = __commonJS({
74941
75264
  }
74942
75265
  return result;
74943
75266
  }
74944
- function selectRandomPersona(personas) {
75267
+ function selectRandomPersona(personas, weights) {
74945
75268
  if (personas.length === 0) {
74946
75269
  return null;
74947
75270
  }
74948
- const index = Math.floor(Math.random() * personas.length);
74949
- return personas[index];
75271
+ const weighted = personas.map((p) => {
75272
+ const raw = weights?.[p.id];
75273
+ const weight = raw === void 0 ? 1 : Number(raw);
75274
+ return { persona: p, weight };
75275
+ }).filter((entry) => Number.isFinite(entry.weight) && entry.weight > 0);
75276
+ if (weighted.length === 0) {
75277
+ return null;
75278
+ }
75279
+ const totalWeight = weighted.reduce((sum, entry) => sum + entry.weight, 0);
75280
+ const threshold = Math.random() * totalWeight;
75281
+ let accumulated = 0;
75282
+ for (const entry of weighted) {
75283
+ accumulated += entry.weight;
75284
+ if (accumulated > threshold) {
75285
+ return entry.persona;
75286
+ }
75287
+ }
75288
+ return weighted[weighted.length - 1].persona;
74950
75289
  }
74951
75290
  async function selectPersonaForSession(sessionId, config, ctx) {
74952
75291
  const personaConfig = {
@@ -74975,7 +75314,15 @@ var require_persona_selection = __commonJS({
74975
75314
  });
74976
75315
  return null;
74977
75316
  }
74978
- const selected = selectRandomPersona(eligiblePersonas);
75317
+ const selected = selectRandomPersona(eligiblePersonas, personaConfig.weights);
75318
+ if (!selected) {
75319
+ ctx.logger.warn("No eligible personas after applying weights", {
75320
+ sessionId,
75321
+ weights: personaConfig.weights,
75322
+ eligibleCount: eligiblePersonas.length
75323
+ });
75324
+ return null;
75325
+ }
74979
75326
  const personaState = {
74980
75327
  persona_id: selected.id,
74981
75328
  selected_from: eligiblePersonas.map((p) => p.id),
@@ -75107,12 +75454,37 @@ var require_persona_utils = __commonJS({
75107
75454
  "../feature-session-summary/dist/handlers/persona-utils.js"(exports2) {
75108
75455
  "use strict";
75109
75456
  Object.defineProperty(exports2, "__esModule", { value: true });
75457
+ exports2.buildUserProfileContext = buildUserProfileContext;
75458
+ exports2.loadUserProfileContext = loadUserProfileContext;
75110
75459
  exports2.buildPersonaContext = buildPersonaContext;
75111
75460
  exports2.stripSurroundingQuotes = stripSurroundingQuotes;
75112
75461
  exports2.loadSessionPersona = loadSessionPersona;
75462
+ exports2.resolvePersonaLlmProfile = resolvePersonaLlmProfile;
75463
+ exports2._resetProfileWarningState = _resetProfileWarningState;
75464
+ exports2.validatePersonaLlmProfile = validatePersonaLlmProfile;
75465
+ exports2.mergePersonaConfig = mergePersonaConfig;
75466
+ exports2.getEffectiveProfile = getEffectiveProfile;
75113
75467
  var core_1 = require_dist4();
75114
75468
  var state_js_1 = require_state4();
75469
+ var types_js_1 = require_types4();
75115
75470
  var DEFAULT_PERSONA_SITUATION = "You are watching over the shoulder of a software developer as they work.";
75471
+ function buildUserProfileContext(profile) {
75472
+ if (!profile) {
75473
+ return {
75474
+ user_name: "",
75475
+ user_role: "",
75476
+ user_interests: ""
75477
+ };
75478
+ }
75479
+ return {
75480
+ user_name: profile.name,
75481
+ user_role: profile.role,
75482
+ user_interests: profile.interests.join(", ")
75483
+ };
75484
+ }
75485
+ function loadUserProfileContext(logger) {
75486
+ return buildUserProfileContext((0, core_1.loadUserProfile)({ logger }));
75487
+ }
75116
75488
  function formatExamples(examples) {
75117
75489
  if (!examples || examples.length === 0)
75118
75490
  return "";
@@ -75166,6 +75538,60 @@ var require_persona_utils = __commonJS({
75166
75538
  const personas = loader.discover();
75167
75539
  return personas.get(result.data.persona_id) ?? null;
75168
75540
  }
75541
+ function resolvePersonaLlmProfile(personaId, personaDef, personaConfig) {
75542
+ const perPersona = personaConfig.llmProfiles?.[personaId];
75543
+ if (perPersona)
75544
+ return perPersona;
75545
+ if (personaDef?.llmProfile)
75546
+ return personaDef.llmProfile;
75547
+ if (personaConfig.defaultLlmProfile)
75548
+ return personaConfig.defaultLlmProfile;
75549
+ return void 0;
75550
+ }
75551
+ var _warnedProfiles = /* @__PURE__ */ new Set();
75552
+ var _erroredDefaults = /* @__PURE__ */ new Set();
75553
+ function _resetProfileWarningState() {
75554
+ _warnedProfiles.clear();
75555
+ _erroredDefaults.clear();
75556
+ }
75557
+ function validatePersonaLlmProfile(resolvedProfile, personaId, featureProfile, availableProfiles, isFromDefault, logger) {
75558
+ if (resolvedProfile in availableProfiles) {
75559
+ return { profileId: resolvedProfile };
75560
+ }
75561
+ if (isFromDefault) {
75562
+ if (!_erroredDefaults.has(resolvedProfile)) {
75563
+ _erroredDefaults.add(resolvedProfile);
75564
+ logger.error("Invalid defaultLlmProfile in persona config", {
75565
+ profileId: resolvedProfile,
75566
+ personaId,
75567
+ availableProfiles: Object.keys(availableProfiles)
75568
+ });
75569
+ }
75570
+ return { errorMessage: `Persona ${personaId}'s profile ${resolvedProfile} is not recognized` };
75571
+ }
75572
+ if (!_warnedProfiles.has(resolvedProfile)) {
75573
+ _warnedProfiles.add(resolvedProfile);
75574
+ logger.warn("Persona LLM profile not found, falling back to feature profile", {
75575
+ resolvedProfile,
75576
+ personaId,
75577
+ fallbackProfile: featureProfile,
75578
+ availableProfiles: Object.keys(availableProfiles)
75579
+ });
75580
+ }
75581
+ return { profileId: featureProfile };
75582
+ }
75583
+ function mergePersonaConfig(config) {
75584
+ return { ...types_js_1.DEFAULT_SESSION_SUMMARY_CONFIG.personas, ...config.personas };
75585
+ }
75586
+ function getEffectiveProfile(persona, llmConfig, config, availableProfiles, logger) {
75587
+ const personaId = persona?.id ?? "";
75588
+ const personaConfig = mergePersonaConfig(config);
75589
+ const resolvedProfile = resolvePersonaLlmProfile(personaId, persona, personaConfig);
75590
+ if (!resolvedProfile) {
75591
+ return { profileId: llmConfig.profile };
75592
+ }
75593
+ return validatePersonaLlmProfile(resolvedProfile, personaId, llmConfig.profile, availableProfiles, resolvedProfile === personaConfig.defaultLlmProfile, logger);
75594
+ }
75169
75595
  }
75170
75596
  });
75171
75597
 
@@ -75467,8 +75893,10 @@ var require_update_summary = __commonJS({
75467
75893
  return;
75468
75894
  }
75469
75895
  const personaContext = (0, persona_utils_js_1.buildPersonaContext)(persona);
75896
+ const userProfileContext = (0, persona_utils_js_1.loadUserProfileContext)(ctx.logger);
75470
75897
  const prompt = interpolateTemplate(promptTemplate, {
75471
75898
  ...personaContext,
75899
+ ...userProfileContext,
75472
75900
  session_title: summary.session_title,
75473
75901
  latest_intent: summary.latest_intent,
75474
75902
  turn_count: ctx.transcript.getMetrics().turnCount,
@@ -75477,7 +75905,16 @@ var require_update_summary = __commonJS({
75477
75905
  maxSnarkyWords: config.maxSnarkyWords
75478
75906
  });
75479
75907
  const llmConfig = config.llm?.snarkyComment ?? types_js_1.DEFAULT_SESSION_SUMMARY_CONFIG.llm.snarkyComment;
75480
- const provider = ctx.profileFactory.createForProfile(llmConfig.profile, llmConfig.fallbackProfile);
75908
+ const profileResult = (0, persona_utils_js_1.getEffectiveProfile)(persona, llmConfig, config, ctx.config.llm.profiles, ctx.logger);
75909
+ if ("errorMessage" in profileResult) {
75910
+ const snarkyState = {
75911
+ message: profileResult.errorMessage,
75912
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
75913
+ };
75914
+ await summaryState.snarkyMessage.write(sessionId, snarkyState);
75915
+ return;
75916
+ }
75917
+ const provider = ctx.profileFactory.createForProfile(profileResult.profileId, llmConfig.fallbackProfile);
75481
75918
  try {
75482
75919
  const response = await provider.complete({
75483
75920
  messages: [{ role: "user", content: prompt }]
@@ -75514,7 +75951,9 @@ var require_update_summary = __commonJS({
75514
75951
  last_task_id: null,
75515
75952
  session_title: summary.session_title,
75516
75953
  snarky_comment: summary.latest_intent,
75517
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
75954
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
75955
+ persona_id: null,
75956
+ persona_display_name: null
75518
75957
  };
75519
75958
  await summaryState.resumeMessage.write(sessionId, resumeState);
75520
75959
  (0, core_1.logEvent)(ctx.logger, core_1.LogEvents.resumeUpdated({ sessionId }, {
@@ -75533,9 +75972,11 @@ var require_update_summary = __commonJS({
75533
75972
  intent_confidence: summary.latest_intent_confidence
75534
75973
  }));
75535
75974
  const personaContext = (0, persona_utils_js_1.buildPersonaContext)(persona);
75975
+ const userProfileContext = (0, persona_utils_js_1.loadUserProfileContext)(ctx.logger);
75536
75976
  const keyPhrases = summary.session_title_key_phrases?.join(", ") ?? "";
75537
75977
  const prompt = interpolateTemplate(promptTemplate, {
75538
75978
  ...personaContext,
75979
+ ...userProfileContext,
75539
75980
  sessionTitle: summary.session_title,
75540
75981
  confidence: summary.session_title_confidence,
75541
75982
  latestIntent: summary.latest_intent,
@@ -75544,7 +75985,15 @@ var require_update_summary = __commonJS({
75544
75985
  maxResumeWords: config.maxResumeWords
75545
75986
  });
75546
75987
  const llmConfig = config.llm?.resumeMessage ?? types_js_1.DEFAULT_SESSION_SUMMARY_CONFIG.llm.resumeMessage;
75547
- const provider = ctx.profileFactory.createForProfile(llmConfig.profile, llmConfig.fallbackProfile);
75988
+ const profileResult = (0, persona_utils_js_1.getEffectiveProfile)(persona, llmConfig, config, ctx.config.llm.profiles, ctx.logger);
75989
+ if ("errorMessage" in profileResult) {
75990
+ ctx.logger.error("Skipping resume generation due to invalid persona profile", {
75991
+ sessionId,
75992
+ errorMessage: profileResult.errorMessage
75993
+ });
75994
+ return;
75995
+ }
75996
+ const provider = ctx.profileFactory.createForProfile(profileResult.profileId, llmConfig.fallbackProfile);
75548
75997
  try {
75549
75998
  const response = await provider.complete({
75550
75999
  messages: [{ role: "user", content: prompt }]
@@ -75555,7 +76004,9 @@ var require_update_summary = __commonJS({
75555
76004
  // Not tracked in summary
75556
76005
  session_title: summary.session_title,
75557
76006
  snarky_comment: snarkyWelcome,
75558
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
76007
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
76008
+ persona_id: persona?.id ?? null,
76009
+ persona_display_name: persona?.display_name ?? null
75559
76010
  };
75560
76011
  await summaryState.resumeMessage.write(sessionId, resumeState);
75561
76012
  (0, core_1.logEvent)(ctx.logger, core_1.LogEvents.resumeUpdated({ sessionId }, {
@@ -75641,10 +76092,12 @@ var require_on_demand_generation = __commonJS({
75641
76092
  };
75642
76093
  }
75643
76094
  const personaContext = (0, persona_utils_js_1.buildPersonaContext)(persona);
76095
+ const userProfileContext = (0, persona_utils_js_1.loadUserProfileContext)(ctx.logger);
75644
76096
  const featureConfig = ctx.config.getFeature("session-summary");
75645
76097
  const config = { ...types_js_1.DEFAULT_SESSION_SUMMARY_CONFIG, ...featureConfig.settings };
75646
76098
  const prompt = (0, update_summary_js_1.interpolateTemplate)(promptTemplate, {
75647
76099
  ...personaContext,
76100
+ ...userProfileContext,
75648
76101
  session_title: summary.session_title,
75649
76102
  latest_intent: summary.latest_intent,
75650
76103
  turn_count: ctx.transcript.getMetrics().turnCount,
@@ -75653,7 +76106,11 @@ var require_on_demand_generation = __commonJS({
75653
76106
  maxSnarkyWords: config.maxSnarkyWords
75654
76107
  });
75655
76108
  const llmConfig = config.llm?.snarkyComment ?? types_js_1.DEFAULT_SESSION_SUMMARY_CONFIG.llm.snarkyComment;
75656
- const provider = ctx.profileFactory.createForProfile(llmConfig.profile, llmConfig.fallbackProfile);
76109
+ const profileResult = (0, persona_utils_js_1.getEffectiveProfile)(persona, llmConfig, config, ctx.config.llm.profiles, ctx.logger);
76110
+ if ("errorMessage" in profileResult) {
76111
+ return { success: false, error: profileResult.errorMessage };
76112
+ }
76113
+ const provider = ctx.profileFactory.createForProfile(profileResult.profileId, llmConfig.fallbackProfile);
75657
76114
  try {
75658
76115
  const response = await provider.complete({
75659
76116
  messages: [{ role: "user", content: prompt }]
@@ -75700,7 +76157,9 @@ var require_on_demand_generation = __commonJS({
75700
76157
  last_task_id: null,
75701
76158
  session_title: summary.session_title,
75702
76159
  snarky_comment: summary.latest_intent,
75703
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
76160
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
76161
+ persona_id: null,
76162
+ persona_display_name: null
75704
76163
  };
75705
76164
  await summaryState.resumeMessage.write(sessionId, resumeState);
75706
76165
  ctx.logger.info("Generated deterministic resume message (disabled persona)", { sessionId });
@@ -75714,6 +76173,7 @@ var require_on_demand_generation = __commonJS({
75714
76173
  };
75715
76174
  }
75716
76175
  const personaContext = (0, persona_utils_js_1.buildPersonaContext)(persona);
76176
+ const userProfileContext = (0, persona_utils_js_1.loadUserProfileContext)(ctx.logger);
75717
76177
  const featureConfig = ctx.config.getFeature("session-summary");
75718
76178
  const config = { ...types_js_1.DEFAULT_SESSION_SUMMARY_CONFIG, ...featureConfig.settings };
75719
76179
  const excerpt = ctx.transcript.getExcerpt({
@@ -75725,6 +76185,7 @@ var require_on_demand_generation = __commonJS({
75725
76185
  const keyPhrases = summary.session_title_key_phrases?.join(", ") ?? "";
75726
76186
  const prompt = (0, update_summary_js_1.interpolateTemplate)(promptTemplate, {
75727
76187
  ...personaContext,
76188
+ ...userProfileContext,
75728
76189
  sessionTitle: summary.session_title,
75729
76190
  confidence: summary.session_title_confidence,
75730
76191
  latestIntent: summary.latest_intent,
@@ -75733,7 +76194,11 @@ var require_on_demand_generation = __commonJS({
75733
76194
  maxResumeWords: config.maxResumeWords
75734
76195
  });
75735
76196
  const llmConfig = config.llm?.resumeMessage ?? types_js_1.DEFAULT_SESSION_SUMMARY_CONFIG.llm.resumeMessage;
75736
- const provider = ctx.profileFactory.createForProfile(llmConfig.profile, llmConfig.fallbackProfile);
76197
+ const profileResult = (0, persona_utils_js_1.getEffectiveProfile)(persona, llmConfig, config, ctx.config.llm.profiles, ctx.logger);
76198
+ if ("errorMessage" in profileResult) {
76199
+ return { success: false, error: profileResult.errorMessage };
76200
+ }
76201
+ const provider = ctx.profileFactory.createForProfile(profileResult.profileId, llmConfig.fallbackProfile);
75737
76202
  try {
75738
76203
  const response = await provider.complete({
75739
76204
  messages: [{ role: "user", content: prompt }]
@@ -75743,7 +76208,9 @@ var require_on_demand_generation = __commonJS({
75743
76208
  last_task_id: null,
75744
76209
  session_title: summary.session_title,
75745
76210
  snarky_comment: snarkyWelcome,
75746
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
76211
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
76212
+ persona_id: persona?.id ?? null,
76213
+ persona_display_name: persona?.display_name ?? null
75747
76214
  };
75748
76215
  await summaryState.resumeMessage.write(sessionId, resumeState);
75749
76216
  ctx.logger.info("Generated resume message on-demand", {
@@ -76855,7 +77322,7 @@ var require_statusline_service = __commonJS({
76855
77322
  const keyHealth = await this.setupService.getEffectiveApiKeyHealth(keyName);
76856
77323
  if (keyHealth === "missing") {
76857
77324
  return {
76858
- warning: `${keyName} not found. Run 'sidekick doctor' or /sidekick-config`,
77325
+ warning: `${keyName} not found. Run 'sidekick doctor' or /sidekick-setup`,
76859
77326
  state
76860
77327
  };
76861
77328
  }
@@ -77032,7 +77499,7 @@ var require_statusline_service = __commonJS({
77032
77499
  */
77033
77500
  buildViewModel(state, summary, resume, snarkyMessage, branch, baseline, logMetrics, emptySessionMessage, persona) {
77034
77501
  const displayMode = this.determineDisplayMode(summary, resume);
77035
- const { summaryText, title } = this.getSummaryContent(displayMode, summary, resume, snarkyMessage, emptySessionMessage);
77502
+ const { summaryText, title } = this.getSummaryContent(displayMode, summary, resume, snarkyMessage, emptySessionMessage, persona);
77036
77503
  const isIndeterminate = state.isPostCompactIndeterminate === true;
77037
77504
  let effectiveTokens;
77038
77505
  let usingBaseline = false;
@@ -77143,11 +77610,15 @@ var require_statusline_service = __commonJS({
77143
77610
  /**
77144
77611
  * Get summary content based on display mode.
77145
77612
  */
77146
- getSummaryContent(displayMode, summary, resume, snarkyMessage, emptySessionMessage) {
77613
+ getSummaryContent(displayMode, summary, resume, snarkyMessage, emptySessionMessage, persona) {
77147
77614
  switch (displayMode) {
77148
77615
  case "resume_message": {
77149
77616
  const resumeTitle = resume?.session_title ? `Last Session: ${resume.session_title}` : types_js_1.DEFAULT_PLACEHOLDERS.newSession;
77150
- const resumeSummary = resume?.snarky_comment || emptySessionMessage;
77617
+ let resumeSummary = resume?.snarky_comment || emptySessionMessage;
77618
+ const isPersonaDisabled = persona?.id === "disabled";
77619
+ if (resume?.persona_id && resume.persona_display_name && !isPersonaDisabled && resume.persona_id !== persona?.id) {
77620
+ resumeSummary = `${resume.persona_display_name}: ${resumeSummary}`;
77621
+ }
77151
77622
  return {
77152
77623
  summaryText: resumeSummary,
77153
77624
  title: resumeTitle
@@ -78008,6 +78479,200 @@ Examples:
78008
78479
  }
78009
78480
  });
78010
78481
 
78482
+ // ../sidekick-cli/dist/commands/config.js
78483
+ var require_config3 = __commonJS({
78484
+ "../sidekick-cli/dist/commands/config.js"(exports2) {
78485
+ "use strict";
78486
+ Object.defineProperty(exports2, "__esModule", { value: true });
78487
+ exports2.handleConfigCommand = handleConfigCommand;
78488
+ var core_1 = require_dist4();
78489
+ function handleGet(args, projectRoot, logger, stdout, options) {
78490
+ const dotPath = args[0];
78491
+ if (!dotPath) {
78492
+ const error = "Error: config get requires a dot-path argument";
78493
+ stdout.write(error + "\n");
78494
+ stdout.write("Usage: sidekick config get <path> [--scope=user|project|local]\n");
78495
+ return { exitCode: 1, output: error };
78496
+ }
78497
+ logger.debug("Config get", { dotPath, scope: options.scope });
78498
+ let result;
78499
+ try {
78500
+ result = (0, core_1.configGet)(String(dotPath), {
78501
+ scope: options.scope,
78502
+ projectRoot,
78503
+ assets: options.assets,
78504
+ logger
78505
+ });
78506
+ } catch (err) {
78507
+ const message = err instanceof Error ? err.message : String(err);
78508
+ const error = `Error: ${message}`;
78509
+ stdout.write(error + "\n");
78510
+ return { exitCode: 1, output: error };
78511
+ }
78512
+ if (result === void 0) {
78513
+ const error = `No value found for "${dotPath}"`;
78514
+ stdout.write(error + "\n");
78515
+ return { exitCode: 1, output: error };
78516
+ }
78517
+ const { value } = result;
78518
+ if (options.format === "json") {
78519
+ const output2 = JSON.stringify(value, null, 2);
78520
+ stdout.write(output2 + "\n");
78521
+ return { exitCode: 0, output: output2 };
78522
+ }
78523
+ if (value !== null && typeof value === "object") {
78524
+ const output2 = JSON.stringify(value, null, 2);
78525
+ stdout.write(output2 + "\n");
78526
+ return { exitCode: 0, output: output2 };
78527
+ }
78528
+ const output = String(value);
78529
+ stdout.write(output + "\n");
78530
+ return { exitCode: 0, output };
78531
+ }
78532
+ function handleSet(args, projectRoot, logger, stdout, options) {
78533
+ const dotPath = args[0];
78534
+ const rawValue = args[1];
78535
+ if (!dotPath || rawValue === void 0) {
78536
+ const error = "Error: config set requires a dot-path and a value";
78537
+ stdout.write(error + "\n");
78538
+ stdout.write("Usage: sidekick config set <path> <value> [--scope=user|project|local]\n");
78539
+ return { exitCode: 1, output: error };
78540
+ }
78541
+ logger.debug("Config set", { dotPath, rawValue, scope: options.scope });
78542
+ try {
78543
+ const result = (0, core_1.configSet)(String(dotPath), String(rawValue), {
78544
+ scope: options.scope,
78545
+ projectRoot,
78546
+ assets: options.assets,
78547
+ logger
78548
+ });
78549
+ const output = `Set ${dotPath} = ${JSON.stringify(result.value)} (in ${result.filePath})`;
78550
+ stdout.write(output + "\n");
78551
+ return { exitCode: 0, output };
78552
+ } catch (err) {
78553
+ const message = err instanceof Error ? err.message : String(err);
78554
+ const error = `Error: ${message}`;
78555
+ stdout.write(error + "\n");
78556
+ return { exitCode: 1, output: error };
78557
+ }
78558
+ }
78559
+ function handleUnset(args, projectRoot, logger, stdout, options) {
78560
+ const dotPath = args[0];
78561
+ if (!dotPath) {
78562
+ const error = "Error: config unset requires a dot-path argument";
78563
+ stdout.write(error + "\n");
78564
+ stdout.write("Usage: sidekick config unset <path> [--scope=user|project|local]\n");
78565
+ return { exitCode: 1, output: error };
78566
+ }
78567
+ logger.debug("Config unset", { dotPath, scope: options.scope });
78568
+ try {
78569
+ const result = (0, core_1.configUnset)(String(dotPath), {
78570
+ scope: options.scope,
78571
+ projectRoot
78572
+ });
78573
+ if (result.existed) {
78574
+ const output2 = `Unset ${dotPath} (from ${result.filePath})`;
78575
+ stdout.write(output2 + "\n");
78576
+ return { exitCode: 0, output: output2 };
78577
+ }
78578
+ const output = `Key "${dotPath}" was not set`;
78579
+ stdout.write(output + "\n");
78580
+ return { exitCode: 0, output };
78581
+ } catch (err) {
78582
+ const message = err instanceof Error ? err.message : String(err);
78583
+ const error = `Error: ${message}`;
78584
+ stdout.write(error + "\n");
78585
+ return { exitCode: 1, output: error };
78586
+ }
78587
+ }
78588
+ function handleList(projectRoot, logger, stdout, options) {
78589
+ const scope = options.scope ?? "project";
78590
+ logger.debug("Config list", { scope });
78591
+ try {
78592
+ const result = (0, core_1.configList)({
78593
+ scope,
78594
+ projectRoot
78595
+ });
78596
+ if (result.entries.length === 0) {
78597
+ const output2 = `No overrides at ${scope} scope`;
78598
+ stdout.write(output2 + "\n");
78599
+ return { exitCode: 0, output: output2 };
78600
+ }
78601
+ if (options.format === "json") {
78602
+ const output2 = JSON.stringify(result.entries, null, 2);
78603
+ stdout.write(output2 + "\n");
78604
+ return { exitCode: 0, output: output2 };
78605
+ }
78606
+ const lines = result.entries.map((e) => `${e.path} = ${JSON.stringify(e.value)}`);
78607
+ const output = lines.join("\n");
78608
+ stdout.write(output + "\n");
78609
+ return { exitCode: 0, output };
78610
+ } catch (err) {
78611
+ const message = err instanceof Error ? err.message : String(err);
78612
+ const error = `Error: ${message}`;
78613
+ stdout.write(error + "\n");
78614
+ return { exitCode: 1, output: error };
78615
+ }
78616
+ }
78617
+ function showConfigHelp(stdout) {
78618
+ const helpText = `Usage: sidekick config <subcommand> [options]
78619
+
78620
+ Subcommands:
78621
+ get <path> Read a config value by dot-path
78622
+ set <path> <value> Write a config value to a scope file
78623
+ unset <path> Remove a config override from a scope file
78624
+ list List all overrides at a scope
78625
+
78626
+ Options:
78627
+ --scope=<scope> Scope: user, project (default), or local
78628
+ --format=<format> Output format: text (default) or json
78629
+
78630
+ Dot-path format:
78631
+ <domain>.<key>[.<subkey>...]
78632
+ Domains: core, llm, transcript, features
78633
+
78634
+ Examples:
78635
+ sidekick config get core.logging.level
78636
+ sidekick config get core.logging.level --scope=user
78637
+ sidekick config set core.logging.level debug
78638
+ sidekick config set core.logging.level debug --scope=user
78639
+ sidekick config unset core.logging.level
78640
+ sidekick config list
78641
+ sidekick config list --scope=user
78642
+ sidekick config list --format=json
78643
+ `;
78644
+ stdout.write(helpText);
78645
+ return { exitCode: 0, output: "" };
78646
+ }
78647
+ function handleConfigCommand(subcommand, args, projectRoot, logger, stdout, options) {
78648
+ switch (subcommand) {
78649
+ case "get":
78650
+ return handleGet(args, projectRoot, logger, stdout, options);
78651
+ case "set":
78652
+ return handleSet(args, projectRoot, logger, stdout, options);
78653
+ case "unset":
78654
+ return handleUnset(args, projectRoot, logger, stdout, options);
78655
+ case "list":
78656
+ return handleList(projectRoot, logger, stdout, options);
78657
+ case "help":
78658
+ case "--help":
78659
+ case "-h":
78660
+ return showConfigHelp(stdout);
78661
+ case void 0:
78662
+ stdout.write("Error: config command requires a subcommand\n\n");
78663
+ showConfigHelp(stdout);
78664
+ return { exitCode: 1, output: "" };
78665
+ default:
78666
+ stdout.write(`Error: Unknown config subcommand: ${subcommand}
78667
+
78668
+ `);
78669
+ showConfigHelp(stdout);
78670
+ return { exitCode: 1, output: "" };
78671
+ }
78672
+ }
78673
+ }
78674
+ });
78675
+
78011
78676
  // ../sidekick-cli/dist/commands/sessions.js
78012
78677
  var require_sessions3 = __commonJS({
78013
78678
  "../sidekick-cli/dist/commands/sessions.js"(exports2) {
@@ -78264,28 +78929,40 @@ var require_dev_mode = __commonJS({
78264
78929
  return false;
78265
78930
  }
78266
78931
  }
78267
- async function copySkillForDev(projectDir, stdout) {
78268
- const srcSkillDir = node_path_1.default.join(projectDir, "packages", "sidekick-plugin", "skills", "sidekick-config");
78269
- const destSkillDir = node_path_1.default.join(projectDir, ".claude", "skills", "sidekick-config");
78270
- if (!await fileExists(srcSkillDir)) {
78271
- log(stdout, "warn", `Plugin skill not found at ${srcSkillDir}, skipping skill copy`);
78932
+ async function copySkillsForDev(projectDir, stdout) {
78933
+ const srcSkillsRoot = node_path_1.default.join(projectDir, "packages", "sidekick-plugin", "skills");
78934
+ if (!await fileExists(srcSkillsRoot)) {
78935
+ log(stdout, "warn", `Plugin skills directory not found at ${srcSkillsRoot}, skipping skill copy`);
78272
78936
  return;
78273
78937
  }
78274
- await (0, promises_12.rm)(destSkillDir, { recursive: true, force: true });
78275
- await (0, promises_12.cp)(srcSkillDir, destSkillDir, { recursive: true });
78276
- const skillMdPath = node_path_1.default.join(destSkillDir, "SKILL.md");
78277
- if (await fileExists(skillMdPath)) {
78278
- const content = await (0, promises_12.readFile)(skillMdPath, "utf-8");
78279
- const transformed = content.replace(/npx @scotthamilton77\/sidekick/g, "pnpm sidekick");
78280
- await (0, promises_12.writeFile)(skillMdPath, transformed);
78281
- }
78282
- log(stdout, "info", `Copied sidekick-config skill to ${destSkillDir}`);
78283
- }
78284
- async function removeDevSkill(projectDir, stdout) {
78285
- const destSkillDir = node_path_1.default.join(projectDir, ".claude", "skills", "sidekick-config");
78286
- if (await fileExists(destSkillDir)) {
78287
- await (0, promises_12.rm)(destSkillDir, { recursive: true, force: true });
78288
- log(stdout, "info", `Removed sidekick-config skill from ${destSkillDir}`);
78938
+ const entries = await (0, promises_12.readdir)(srcSkillsRoot, { withFileTypes: true });
78939
+ const skillDirs = entries.filter((e) => e.isDirectory());
78940
+ for (const skillDir of skillDirs) {
78941
+ const srcDir = node_path_1.default.join(srcSkillsRoot, skillDir.name);
78942
+ const destDir = node_path_1.default.join(projectDir, ".claude", "skills", skillDir.name);
78943
+ await (0, promises_12.rm)(destDir, { recursive: true, force: true });
78944
+ await (0, promises_12.cp)(srcDir, destDir, { recursive: true });
78945
+ const skillMdPath = node_path_1.default.join(destDir, "SKILL.md");
78946
+ if (await fileExists(skillMdPath)) {
78947
+ const content = await (0, promises_12.readFile)(skillMdPath, "utf-8");
78948
+ const transformed = content.replace(/npx @scotthamilton77\/sidekick/g, "pnpm sidekick");
78949
+ await (0, promises_12.writeFile)(skillMdPath, transformed);
78950
+ }
78951
+ log(stdout, "info", `Copied ${skillDir.name} skill to ${destDir}`);
78952
+ }
78953
+ }
78954
+ async function removeDevSkills(projectDir, stdout) {
78955
+ const srcSkillsRoot = node_path_1.default.join(projectDir, "packages", "sidekick-plugin", "skills");
78956
+ if (!await fileExists(srcSkillsRoot))
78957
+ return;
78958
+ const entries = await (0, promises_12.readdir)(srcSkillsRoot, { withFileTypes: true });
78959
+ const skillDirs = entries.filter((e) => e.isDirectory());
78960
+ for (const skillDir of skillDirs) {
78961
+ const destDir = node_path_1.default.join(projectDir, ".claude", "skills", skillDir.name);
78962
+ if (await fileExists(destDir)) {
78963
+ await (0, promises_12.rm)(destDir, { recursive: true, force: true });
78964
+ log(stdout, "info", `Removed ${skillDir.name} skill from ${destDir}`);
78965
+ }
78289
78966
  }
78290
78967
  }
78291
78968
  function log(stdout, level, message) {
@@ -78446,7 +79123,7 @@ var require_dev_mode = __commonJS({
78446
79123
  log(stdout, "warn", "Run 'pnpm build' before using dev-mode hooks");
78447
79124
  }
78448
79125
  await (0, promises_12.mkdir)(node_path_1.default.join(projectDir, ".claude"), { recursive: true });
78449
- await copySkillForDev(projectDir, stdout);
79126
+ await copySkillsForDev(projectDir, stdout);
78450
79127
  const gitignoreResult = await (0, core_1.installGitignoreSection)(projectDir);
78451
79128
  if (gitignoreResult.status === "installed") {
78452
79129
  log(stdout, "info", "Installed .gitignore entries for .sidekick/");
@@ -78542,7 +79219,7 @@ var require_dev_mode = __commonJS({
78542
79219
  await (0, promises_12.writeFile)(settingsPath, JSON.stringify(settings, null, 2) + "\n");
78543
79220
  log(stdout, "info", `Dev-mode hooks removed from ${settingsPath}`);
78544
79221
  }
78545
- await removeDevSkill(projectDir, stdout);
79222
+ await removeDevSkills(projectDir, stdout);
78546
79223
  const pluginInstalled = await setupService.isPluginInstalled();
78547
79224
  if (pluginInstalled) {
78548
79225
  log(stdout, "info", "Skipping .gitignore cleanup \u2014 plugin is still installed");
@@ -79321,6 +79998,108 @@ var require_plugin_installer = __commonJS({
79321
79998
  }
79322
79999
  });
79323
80000
 
80001
+ // ../sidekick-cli/dist/commands/setup/user-profile-setup.js
80002
+ var require_user_profile_setup = __commonJS({
80003
+ "../sidekick-cli/dist/commands/setup/user-profile-setup.js"(exports2) {
80004
+ "use strict";
80005
+ var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
80006
+ if (k2 === void 0) k2 = k;
80007
+ var desc = Object.getOwnPropertyDescriptor(m, k);
80008
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
80009
+ desc = { enumerable: true, get: function() {
80010
+ return m[k];
80011
+ } };
80012
+ }
80013
+ Object.defineProperty(o, k2, desc);
80014
+ }) : (function(o, m, k, k2) {
80015
+ if (k2 === void 0) k2 = k;
80016
+ o[k2] = m[k];
80017
+ }));
80018
+ var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
80019
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
80020
+ }) : function(o, v) {
80021
+ o["default"] = v;
80022
+ });
80023
+ var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
80024
+ var ownKeys = function(o) {
80025
+ ownKeys = Object.getOwnPropertyNames || function(o2) {
80026
+ var ar = [];
80027
+ for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
80028
+ return ar;
80029
+ };
80030
+ return ownKeys(o);
80031
+ };
80032
+ return function(mod) {
80033
+ if (mod && mod.__esModule) return mod;
80034
+ var result = {};
80035
+ if (mod != null) {
80036
+ for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
80037
+ }
80038
+ __setModuleDefault(result, mod);
80039
+ return result;
80040
+ };
80041
+ })();
80042
+ Object.defineProperty(exports2, "__esModule", { value: true });
80043
+ exports2.escapeYamlString = escapeYamlString;
80044
+ exports2.serializeProfileYaml = serializeProfileYaml;
80045
+ exports2.runUserProfileStep = runUserProfileStep;
80046
+ var fs = __importStar(require("node:fs/promises"));
80047
+ var path = __importStar(require("node:path"));
80048
+ var core_1 = require_dist4();
80049
+ var prompts_js_1 = require_prompts();
80050
+ function escapeYamlString(value) {
80051
+ return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
80052
+ }
80053
+ function serializeProfileYaml(profile) {
80054
+ const lines = [`name: "${escapeYamlString(profile.name)}"`, `role: "${escapeYamlString(profile.role)}"`];
80055
+ if (profile.interests.length === 0) {
80056
+ lines.push("interests: []");
80057
+ } else {
80058
+ lines.push("interests:");
80059
+ for (const interest of profile.interests) {
80060
+ lines.push(` - "${escapeYamlString(interest)}"`);
80061
+ }
80062
+ }
80063
+ return lines.join("\n") + "\n";
80064
+ }
80065
+ async function runUserProfileStep(ctx, homeDir) {
80066
+ (0, prompts_js_1.printHeader)(ctx, "Step 8: User Profile", "Personas can personalize messages when they know who you are.");
80067
+ const existing = (0, core_1.loadUserProfile)({ homeDir });
80068
+ if (existing) {
80069
+ ctx.stdout.write(` Current profile:
80070
+ `);
80071
+ ctx.stdout.write(` Name: ${existing.name}
80072
+ `);
80073
+ ctx.stdout.write(` Role: ${existing.role}
80074
+ `);
80075
+ ctx.stdout.write(` Interests: ${existing.interests.join(", ")}
80076
+
80077
+ `);
80078
+ const keepIt = await (0, prompts_js_1.promptConfirm)(ctx, "Keep this profile?", true);
80079
+ if (keepIt) {
80080
+ (0, prompts_js_1.printStatus)(ctx, "success", "User profile unchanged");
80081
+ return { configured: true };
80082
+ }
80083
+ }
80084
+ const name = await (0, prompts_js_1.promptInput)(ctx, "Your name:");
80085
+ if (!name.trim()) {
80086
+ (0, prompts_js_1.printStatus)(ctx, "info", "Skipped user profile (no name provided)");
80087
+ return { configured: false };
80088
+ }
80089
+ const role = await (0, prompts_js_1.promptInput)(ctx, "Your role (e.g., Software Architect):");
80090
+ const interestsRaw = await (0, prompts_js_1.promptInput)(ctx, "Interests (comma-separated, e.g., Sci-Fi, hiking):");
80091
+ const interests = interestsRaw.split(",").map((s) => s.trim()).filter(Boolean);
80092
+ const profile = { name: name.trim(), role: role.trim() || "User", interests };
80093
+ const sidekickDir = path.join(homeDir, ".sidekick");
80094
+ await fs.mkdir(sidekickDir, { recursive: true });
80095
+ const filePath = path.join(sidekickDir, "user.yaml");
80096
+ await fs.writeFile(filePath, serializeProfileYaml(profile), "utf-8");
80097
+ (0, prompts_js_1.printStatus)(ctx, "success", `User profile saved to ${filePath}`);
80098
+ return { configured: true };
80099
+ }
80100
+ }
80101
+ });
80102
+
79324
80103
  // ../sidekick-cli/dist/commands/setup/shell-alias.js
79325
80104
  var require_shell_alias = __commonJS({
79326
80105
  "../sidekick-cli/dist/commands/setup/shell-alias.js"(exports2) {
@@ -79476,6 +80255,7 @@ var require_setup = __commonJS({
79476
80255
  var core_1 = require_dist4();
79477
80256
  var prompts_js_1 = require_prompts();
79478
80257
  var plugin_installer_js_1 = require_plugin_installer();
80258
+ var user_profile_setup_js_1 = require_user_profile_setup();
79479
80259
  var shell_alias_js_1 = require_shell_alias();
79480
80260
  var USAGE_TEXT = `Usage: sidekick setup [options]
79481
80261
 
@@ -79502,6 +80282,9 @@ Scripting Flags (for non-interactive/partial setup):
79502
80282
  --auto-config=<mode> Auto-configure preference: auto | manual
79503
80283
  --alias Add 'sidekick' shell alias to ~/.zshrc or ~/.bashrc
79504
80284
  --no-alias Remove 'sidekick' shell alias from shell config
80285
+ --user-profile-name=<name> Set user profile name (creates ~/.sidekick/user.yaml)
80286
+ --user-profile-role=<role> Set user profile role (e.g., "Software Architect")
80287
+ --user-profile-interests=<i> Set user interests (comma-separated)
79505
80288
 
79506
80289
  Examples:
79507
80290
  sidekick setup Interactive wizard
@@ -79511,6 +80294,7 @@ Examples:
79511
80294
  sidekick setup --statusline-scope=user Configure statusline only
79512
80295
  sidekick setup --gitignore --personas Configure gitignore and enable personas
79513
80296
  OPENROUTER_API_KEY=sk-xxx sidekick setup --personas --api-key-scope=user
80297
+ sidekick setup --user-profile-name="Scott" --user-profile-role="Software Architect" --user-profile-interests="Sci-Fi,hiking"
79514
80298
  `;
79515
80299
  var STATUSLINE_COMMAND = "npx @scotthamilton77/sidekick statusline --project-dir=$CLAUDE_PROJECT_DIR";
79516
80300
  function statuslineSettingsPath(scope, homeDir, projectDir) {
@@ -79805,7 +80589,7 @@ Examples:
79805
80589
  if (!configureNow) {
79806
80590
  stdout.write("\n");
79807
80591
  (0, prompts_js_1.printStatus)(ctx, "warning", "LLM features will be limited until an API key is configured.");
79808
- stdout.write("Run 'sidekick setup' again or ask Claude to help configure API keys using /sidekick-config.\n");
80592
+ stdout.write("Run 'sidekick setup' again or ask Claude to help configure API keys using /sidekick-setup.\n");
79809
80593
  return { health: "missing", detection };
79810
80594
  }
79811
80595
  const keyScope = await (0, prompts_js_1.promptSelect)(ctx, "Where should the API key be stored?", [
@@ -79999,6 +80783,7 @@ Examples:
79999
80783
  const forceAutoConfig = pluginResult.pluginScope === "user" ? "auto" : "manual";
80000
80784
  const autoConfig = force ? forceAutoConfig : await runStep6AutoConfig(wctx, pluginResult.pluginScope);
80001
80785
  const shellAlias = force ? "skipped" : await runStep7ShellAlias(wctx);
80786
+ const _userProfile = force ? { configured: false } : await (0, user_profile_setup_js_1.runUserProfileStep)(wctx.ctx, homeDir);
80002
80787
  if (force) {
80003
80788
  const settingsPath = statuslineSettingsPath(forceEffectiveScope, homeDir, projectDir);
80004
80789
  const wrote = await configureStatusline(settingsPath, logger);
@@ -80038,7 +80823,7 @@ Examples:
80038
80823
  return { exitCode: 0 };
80039
80824
  }
80040
80825
  function hasScriptingFlags(options) {
80041
- return options.marketplaceScope !== void 0 || options.pluginScope !== void 0 || options.statuslineScope !== void 0 || options.gitignore !== void 0 || options.personas !== void 0 || options.apiKeyScope !== void 0 || options.autoConfig !== void 0 || options.alias !== void 0;
80826
+ return options.marketplaceScope !== void 0 || options.pluginScope !== void 0 || options.statuslineScope !== void 0 || options.gitignore !== void 0 || options.personas !== void 0 || options.apiKeyScope !== void 0 || options.autoConfig !== void 0 || options.alias !== void 0 || options.userProfileName !== void 0 || options.userProfileRole !== void 0 || options.userProfileInterests !== void 0;
80042
80827
  }
80043
80828
  async function runScripted(projectDir, logger, stdout, options, isDevMode) {
80044
80829
  const homeDir = options.homeDir ?? os.homedir();
@@ -80194,6 +80979,27 @@ Examples:
80194
80979
  configuredCount++;
80195
80980
  }
80196
80981
  }
80982
+ const hasProfileFlags = options.userProfileName || options.userProfileRole || options.userProfileInterests;
80983
+ if (hasProfileFlags) {
80984
+ if (!options.userProfileName) {
80985
+ stdout.write("\u26A0 --user-profile-name is required when using user profile flags\n");
80986
+ } else if (!options.userProfileRole) {
80987
+ stdout.write("\u26A0 --user-profile-role is required when --user-profile-name is provided\n");
80988
+ } else {
80989
+ const profile = {
80990
+ name: options.userProfileName,
80991
+ role: options.userProfileRole,
80992
+ interests: options.userProfileInterests ? options.userProfileInterests.split(",").map((s) => s.trim()).filter(Boolean) : []
80993
+ };
80994
+ const sidekickDir = path.join(homeDir, ".sidekick");
80995
+ await fs.mkdir(sidekickDir, { recursive: true });
80996
+ const filePath = path.join(sidekickDir, "user.yaml");
80997
+ await fs.writeFile(filePath, (0, user_profile_setup_js_1.serializeProfileYaml)(profile), "utf-8");
80998
+ stdout.write(`\u2713 User profile saved to ${filePath}
80999
+ `);
81000
+ configuredCount++;
81001
+ }
81002
+ }
80197
81003
  if (configuredCount > 0) {
80198
81004
  const existingProject = await setupService.getProjectStatus();
80199
81005
  const projectStatus = {
@@ -80353,7 +81159,7 @@ Configured ${configuredCount} setting${configuredCount === 1 ? "" : "s"}.
80353
81159
  unfixable.push("API Key: Run 'sidekick setup' to configure API keys interactively.");
80354
81160
  }
80355
81161
  if (liveness !== null && liveness !== "active") {
80356
- unfixable.push("Plugin Liveness: Hooks not responding. Try running '/sidekick-config' in Claude Code or 'sidekick setup' from the terminal.");
81162
+ unfixable.push("Plugin Liveness: Hooks not responding. Try running '/sidekick-setup' in Claude Code or 'sidekick setup' from the terminal.");
80357
81163
  }
80358
81164
  }
80359
81165
  stdout.write("\n");
@@ -81279,7 +82085,7 @@ var require_cli = __commonJS({
81279
82085
  var promises_12 = require("node:fs/promises");
81280
82086
  var node_stream_1 = require("node:stream");
81281
82087
  var yargs_parser_1 = __importDefault2(require_build());
81282
- var VERSION = true ? "0.1.0" : "dev";
82088
+ var VERSION = true ? "0.1.1" : "dev";
81283
82089
  var SANDBOX_ERROR_MESSAGE = `Error: Daemon commands cannot run in sandbox mode.
81284
82090
 
81285
82091
  Claude Code's sandbox blocks Unix socket operations required for daemon IPC.
@@ -81330,7 +82136,10 @@ Example: { "command": "pnpm sidekick daemon status", "dangerouslyDisableSandbox"
81330
82136
  "auto-config",
81331
82137
  "only",
81332
82138
  "marketplace-scope",
81333
- "plugin-scope"
82139
+ "plugin-scope",
82140
+ "user-profile-name",
82141
+ "user-profile-role",
82142
+ "user-profile-interests"
81334
82143
  ],
81335
82144
  number: ["port", "width"],
81336
82145
  alias: { h: "help", v: "version" }
@@ -81389,10 +82198,14 @@ Example: { "command": "pnpm sidekick daemon status", "dangerouslyDisableSandbox"
81389
82198
  personas: hasPersonasFlag ? Boolean(parsed.personas) : void 0,
81390
82199
  apiKeyScope: parsed["api-key-scope"],
81391
82200
  autoConfig: parsed["auto-config"],
82201
+ scope: parsed.scope,
81392
82202
  only: parsed.only,
81393
82203
  marketplaceScope: parsed["marketplace-scope"],
81394
82204
  pluginScope: parsed["plugin-scope"],
81395
- alias: hasAliasFlag ? Boolean(parsed.alias) : void 0
82205
+ alias: hasAliasFlag ? Boolean(parsed.alias) : void 0,
82206
+ userProfileName: parsed["user-profile-name"],
82207
+ userProfileRole: parsed["user-profile-role"],
82208
+ userProfileInterests: parsed["user-profile-interests"]
81396
82209
  };
81397
82210
  }
81398
82211
  function parseHookInput(stdinData) {
@@ -81466,6 +82279,7 @@ Example: { "command": "pnpm sidekick daemon status", "dangerouslyDisableSandbox"
81466
82279
  Commands:
81467
82280
  hook <hook-name> Execute Claude Code hook (session-start, user-prompt-submit, etc.)
81468
82281
  persona <subcommand> Manage session personas (list, set, clear, test)
82282
+ config <subcommand> Manage configuration (get, set, unset, list)
81469
82283
  sessions List all daemon-tracked sessions
81470
82284
  daemon <subcommand> Manage the background daemon (start, stop, status, kill)
81471
82285
  statusline Render the status line (used by hooks)
@@ -81606,6 +82420,17 @@ Run 'sidekick hook --help' for available hooks.
81606
82420
  });
81607
82421
  return { exitCode: result.exitCode, stdout: result.output, stderr: "" };
81608
82422
  }
82423
+ if (parsed.command === "config") {
82424
+ const { handleConfigCommand } = await Promise.resolve().then(() => __importStar(require_config3()));
82425
+ const subcommand = parsed.help ? "--help" : parsed._?.[1];
82426
+ const args = parsed._?.slice(2) ?? [];
82427
+ const result = handleConfigCommand(subcommand, args, runtime.projectRoot || process.cwd(), runtime.logger, stdout, {
82428
+ scope: parsed.scope,
82429
+ format: parsed.format === "json" ? "json" : void 0,
82430
+ assets: runtime.assets
82431
+ });
82432
+ return { exitCode: result.exitCode, stdout: result.output, stderr: "" };
82433
+ }
81609
82434
  if (parsed.command === "sessions") {
81610
82435
  const { handleSessionsCommand } = await Promise.resolve().then(() => __importStar(require_sessions3()));
81611
82436
  const result = await handleSessionsCommand(runtime.projectRoot || process.cwd(), runtime.logger, stdout, {
@@ -81638,7 +82463,10 @@ Run 'sidekick hook --help' for available hooks.
81638
82463
  autoConfig: parsed.autoConfig,
81639
82464
  marketplaceScope: parsed.marketplaceScope,
81640
82465
  pluginScope: parsed.pluginScope,
81641
- alias: parsed.alias
82466
+ alias: parsed.alias,
82467
+ userProfileName: parsed.userProfileName,
82468
+ userProfileRole: parsed.userProfileRole,
82469
+ userProfileInterests: parsed.userProfileInterests
81642
82470
  });
81643
82471
  return { exitCode: result.exitCode, stdout: "", stderr: "" };
81644
82472
  }