@hasna/statusline 0.0.2 → 0.0.3

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/mcp/index.js CHANGED
@@ -114,7 +114,7 @@ var require_code = __commonJS((exports) => {
114
114
  }
115
115
  exports._ = _;
116
116
  var plus = new _Code("+");
117
- function str(strs, ...args) {
117
+ function str2(strs, ...args) {
118
118
  const expr = [safeStringify(strs[0])];
119
119
  let i = 0;
120
120
  while (i < args.length) {
@@ -125,7 +125,7 @@ var require_code = __commonJS((exports) => {
125
125
  optimize(expr);
126
126
  return new _Code(expr);
127
127
  }
128
- exports.str = str;
128
+ exports.str = str2;
129
129
  function addCodeArg(code, arg) {
130
130
  if (arg instanceof _Code)
131
131
  code.push(...arg._items);
@@ -168,7 +168,7 @@ var require_code = __commonJS((exports) => {
168
168
  return;
169
169
  }
170
170
  function strConcat(c1, c2) {
171
- return c2.emptyStr() ? c1 : c1.emptyStr() ? c2 : str`${c1}${c2}`;
171
+ return c2.emptyStr() ? c1 : c1.emptyStr() ? c2 : str2`${c1}${c2}`;
172
172
  }
173
173
  exports.strConcat = strConcat;
174
174
  function interpolate(x) {
@@ -1118,22 +1118,22 @@ var require_util = __commonJS((exports) => {
1118
1118
  return (0, codegen_1._)`${topSchemaRef}${schemaPath}${(0, codegen_1.getProperty)(keyword)}`;
1119
1119
  }
1120
1120
  exports.schemaRefOrVal = schemaRefOrVal;
1121
- function unescapeFragment(str) {
1122
- return unescapeJsonPointer(decodeURIComponent(str));
1121
+ function unescapeFragment(str2) {
1122
+ return unescapeJsonPointer(decodeURIComponent(str2));
1123
1123
  }
1124
1124
  exports.unescapeFragment = unescapeFragment;
1125
- function escapeFragment(str) {
1126
- return encodeURIComponent(escapeJsonPointer(str));
1125
+ function escapeFragment(str2) {
1126
+ return encodeURIComponent(escapeJsonPointer(str2));
1127
1127
  }
1128
1128
  exports.escapeFragment = escapeFragment;
1129
- function escapeJsonPointer(str) {
1130
- if (typeof str == "number")
1131
- return `${str}`;
1132
- return str.replace(/~/g, "~0").replace(/\//g, "~1");
1129
+ function escapeJsonPointer(str2) {
1130
+ if (typeof str2 == "number")
1131
+ return `${str2}`;
1132
+ return str2.replace(/~/g, "~0").replace(/\//g, "~1");
1133
1133
  }
1134
1134
  exports.escapeJsonPointer = escapeJsonPointer;
1135
- function unescapeJsonPointer(str) {
1136
- return str.replace(/~1/g, "/").replace(/~0/g, "~");
1135
+ function unescapeJsonPointer(str2) {
1136
+ return str2.replace(/~1/g, "/").replace(/~0/g, "~");
1137
1137
  }
1138
1138
  exports.unescapeJsonPointer = unescapeJsonPointer;
1139
1139
  function eachItem(xs, f) {
@@ -2117,8 +2117,8 @@ var require_json_schema_traverse = __commonJS((exports, module) => {
2117
2117
  post(schema, jsonPtr, rootSchema, parentJsonPtr, parentKeyword, parentSchema, keyIndex);
2118
2118
  }
2119
2119
  }
2120
- function escapeJsonPtr(str) {
2121
- return str.replace(/~/g, "~0").replace(/\//g, "~1");
2120
+ function escapeJsonPtr(str2) {
2121
+ return str2.replace(/~/g, "~0").replace(/\//g, "~1");
2122
2122
  }
2123
2123
  });
2124
2124
 
@@ -2931,7 +2931,7 @@ var require_compile = __commonJS((exports) => {
2931
2931
  const schOrFunc = root.refs[ref];
2932
2932
  if (schOrFunc)
2933
2933
  return schOrFunc;
2934
- let _sch = resolve.call(this, root, ref);
2934
+ let _sch = resolve3.call(this, root, ref);
2935
2935
  if (_sch === undefined) {
2936
2936
  const schema = (_a = root.localRefs) === null || _a === undefined ? undefined : _a[ref];
2937
2937
  const { schemaId } = this.opts;
@@ -2958,7 +2958,7 @@ var require_compile = __commonJS((exports) => {
2958
2958
  function sameSchemaEnv(s1, s2) {
2959
2959
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
2960
2960
  }
2961
- function resolve(root, ref) {
2961
+ function resolve3(root, ref) {
2962
2962
  let sch;
2963
2963
  while (typeof (sch = this.refs[ref]) == "string")
2964
2964
  ref = sch;
@@ -3164,10 +3164,10 @@ var require_utils = __commonJS((exports, module) => {
3164
3164
  return { host, isIPV6: false };
3165
3165
  }
3166
3166
  }
3167
- function findToken(str, token) {
3167
+ function findToken(str2, token) {
3168
3168
  let ind = 0;
3169
- for (let i = 0;i < str.length; i++) {
3170
- if (str[i] === token)
3169
+ for (let i = 0;i < str2.length; i++) {
3170
+ if (str2[i] === token)
3171
3171
  ind++;
3172
3172
  }
3173
3173
  return ind;
@@ -3544,7 +3544,7 @@ var require_fast_uri = __commonJS((exports, module) => {
3544
3544
  }
3545
3545
  return uri;
3546
3546
  }
3547
- function resolve(baseURI, relativeURI, options) {
3547
+ function resolve3(baseURI, relativeURI, options) {
3548
3548
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3549
3549
  const resolved = resolveComponent(parse6(baseURI, schemelessOptions), parse6(relativeURI, schemelessOptions), schemelessOptions, true);
3550
3550
  schemelessOptions.skipEscape = true;
@@ -3672,6 +3672,7 @@ var require_fast_uri = __commonJS((exports, module) => {
3672
3672
  return uriTokens.join("");
3673
3673
  }
3674
3674
  var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
3675
+ var AUTHORITY_PREFIX = /^(?:[^#/:?]+:)?\/\/([^/?#]*)/;
3675
3676
  function getParseError(parsed, matches) {
3676
3677
  if (matches[2] !== undefined && parsed.path && parsed.path[0] !== "/") {
3677
3678
  return 'URI path must start with "/" when authority is present.';
@@ -3701,6 +3702,11 @@ var require_fast_uri = __commonJS((exports, module) => {
3701
3702
  uri = "//" + uri;
3702
3703
  }
3703
3704
  }
3705
+ const authorityMatch = uri.match(AUTHORITY_PREFIX);
3706
+ if (authorityMatch !== null && authorityMatch[1].indexOf("\\") !== -1) {
3707
+ parsed.error = "URI authority must not contain a literal backslash.";
3708
+ malformedAuthorityOrPort = true;
3709
+ }
3704
3710
  const matches = uri.match(URI_PARSE);
3705
3711
  if (matches) {
3706
3712
  parsed.scheme = matches[1];
@@ -3803,7 +3809,7 @@ var require_fast_uri = __commonJS((exports, module) => {
3803
3809
  var fastUri = {
3804
3810
  SCHEMES,
3805
3811
  normalize,
3806
- resolve,
3812
+ resolve: resolve3,
3807
3813
  resolveComponent,
3808
3814
  equal,
3809
3815
  serialize,
@@ -3859,7 +3865,7 @@ var require_core = __commonJS((exports) => {
3859
3865
  var util_1 = require_util();
3860
3866
  var $dataRefSchema = require_data();
3861
3867
  var uri_1 = require_uri();
3862
- var defaultRegExp = (str, flags) => new RegExp(str, flags);
3868
+ var defaultRegExp = (str2, flags) => new RegExp(str2, flags);
3863
3869
  defaultRegExp.code = "new RegExp";
3864
3870
  var META_IGNORE_OPTIONS = ["removeAdditional", "useDefaults", "coerceTypes"];
3865
3871
  var EXT_SCOPE_NAMES = new Set([
@@ -4621,16 +4627,16 @@ var require_multipleOf = __commonJS((exports) => {
4621
4627
  // node_modules/ajv/dist/runtime/ucs2length.js
4622
4628
  var require_ucs2length = __commonJS((exports) => {
4623
4629
  Object.defineProperty(exports, "__esModule", { value: true });
4624
- function ucs2length(str) {
4625
- const len = str.length;
4630
+ function ucs2length(str2) {
4631
+ const len = str2.length;
4626
4632
  let length = 0;
4627
4633
  let pos = 0;
4628
4634
  let value;
4629
4635
  while (pos < len) {
4630
4636
  length++;
4631
- value = str.charCodeAt(pos++);
4637
+ value = str2.charCodeAt(pos++);
4632
4638
  if (value >= 55296 && value <= 56319 && pos < len) {
4633
- value = str.charCodeAt(pos);
4639
+ value = str2.charCodeAt(pos);
4634
4640
  if ((value & 64512) === 56320)
4635
4641
  pos++;
4636
4642
  }
@@ -6371,8 +6377,8 @@ var require_formats = __commonJS((exports) => {
6371
6377
  }
6372
6378
  var DATE = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
6373
6379
  var DAYS = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
6374
- function date4(str) {
6375
- const matches = DATE.exec(str);
6380
+ function date4(str2) {
6381
+ const matches = DATE.exec(str2);
6376
6382
  if (!matches)
6377
6383
  return false;
6378
6384
  const year = +matches[1];
@@ -6391,8 +6397,8 @@ var require_formats = __commonJS((exports) => {
6391
6397
  }
6392
6398
  var TIME = /^(\d\d):(\d\d):(\d\d(?:\.\d+)?)(z|([+-])(\d\d)(?::?(\d\d))?)?$/i;
6393
6399
  function getTime(strictTimeZone) {
6394
- return function time3(str) {
6395
- const matches = TIME.exec(str);
6400
+ return function time3(str2) {
6401
+ const matches = TIME.exec(str2);
6396
6402
  if (!matches)
6397
6403
  return false;
6398
6404
  const hr = +matches[1];
@@ -6438,8 +6444,8 @@ var require_formats = __commonJS((exports) => {
6438
6444
  var DATE_TIME_SEPARATOR = /t|\s/i;
6439
6445
  function getDateTime(strictTimeZone) {
6440
6446
  const time3 = getTime(strictTimeZone);
6441
- return function date_time(str) {
6442
- const dateTime = str.split(DATE_TIME_SEPARATOR);
6447
+ return function date_time(str2) {
6448
+ const dateTime = str2.split(DATE_TIME_SEPARATOR);
6443
6449
  return dateTime.length === 2 && date4(dateTime[0]) && time3(dateTime[1]);
6444
6450
  };
6445
6451
  }
@@ -6464,13 +6470,13 @@ var require_formats = __commonJS((exports) => {
6464
6470
  }
6465
6471
  var NOT_URI_FRAGMENT = /\/|:/;
6466
6472
  var URI = /^(?:[a-z][a-z0-9+\-.]*:)(?:\/?\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:]|%[0-9a-f]{2})*@)?(?:\[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+\.[a-z0-9\-._~!$&'()*+,;=:]+)\]|(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)|(?:[a-z0-9\-._~!$&'()*+,;=]|%[0-9a-f]{2})*)(?::\d*)?(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*|\/(?:(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})+(?:\/(?:[a-z0-9\-._~!$&'()*+,;=:@]|%[0-9a-f]{2})*)*)(?:\?(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9\-._~!$&'()*+,;=:@/?]|%[0-9a-f]{2})*)?$/i;
6467
- function uri(str) {
6468
- return NOT_URI_FRAGMENT.test(str) && URI.test(str);
6473
+ function uri(str2) {
6474
+ return NOT_URI_FRAGMENT.test(str2) && URI.test(str2);
6469
6475
  }
6470
6476
  var BYTE = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/gm;
6471
- function byte(str) {
6477
+ function byte(str2) {
6472
6478
  BYTE.lastIndex = 0;
6473
- return BYTE.test(str);
6479
+ return BYTE.test(str2);
6474
6480
  }
6475
6481
  var MIN_INT32 = -(2 ** 31);
6476
6482
  var MAX_INT32 = 2 ** 31 - 1;
@@ -6484,11 +6490,11 @@ var require_formats = __commonJS((exports) => {
6484
6490
  return true;
6485
6491
  }
6486
6492
  var Z_ANCHOR = /[^\\]\\Z/;
6487
- function regex(str) {
6488
- if (Z_ANCHOR.test(str))
6493
+ function regex(str2) {
6494
+ if (Z_ANCHOR.test(str2))
6489
6495
  return false;
6490
6496
  try {
6491
- new RegExp(str);
6497
+ new RegExp(str2);
6492
6498
  return true;
6493
6499
  } catch (e) {
6494
6500
  return false;
@@ -6611,6 +6617,7 @@ import { dirname, join } from "path";
6611
6617
  function defaultConfig() {
6612
6618
  return {
6613
6619
  separator: " \xB7 ",
6620
+ colors: true,
6614
6621
  segments: [
6615
6622
  "machine",
6616
6623
  "project",
@@ -6638,7 +6645,8 @@ function loadConfig(path = configPath()) {
6638
6645
  const fallback = defaultConfig();
6639
6646
  return {
6640
6647
  separator: typeof raw.separator === "string" ? raw.separator : fallback.separator,
6641
- segments: Array.isArray(raw.segments) ? raw.segments.filter((s) => typeof s === "string") : fallback.segments
6648
+ segments: Array.isArray(raw.segments) ? raw.segments.filter((s) => typeof s === "string") : fallback.segments,
6649
+ colors: typeof raw.colors === "boolean" ? raw.colors : fallback.colors
6642
6650
  };
6643
6651
  } catch {
6644
6652
  return defaultConfig();
@@ -6666,8 +6674,15 @@ function parseClaudeInput(input) {
6666
6674
  } : undefined,
6667
6675
  transcriptPath: input?.transcript_path || undefined,
6668
6676
  sessionId: input?.session_id || undefined,
6677
+ sessionName: input?.session_name || undefined,
6669
6678
  version: input?.version || undefined,
6670
- outputStyle: input?.output_style?.name || undefined
6679
+ outputStyle: input?.output_style?.name || undefined,
6680
+ effort: input?.effort?.level || undefined,
6681
+ thinking: typeof input?.thinking?.enabled === "boolean" ? input.thinking.enabled : undefined,
6682
+ rateLimits: input?.rate_limits ? {
6683
+ fiveHour: { usedPercentage: numberOr(input.rate_limits.five_hour?.used_percentage) },
6684
+ sevenDay: { usedPercentage: numberOr(input.rate_limits.seven_day?.used_percentage) }
6685
+ } : undefined
6671
6686
  };
6672
6687
  }
6673
6688
  function numberOr(v) {
@@ -6812,6 +6827,146 @@ function windowSize(ctx) {
6812
6827
  return ctx.model?.id?.includes("[1m]") ? 1e6 : 200000;
6813
6828
  }
6814
6829
 
6830
+ // src/accounts.ts
6831
+ import { existsSync as existsSync3, readFileSync as readFileSync3, realpathSync } from "fs";
6832
+ import { homedir as homedir2 } from "os";
6833
+ import { join as join2, resolve, sep } from "path";
6834
+ var CONFIG_DIR_ENV = "CLAUDE_CONFIG_DIR";
6835
+ var DEFAULT_CONFIG_SUBDIR = ".claude";
6836
+ var STORE_PATH_ENV = "ACCOUNTS_STORE_PATH";
6837
+ var ACCOUNTS_HOME_ENV = "ACCOUNTS_HOME";
6838
+ var DEFAULT_ACCOUNTS_HOME = [".hasna", "accounts"];
6839
+ var STORE_FILE = "accounts.json";
6840
+ var PROFILES_SUBDIR = "profiles";
6841
+ var STATE_FILE_PREFERRED = ".config.json";
6842
+ var STATE_FILE_PREFIX = ".claude";
6843
+ var STATE_FILE_SUFFIX = ".json";
6844
+ var CUSTOM_OAUTH_ENV = "CLAUDE_CODE_CUSTOM_OAUTH_URL";
6845
+ var OAUTH_VARIANTS = ["", "-custom-oauth", "-local-oauth", "-staging-oauth"];
6846
+ function str(value) {
6847
+ return typeof value === "string" && value.trim() ? value.trim() : null;
6848
+ }
6849
+ function home(env) {
6850
+ return str(env.HOME) ?? homedir2();
6851
+ }
6852
+ function expandHome(path, env) {
6853
+ return path === "~" || path.startsWith(`~${sep}`) ? join2(home(env), path.slice(1)) : path;
6854
+ }
6855
+ function canonical(path, env) {
6856
+ const abs = resolve(expandHome(path, env));
6857
+ try {
6858
+ return realpathSync(abs);
6859
+ } catch {
6860
+ return abs;
6861
+ }
6862
+ }
6863
+ function readJson(path) {
6864
+ try {
6865
+ return JSON.parse(readFileSync3(path, "utf8"));
6866
+ } catch {
6867
+ return null;
6868
+ }
6869
+ }
6870
+ var ACCOUNTS_STORAGE_MODULE = "@hasna/accounts/storage";
6871
+ var storagePromise;
6872
+ function accountsStorage() {
6873
+ storagePromise ??= import(ACCOUNTS_STORAGE_MODULE).then((mod) => typeof mod?.storePath === "function" && typeof mod?.profilesDir === "function" ? mod : null, () => null);
6874
+ return storagePromise;
6875
+ }
6876
+ async function accountsPaths(env) {
6877
+ const homeOverride = str(env[ACCOUNTS_HOME_ENV]);
6878
+ const storeOverride = str(env[STORE_PATH_ENV]);
6879
+ if (!homeOverride && !storeOverride) {
6880
+ const storage = await accountsStorage();
6881
+ try {
6882
+ if (storage)
6883
+ return { store: storage.storePath(), profiles: storage.profilesDir() };
6884
+ } catch {}
6885
+ }
6886
+ const base = homeOverride ?? join2(home(env), ...DEFAULT_ACCOUNTS_HOME);
6887
+ return {
6888
+ store: storeOverride ?? join2(base, STORE_FILE),
6889
+ profiles: join2(base, PROFILES_SUBDIR)
6890
+ };
6891
+ }
6892
+ function registryEntry(store, configDir, env, tool) {
6893
+ if (!existsSync3(store))
6894
+ return null;
6895
+ const entries = readJson(store)?.profiles;
6896
+ if (!Array.isArray(entries))
6897
+ return null;
6898
+ let untyped = null;
6899
+ let first = null;
6900
+ for (const entry of entries) {
6901
+ const dir = str(entry?.dir);
6902
+ if (!dir || canonical(dir, env) !== configDir)
6903
+ continue;
6904
+ const entryTool = str(entry?.tool);
6905
+ if (tool && entryTool === tool)
6906
+ return entry;
6907
+ if (!entryTool)
6908
+ untyped ??= entry;
6909
+ first ??= entry;
6910
+ }
6911
+ return tool ? untyped : first;
6912
+ }
6913
+ function layoutProfile(profilesRoot, configDir, env) {
6914
+ if (!existsSync3(configDir))
6915
+ return null;
6916
+ const prefix = canonical(profilesRoot, env) + sep;
6917
+ if (!configDir.startsWith(prefix))
6918
+ return null;
6919
+ const parts = configDir.slice(prefix.length).split(sep);
6920
+ if (parts.length !== 2)
6921
+ return null;
6922
+ const [tool, profile] = parts;
6923
+ if (!tool || !profile)
6924
+ return null;
6925
+ return { configDir, profile, tool, source: "layout" };
6926
+ }
6927
+ function sessionConfigDir(env = process.env) {
6928
+ return canonical(str(env[CONFIG_DIR_ENV]) ?? join2(home(env), DEFAULT_CONFIG_SUBDIR), env);
6929
+ }
6930
+ function sessionStateFile(env = process.env) {
6931
+ const base = canonical(str(env[CONFIG_DIR_ENV]) ?? home(env), env);
6932
+ const preferred = join2(base, STATE_FILE_PREFERRED);
6933
+ if (existsSync3(preferred))
6934
+ return preferred;
6935
+ const variants = str(env[CUSTOM_OAUTH_ENV]) ? ["-custom-oauth", ...OAUTH_VARIANTS] : OAUTH_VARIANTS;
6936
+ for (const variant of variants) {
6937
+ const candidate = join2(base, `${STATE_FILE_PREFIX}${variant}${STATE_FILE_SUFFIX}`);
6938
+ if (existsSync3(candidate))
6939
+ return candidate;
6940
+ }
6941
+ return null;
6942
+ }
6943
+ async function sessionAccount(env = process.env, tool) {
6944
+ const configDir = sessionConfigDir(env);
6945
+ const unresolved = { configDir, profile: null, tool: null, source: null };
6946
+ try {
6947
+ const paths = await accountsPaths(env);
6948
+ const entry = registryEntry(paths.store, configDir, env, tool);
6949
+ const name = str(entry?.name);
6950
+ if (name)
6951
+ return { configDir, profile: name, tool: str(entry?.tool), source: "registry" };
6952
+ return layoutProfile(paths.profiles, configDir, env) ?? unresolved;
6953
+ } catch {
6954
+ return unresolved;
6955
+ }
6956
+ }
6957
+ async function sessionAccountEmail(env = process.env, tool) {
6958
+ try {
6959
+ const stateFile = sessionStateFile(env);
6960
+ const live = stateFile ? str(readJson(stateFile)?.oauthAccount?.emailAddress) : null;
6961
+ if (live)
6962
+ return live;
6963
+ const paths = await accountsPaths(env);
6964
+ return str(registryEntry(paths.store, sessionConfigDir(env), env, tool)?.email);
6965
+ } catch {
6966
+ return null;
6967
+ }
6968
+ }
6969
+
6815
6970
  // src/segments/index.ts
6816
6971
  function friendlyModel(id) {
6817
6972
  let tag = null;
@@ -6829,6 +6984,14 @@ function friendlyModel(id) {
6829
6984
  return { name: name || mid, tag };
6830
6985
  }
6831
6986
  var dir = (ctx) => ctx.cwd || process.cwd();
6987
+ function modelName(ctx) {
6988
+ if (ctx.model?.displayName)
6989
+ return ctx.model.displayName;
6990
+ return ctx.model?.id ? friendlyModel(ctx.model.id).name : null;
6991
+ }
6992
+ function limitPercent(pct) {
6993
+ return typeof pct === "number" ? pct : 0;
6994
+ }
6832
6995
  var segments = [
6833
6996
  {
6834
6997
  id: "machine",
@@ -6907,6 +7070,66 @@ var segments = [
6907
7070
  return tag ? `${name} ${tag}` : name;
6908
7071
  }
6909
7072
  },
7073
+ {
7074
+ id: "model-with-reasoning",
7075
+ description: "Model name with its reasoning effort (or thinking, when on)",
7076
+ defaultEnabled: false,
7077
+ color: "cyan",
7078
+ render(ctx) {
7079
+ const name = modelName(ctx);
7080
+ if (!name)
7081
+ return null;
7082
+ if (ctx.effort)
7083
+ return `${name} (${ctx.effort})`;
7084
+ if (ctx.thinking)
7085
+ return `${name} (thinking)`;
7086
+ return name;
7087
+ }
7088
+ },
7089
+ {
7090
+ id: "auth-profile",
7091
+ description: "Account profile this session runs as (omitted when unmanaged)",
7092
+ defaultEnabled: false,
7093
+ color: "magenta",
7094
+ async render(ctx) {
7095
+ const account = await sessionAccount(process.env, ctx.provider);
7096
+ return account.profile ?? await sessionAccountEmail(process.env, ctx.provider);
7097
+ }
7098
+ },
7099
+ {
7100
+ id: "auth-email",
7101
+ description: "Account email this session is logged in as (omitted when unknown)",
7102
+ defaultEnabled: false,
7103
+ color: "magenta",
7104
+ render: (ctx) => sessionAccountEmail(process.env, ctx.provider)
7105
+ },
7106
+ {
7107
+ id: "five-hour-limit",
7108
+ description: "Percentage of the 5-hour rate limit used (omitted when unreported)",
7109
+ defaultEnabled: false,
7110
+ color: (ctx) => limitPercent(ctx.rateLimits?.fiveHour?.usedPercentage) >= 80 ? "red" : "yellow",
7111
+ render(ctx) {
7112
+ const pct = ctx.rateLimits?.fiveHour?.usedPercentage;
7113
+ return typeof pct === "number" ? `5h:${Math.round(pct)}%` : null;
7114
+ }
7115
+ },
7116
+ {
7117
+ id: "seven-day-limit",
7118
+ description: "Percentage of the 7-day rate limit used (omitted when unreported)",
7119
+ defaultEnabled: false,
7120
+ color: (ctx) => limitPercent(ctx.rateLimits?.sevenDay?.usedPercentage) >= 80 ? "red" : "yellow",
7121
+ render(ctx) {
7122
+ const pct = ctx.rateLimits?.sevenDay?.usedPercentage;
7123
+ return typeof pct === "number" ? `7d:${Math.round(pct)}%` : null;
7124
+ }
7125
+ },
7126
+ {
7127
+ id: "thread-title",
7128
+ description: "Thread title set with /rename (omitted until named)",
7129
+ defaultEnabled: false,
7130
+ color: "blue",
7131
+ render: (ctx) => ctx.sessionName || null
7132
+ },
6910
7133
  {
6911
7134
  id: "context-used",
6912
7135
  description: "Percentage of context window used (omitted when unknown)",
@@ -6997,7 +7220,29 @@ function getSegment(id) {
6997
7220
  }
6998
7221
 
6999
7222
  // src/render.ts
7223
+ var ANSI = {
7224
+ cyan: "\x1B[36m",
7225
+ magenta: "\x1B[35m",
7226
+ blue: "\x1B[34m",
7227
+ green: "\x1B[32m",
7228
+ yellow: "\x1B[33m",
7229
+ red: "\x1B[31m",
7230
+ bold: "\x1B[1m",
7231
+ dim: "\x1B[2m"
7232
+ };
7233
+ var RESET = "\x1B[0m";
7234
+ function colorsEnabled(cfg, env = process.env) {
7235
+ if (env.NO_COLOR)
7236
+ return false;
7237
+ return cfg.colors !== false;
7238
+ }
7239
+ function paint(segment, text, ctx) {
7240
+ const color = typeof segment.color === "function" ? segment.color(ctx) : segment.color;
7241
+ const code = color ? ANSI[color] : undefined;
7242
+ return code ? `${code}${text}${RESET}` : text;
7243
+ }
7000
7244
  async function renderLine(ctx, cfg) {
7245
+ const colorize = colorsEnabled(cfg);
7001
7246
  const parts = [];
7002
7247
  for (const id of cfg.segments) {
7003
7248
  const segment = getSegment(id);
@@ -7006,7 +7251,7 @@ async function renderLine(ctx, cfg) {
7006
7251
  try {
7007
7252
  const out = await segment.render(ctx);
7008
7253
  if (out)
7009
- parts.push(out);
7254
+ parts.push(colorize ? paint(segment, out, ctx) : out);
7010
7255
  } catch {}
7011
7256
  }
7012
7257
  return parts.join(cfg.separator);
@@ -7014,7 +7259,7 @@ async function renderLine(ctx, cfg) {
7014
7259
  // package.json
7015
7260
  var package_default = {
7016
7261
  name: "@hasna/statusline",
7017
- version: "0.0.2",
7262
+ version: "0.0.3",
7018
7263
  description: "Tiny composable statusline CLI for AI coding agents \u2014 pre-built toggleable segments for Claude Code, with a provider model for others",
7019
7264
  license: "Apache-2.0",
7020
7265
  type: "module",
@@ -7083,21 +7328,43 @@ var package_default = {
7083
7328
  }
7084
7329
  };
7085
7330
  // src/install.ts
7086
- import { copyFileSync, existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
7087
- import { homedir as homedir2 } from "os";
7088
- import { dirname as dirname2, join as join2 } from "path";
7089
- function installClaude(settingsPath = join2(homedir2(), ".claude", "settings.json")) {
7331
+ import { copyFileSync, existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
7332
+ import { homedir as homedir3 } from "os";
7333
+ import { dirname as dirname2, join as join3, resolve as resolve2 } from "path";
7334
+ function defaultSettingsPath(env) {
7335
+ return join3(env.HOME || homedir3(), ".claude", "settings.json");
7336
+ }
7337
+ function claudeSettingsPath(env = process.env) {
7338
+ const home2 = env.HOME || homedir3();
7339
+ const raw = env.CLAUDE_CONFIG_DIR?.trim();
7340
+ if (!raw)
7341
+ return defaultSettingsPath(env);
7342
+ const configDir = raw === "~" || raw.startsWith("~/") ? join3(home2, raw.slice(1)) : raw;
7343
+ return join3(configDir, "settings.json");
7344
+ }
7345
+ function installClaude(settingsPath, env = process.env) {
7346
+ const target = settingsPath ?? claudeSettingsPath(env);
7090
7347
  const binary = Bun.which("statusline") || "statusline";
7091
7348
  let settings = {};
7092
- if (existsSync3(settingsPath)) {
7093
- settings = JSON.parse(readFileSync3(settingsPath, "utf8"));
7094
- copyFileSync(settingsPath, `${settingsPath}.bak-statusline`);
7349
+ if (existsSync4(target)) {
7350
+ try {
7351
+ settings = JSON.parse(readFileSync4(target, "utf8"));
7352
+ } catch (error) {
7353
+ throw new Error(`${target} is not valid JSON \u2014 fix or move it first`);
7354
+ }
7355
+ copyFileSync(target, `${target}.bak-statusline`);
7095
7356
  }
7096
- settings.statusLine = { type: "command", command: `${binary} render` };
7097
- mkdirSync2(dirname2(settingsPath), { recursive: true });
7098
- writeFileSync2(settingsPath, JSON.stringify(settings, null, 2) + `
7357
+ settings.statusLine = { ...settings.statusLine, type: "command", command: `${binary} render` };
7358
+ const configDir = dirname2(target);
7359
+ if (!existsSync4(configDir)) {
7360
+ if (resolve2(target) !== resolve2(defaultSettingsPath(env))) {
7361
+ throw new Error(`config dir ${configDir} does not exist \u2014 create the profile first`);
7362
+ }
7363
+ mkdirSync2(configDir, { recursive: true });
7364
+ }
7365
+ writeFileSync2(target, JSON.stringify(settings, null, 2) + `
7099
7366
  `);
7100
- return settingsPath;
7367
+ return target;
7101
7368
  }
7102
7369
 
7103
7370
  // src/index.ts
@@ -7149,6 +7416,9 @@ function setSeparator(separator, config = loadConfig()) {
7149
7416
  throw new Error("separator must be a non-empty string");
7150
7417
  return { config: { ...config, separator }, changed: ["separator"] };
7151
7418
  }
7419
+ function setColors(colors, config = loadConfig()) {
7420
+ return { config: { ...config, colors }, changed: ["colors"] };
7421
+ }
7152
7422
  function resetStatuslineConfig() {
7153
7423
  return defaultConfig();
7154
7424
  }
@@ -7161,7 +7431,11 @@ function sampleClaudeInput(cwd = process.cwd()) {
7161
7431
  model: { id: "claude-fable-5[1m]", display_name: "Fable" },
7162
7432
  cost: { total_cost_usd: 12.34, total_duration_ms: 5400000, total_lines_added: 42, total_lines_removed: 7 },
7163
7433
  version: statuslineVersion,
7164
- session_id: "preview0-0000-0000-0000-000000000000"
7434
+ session_id: "preview0-0000-0000-0000-000000000000",
7435
+ session_name: "preview thread",
7436
+ effort: { level: "high" },
7437
+ thinking: { enabled: true },
7438
+ rate_limits: { five_hour: { used_percentage: 42 } }
7165
7439
  };
7166
7440
  }
7167
7441
  async function previewStatusline(config = loadConfig(), cwd = process.cwd()) {
@@ -11356,14 +11630,14 @@ function promiseAllObject(promisesObj) {
11356
11630
  }
11357
11631
  function randomString(length = 10) {
11358
11632
  const chars = "abcdefghijklmnopqrstuvwxyz";
11359
- let str = "";
11633
+ let str2 = "";
11360
11634
  for (let i = 0;i < length; i++) {
11361
- str += chars[Math.floor(Math.random() * chars.length)];
11635
+ str2 += chars[Math.floor(Math.random() * chars.length)];
11362
11636
  }
11363
- return str;
11637
+ return str2;
11364
11638
  }
11365
- function esc(str) {
11366
- return JSON.stringify(str);
11639
+ function esc(str2) {
11640
+ return JSON.stringify(str2);
11367
11641
  }
11368
11642
  var captureStackTrace = Error.captureStackTrace ? Error.captureStackTrace : (..._args) => {};
11369
11643
  function isObject(data) {
@@ -11450,8 +11724,8 @@ var getParsedType2 = (data) => {
11450
11724
  };
11451
11725
  var propertyKeyTypes = new Set(["string", "number", "symbol"]);
11452
11726
  var primitiveTypes = new Set(["string", "number", "bigint", "boolean", "symbol", "undefined"]);
11453
- function escapeRegex(str) {
11454
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
11727
+ function escapeRegex(str2) {
11728
+ return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
11455
11729
  }
11456
11730
  function clone(inst, def, params) {
11457
11731
  const cl = new inst._zod.constr(def ?? inst._zod.def);
@@ -18375,7 +18649,7 @@ class Protocol {
18375
18649
  return;
18376
18650
  }
18377
18651
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1000;
18378
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
18652
+ await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
18379
18653
  options?.signal?.throwIfAborted();
18380
18654
  }
18381
18655
  } catch (error2) {
@@ -18387,7 +18661,7 @@ class Protocol {
18387
18661
  }
18388
18662
  request(request, resultSchema, options) {
18389
18663
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
18390
- return new Promise((resolve, reject) => {
18664
+ return new Promise((resolve3, reject) => {
18391
18665
  const earlyReject = (error2) => {
18392
18666
  reject(error2);
18393
18667
  };
@@ -18465,7 +18739,7 @@ class Protocol {
18465
18739
  if (!parseResult.success) {
18466
18740
  reject(parseResult.error);
18467
18741
  } else {
18468
- resolve(parseResult.data);
18742
+ resolve3(parseResult.data);
18469
18743
  }
18470
18744
  } catch (error2) {
18471
18745
  reject(error2);
@@ -18656,12 +18930,12 @@ class Protocol {
18656
18930
  interval = task.pollInterval;
18657
18931
  }
18658
18932
  } catch {}
18659
- return new Promise((resolve, reject) => {
18933
+ return new Promise((resolve3, reject) => {
18660
18934
  if (signal.aborted) {
18661
18935
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
18662
18936
  return;
18663
18937
  }
18664
- const timeoutId = setTimeout(resolve, interval);
18938
+ const timeoutId = setTimeout(resolve3, interval);
18665
18939
  signal.addEventListener("abort", () => {
18666
18940
  clearTimeout(timeoutId);
18667
18941
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -19514,7 +19788,7 @@ class McpServer {
19514
19788
  let task = createTaskResult.task;
19515
19789
  const pollInterval = task.pollInterval ?? 5000;
19516
19790
  while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
19517
- await new Promise((resolve) => setTimeout(resolve, pollInterval));
19791
+ await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
19518
19792
  const updatedTask = await extra.taskStore.getTask(taskId);
19519
19793
  if (!updatedTask) {
19520
19794
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -20132,23 +20406,24 @@ class StdioServerTransport {
20132
20406
  this.onclose?.();
20133
20407
  }
20134
20408
  send(message) {
20135
- return new Promise((resolve) => {
20409
+ return new Promise((resolve3) => {
20136
20410
  const json = serializeMessage(message);
20137
20411
  if (this._stdout.write(json)) {
20138
- resolve();
20412
+ resolve3();
20139
20413
  } else {
20140
- this._stdout.once("drain", resolve);
20414
+ this._stdout.once("drain", resolve3);
20141
20415
  }
20142
20416
  });
20143
20417
  }
20144
20418
  }
20145
20419
 
20146
20420
  // src/mcp/index.ts
20147
- import { resolve } from "path";
20421
+ import { resolve as resolve3 } from "path";
20148
20422
  var configPathSchema = exports_external.string().min(1).optional().describe("Path to statusline config JSON. Defaults to STATUSLINE_CONFIG or ~/.config/statusline/config.json.");
20149
20423
  var configSchema = exports_external.object({
20150
20424
  separator: exports_external.string().min(1).optional(),
20151
- segments: exports_external.array(exports_external.string().min(1)).optional()
20425
+ segments: exports_external.array(exports_external.string().min(1)).optional(),
20426
+ colors: exports_external.boolean().optional()
20152
20427
  }).optional();
20153
20428
  function jsonResult(value) {
20154
20429
  return { content: [{ type: "text", text: JSON.stringify(value, null, 2) }] };
@@ -20177,7 +20452,7 @@ function loadConfigFor(path) {
20177
20452
  return { path: resolvedPath, config: loadConfig(resolvedPath) };
20178
20453
  }
20179
20454
  function assertWritableConfigPath(path) {
20180
- if (resolve(path) !== resolve(defaultWritablePath())) {
20455
+ if (resolve3(path) !== resolve3(defaultWritablePath())) {
20181
20456
  throw new Error("config writes are restricted to the server's configured statusline config path.");
20182
20457
  }
20183
20458
  }
@@ -20232,10 +20507,11 @@ function buildServer() {
20232
20507
  const loaded = loadConfigFor(config_path);
20233
20508
  return { configPath: loaded.path, config: loaded.config };
20234
20509
  }));
20235
- server.tool("update_config", "Update separator and/or the full enabled segment list.", {
20510
+ server.tool("update_config", "Update separator, colours, and/or the full enabled segment list.", {
20236
20511
  config_path: configPathSchema,
20237
20512
  separator: exports_external.string().min(1).optional(),
20238
20513
  segments: exports_external.array(exports_external.string().min(1)).optional(),
20514
+ colors: exports_external.boolean().optional(),
20239
20515
  dry_run: exports_external.boolean().default(false),
20240
20516
  confirm_write: exports_external.boolean().default(false)
20241
20517
  }, async (input) => safeTool(() => {
@@ -20246,6 +20522,8 @@ function buildServer() {
20246
20522
  next = setSeparator(input.separator, next).config;
20247
20523
  if (input.segments !== undefined)
20248
20524
  next = orderSegments(input.segments, next).config;
20525
+ if (input.colors !== undefined)
20526
+ next = setColors(input.colors, next).config;
20249
20527
  maybeWrite(loaded.path, next, input);
20250
20528
  return { configPath: loaded.path, dryRun: input.dry_run, config: next };
20251
20529
  }));