ccusage 0.1.9 → 0.1.11
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/README.md +4 -0
- package/dist/index.js +292 -62
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -42,6 +42,10 @@ This tool helps you understand the value you're getting from your subscription b
|
|
|
42
42
|
- 📄 **JSON Output**: Export data in structured JSON format with `--json`
|
|
43
43
|
- 💰 **Cost Tracking**: Shows costs in USD for each day/session
|
|
44
44
|
|
|
45
|
+
## Limitations
|
|
46
|
+
|
|
47
|
+
- This tool only reads local JSONL files generated by Claude Code. If you use Claude Code with multiple devices, you need to ensure the JSONL files are synchronized across devices.
|
|
48
|
+
|
|
45
49
|
## Installation
|
|
46
50
|
|
|
47
51
|
### Quick Start (Recommended)
|
package/dist/index.js
CHANGED
|
@@ -4878,9 +4878,9 @@ var require_picomatch$1 = __commonJS({ "node_modules/picomatch/lib/picomatch.js"
|
|
|
4878
4878
|
if (glob$1 === "" || typeof glob$1 !== "string" && !isState) throw new TypeError("Expected pattern to be a non-empty string");
|
|
4879
4879
|
const opts = options || {};
|
|
4880
4880
|
const posix$1 = opts.windows;
|
|
4881
|
-
const regex$
|
|
4882
|
-
const state = regex$
|
|
4883
|
-
delete regex$
|
|
4881
|
+
const regex$2 = isState ? picomatch$2.compileRe(glob$1, options) : picomatch$2.makeRe(glob$1, options, false, true);
|
|
4882
|
+
const state = regex$2.state;
|
|
4883
|
+
delete regex$2.state;
|
|
4884
4884
|
let isIgnored = () => false;
|
|
4885
4885
|
if (opts.ignore) {
|
|
4886
4886
|
const ignoreOpts = {
|
|
@@ -4892,14 +4892,14 @@ var require_picomatch$1 = __commonJS({ "node_modules/picomatch/lib/picomatch.js"
|
|
|
4892
4892
|
isIgnored = picomatch$2(opts.ignore, ignoreOpts, returnState);
|
|
4893
4893
|
}
|
|
4894
4894
|
const matcher = (input, returnObject = false) => {
|
|
4895
|
-
const { isMatch, match, output } = picomatch$2.test(input, regex$
|
|
4895
|
+
const { isMatch, match, output } = picomatch$2.test(input, regex$2, options, {
|
|
4896
4896
|
glob: glob$1,
|
|
4897
4897
|
posix: posix$1
|
|
4898
4898
|
});
|
|
4899
4899
|
const result = {
|
|
4900
4900
|
glob: glob$1,
|
|
4901
4901
|
state,
|
|
4902
|
-
regex: regex$
|
|
4902
|
+
regex: regex$2,
|
|
4903
4903
|
posix: posix$1,
|
|
4904
4904
|
input,
|
|
4905
4905
|
output,
|
|
@@ -4938,7 +4938,7 @@ var require_picomatch$1 = __commonJS({ "node_modules/picomatch/lib/picomatch.js"
|
|
|
4938
4938
|
* @return {Object} Returns an object with matching info.
|
|
4939
4939
|
* @api public
|
|
4940
4940
|
*/
|
|
4941
|
-
picomatch$2.test = (input, regex$
|
|
4941
|
+
picomatch$2.test = (input, regex$2, options, { glob: glob$1, posix: posix$1 } = {}) => {
|
|
4942
4942
|
if (typeof input !== "string") throw new TypeError("Expected input to be a string");
|
|
4943
4943
|
if (input === "") return {
|
|
4944
4944
|
isMatch: false,
|
|
@@ -4952,8 +4952,8 @@ var require_picomatch$1 = __commonJS({ "node_modules/picomatch/lib/picomatch.js"
|
|
|
4952
4952
|
output = format ? format(input) : input;
|
|
4953
4953
|
match = output === glob$1;
|
|
4954
4954
|
}
|
|
4955
|
-
if (match === false || opts.capture === true) if (opts.matchBase === true || opts.basename === true) match = picomatch$2.matchBase(input, regex$
|
|
4956
|
-
else match = regex$
|
|
4955
|
+
if (match === false || opts.capture === true) if (opts.matchBase === true || opts.basename === true) match = picomatch$2.matchBase(input, regex$2, options, posix$1);
|
|
4956
|
+
else match = regex$2.exec(output);
|
|
4957
4957
|
return {
|
|
4958
4958
|
isMatch: Boolean(match),
|
|
4959
4959
|
match,
|
|
@@ -4974,8 +4974,8 @@ var require_picomatch$1 = __commonJS({ "node_modules/picomatch/lib/picomatch.js"
|
|
|
4974
4974
|
* @api public
|
|
4975
4975
|
*/
|
|
4976
4976
|
picomatch$2.matchBase = (input, glob$1, options) => {
|
|
4977
|
-
const regex$
|
|
4978
|
-
return regex$
|
|
4977
|
+
const regex$2 = glob$1 instanceof RegExp ? glob$1 : picomatch$2.makeRe(glob$1, options);
|
|
4978
|
+
return regex$2.test(utils$1.basename(input));
|
|
4979
4979
|
};
|
|
4980
4980
|
/**
|
|
4981
4981
|
* Returns true if **any** of the given glob `patterns` match the specified `string`.
|
|
@@ -5059,9 +5059,9 @@ var require_picomatch$1 = __commonJS({ "node_modules/picomatch/lib/picomatch.js"
|
|
|
5059
5059
|
const append = opts.contains ? "" : "$";
|
|
5060
5060
|
let source = `${prepend}(?:${state.output})${append}`;
|
|
5061
5061
|
if (state && state.negated === true) source = `^(?!${source}).*$`;
|
|
5062
|
-
const regex$
|
|
5063
|
-
if (returnState === true) regex$
|
|
5064
|
-
return regex$
|
|
5062
|
+
const regex$2 = picomatch$2.toRegex(source, options);
|
|
5063
|
+
if (returnState === true) regex$2.state = state;
|
|
5064
|
+
return regex$2;
|
|
5065
5065
|
};
|
|
5066
5066
|
/**
|
|
5067
5067
|
* Create a regular expression from a parsed glob pattern.
|
|
@@ -5341,14 +5341,14 @@ function getPartialMatcher(patterns, options) {
|
|
|
5341
5341
|
if (inputParts[0] === ".." && ONLY_PARENT_DIRECTORIES.test(input)) return true;
|
|
5342
5342
|
for (let i$1 = 0; i$1 < patterns.length; i$1++) {
|
|
5343
5343
|
const patternParts = patternsParts[i$1];
|
|
5344
|
-
const regex$
|
|
5344
|
+
const regex$2 = regexes[i$1];
|
|
5345
5345
|
const inputPatternCount = inputParts.length;
|
|
5346
5346
|
const minParts = Math.min(inputPatternCount, patternParts.length);
|
|
5347
5347
|
let j = 0;
|
|
5348
5348
|
while (j < minParts) {
|
|
5349
5349
|
const part = patternParts[j];
|
|
5350
5350
|
if (part.includes("/")) return true;
|
|
5351
|
-
const match = regex$
|
|
5351
|
+
const match = regex$2[j].test(inputParts[j]);
|
|
5352
5352
|
if (!match) break;
|
|
5353
5353
|
if (part === "**") return true;
|
|
5354
5354
|
j++;
|
|
@@ -5607,6 +5607,32 @@ function _getStandardProps(context) {
|
|
|
5607
5607
|
};
|
|
5608
5608
|
}
|
|
5609
5609
|
/* @__NO_SIDE_EFFECTS__ */
|
|
5610
|
+
function _isValidObjectKey(object2, key) {
|
|
5611
|
+
return Object.hasOwn(object2, key) && key !== "__proto__" && key !== "prototype" && key !== "constructor";
|
|
5612
|
+
}
|
|
5613
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
5614
|
+
function _joinExpects(values2, separator) {
|
|
5615
|
+
const list = [...new Set(values2)];
|
|
5616
|
+
if (list.length > 1) return `(${list.join(` ${separator} `)})`;
|
|
5617
|
+
return list[0] ?? "never";
|
|
5618
|
+
}
|
|
5619
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
5620
|
+
function regex$1(requirement, message2) {
|
|
5621
|
+
return {
|
|
5622
|
+
kind: "validation",
|
|
5623
|
+
type: "regex",
|
|
5624
|
+
reference: regex$1,
|
|
5625
|
+
async: false,
|
|
5626
|
+
expects: `${requirement}`,
|
|
5627
|
+
requirement,
|
|
5628
|
+
message: message2,
|
|
5629
|
+
"~run"(dataset, config2) {
|
|
5630
|
+
if (dataset.typed && !this.requirement.test(dataset.value)) _addIssue(this, "format", dataset, config2);
|
|
5631
|
+
return dataset;
|
|
5632
|
+
}
|
|
5633
|
+
};
|
|
5634
|
+
}
|
|
5635
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
5610
5636
|
function getFallback(schema, dataset, config2) {
|
|
5611
5637
|
return typeof schema.fallback === "function" ? schema.fallback(dataset, config2) : schema.fallback;
|
|
5612
5638
|
}
|
|
@@ -5615,6 +5641,25 @@ function getDefault(schema, dataset, config2) {
|
|
|
5615
5641
|
return typeof schema.default === "function" ? schema.default(dataset, config2) : schema.default;
|
|
5616
5642
|
}
|
|
5617
5643
|
/* @__NO_SIDE_EFFECTS__ */
|
|
5644
|
+
function boolean(message2) {
|
|
5645
|
+
return {
|
|
5646
|
+
kind: "schema",
|
|
5647
|
+
type: "boolean",
|
|
5648
|
+
reference: boolean,
|
|
5649
|
+
expects: "boolean",
|
|
5650
|
+
async: false,
|
|
5651
|
+
message: message2,
|
|
5652
|
+
get "~standard"() {
|
|
5653
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
5654
|
+
},
|
|
5655
|
+
"~run"(dataset, config2) {
|
|
5656
|
+
if (typeof dataset.value === "boolean") dataset.typed = true;
|
|
5657
|
+
else _addIssue(this, "type", dataset, config2);
|
|
5658
|
+
return dataset;
|
|
5659
|
+
}
|
|
5660
|
+
};
|
|
5661
|
+
}
|
|
5662
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
5618
5663
|
function number(message2) {
|
|
5619
5664
|
return {
|
|
5620
5665
|
kind: "schema",
|
|
@@ -5699,6 +5744,99 @@ function object(entries2, message2) {
|
|
|
5699
5744
|
};
|
|
5700
5745
|
}
|
|
5701
5746
|
/* @__NO_SIDE_EFFECTS__ */
|
|
5747
|
+
function optional(wrapped, default_) {
|
|
5748
|
+
return {
|
|
5749
|
+
kind: "schema",
|
|
5750
|
+
type: "optional",
|
|
5751
|
+
reference: optional,
|
|
5752
|
+
expects: `(${wrapped.expects} | undefined)`,
|
|
5753
|
+
async: false,
|
|
5754
|
+
wrapped,
|
|
5755
|
+
default: default_,
|
|
5756
|
+
get "~standard"() {
|
|
5757
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
5758
|
+
},
|
|
5759
|
+
"~run"(dataset, config2) {
|
|
5760
|
+
if (dataset.value === void 0) {
|
|
5761
|
+
if (this.default !== void 0) dataset.value = /* @__PURE__ */ getDefault(this, dataset, config2);
|
|
5762
|
+
if (dataset.value === void 0) {
|
|
5763
|
+
dataset.typed = true;
|
|
5764
|
+
return dataset;
|
|
5765
|
+
}
|
|
5766
|
+
}
|
|
5767
|
+
return this.wrapped["~run"](dataset, config2);
|
|
5768
|
+
}
|
|
5769
|
+
};
|
|
5770
|
+
}
|
|
5771
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
5772
|
+
function record(key, value2, message2) {
|
|
5773
|
+
return {
|
|
5774
|
+
kind: "schema",
|
|
5775
|
+
type: "record",
|
|
5776
|
+
reference: record,
|
|
5777
|
+
expects: "Object",
|
|
5778
|
+
async: false,
|
|
5779
|
+
key,
|
|
5780
|
+
value: value2,
|
|
5781
|
+
message: message2,
|
|
5782
|
+
get "~standard"() {
|
|
5783
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
5784
|
+
},
|
|
5785
|
+
"~run"(dataset, config2) {
|
|
5786
|
+
const input = dataset.value;
|
|
5787
|
+
if (input && typeof input === "object") {
|
|
5788
|
+
dataset.typed = true;
|
|
5789
|
+
dataset.value = {};
|
|
5790
|
+
for (const entryKey in input) if (/* @__PURE__ */ _isValidObjectKey(input, entryKey)) {
|
|
5791
|
+
const entryValue = input[entryKey];
|
|
5792
|
+
const keyDataset = this.key["~run"]({ value: entryKey }, config2);
|
|
5793
|
+
if (keyDataset.issues) {
|
|
5794
|
+
const pathItem = {
|
|
5795
|
+
type: "object",
|
|
5796
|
+
origin: "key",
|
|
5797
|
+
input,
|
|
5798
|
+
key: entryKey,
|
|
5799
|
+
value: entryValue
|
|
5800
|
+
};
|
|
5801
|
+
for (const issue of keyDataset.issues) {
|
|
5802
|
+
issue.path = [pathItem];
|
|
5803
|
+
dataset.issues?.push(issue);
|
|
5804
|
+
}
|
|
5805
|
+
if (!dataset.issues) dataset.issues = keyDataset.issues;
|
|
5806
|
+
if (config2.abortEarly) {
|
|
5807
|
+
dataset.typed = false;
|
|
5808
|
+
break;
|
|
5809
|
+
}
|
|
5810
|
+
}
|
|
5811
|
+
const valueDataset = this.value["~run"]({ value: entryValue }, config2);
|
|
5812
|
+
if (valueDataset.issues) {
|
|
5813
|
+
const pathItem = {
|
|
5814
|
+
type: "object",
|
|
5815
|
+
origin: "value",
|
|
5816
|
+
input,
|
|
5817
|
+
key: entryKey,
|
|
5818
|
+
value: entryValue
|
|
5819
|
+
};
|
|
5820
|
+
for (const issue of valueDataset.issues) {
|
|
5821
|
+
if (issue.path) issue.path.unshift(pathItem);
|
|
5822
|
+
else issue.path = [pathItem];
|
|
5823
|
+
dataset.issues?.push(issue);
|
|
5824
|
+
}
|
|
5825
|
+
if (!dataset.issues) dataset.issues = valueDataset.issues;
|
|
5826
|
+
if (config2.abortEarly) {
|
|
5827
|
+
dataset.typed = false;
|
|
5828
|
+
break;
|
|
5829
|
+
}
|
|
5830
|
+
}
|
|
5831
|
+
if (!keyDataset.typed || !valueDataset.typed) dataset.typed = false;
|
|
5832
|
+
if (keyDataset.typed) dataset.value[keyDataset.value] = valueDataset.value;
|
|
5833
|
+
}
|
|
5834
|
+
} else _addIssue(this, "type", dataset, config2);
|
|
5835
|
+
return dataset;
|
|
5836
|
+
}
|
|
5837
|
+
};
|
|
5838
|
+
}
|
|
5839
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
5702
5840
|
function string(message2) {
|
|
5703
5841
|
return {
|
|
5704
5842
|
kind: "schema",
|
|
@@ -5718,6 +5856,72 @@ function string(message2) {
|
|
|
5718
5856
|
};
|
|
5719
5857
|
}
|
|
5720
5858
|
/* @__NO_SIDE_EFFECTS__ */
|
|
5859
|
+
function _subIssues(datasets) {
|
|
5860
|
+
let issues;
|
|
5861
|
+
if (datasets) for (const dataset of datasets) if (issues) issues.push(...dataset.issues);
|
|
5862
|
+
else issues = dataset.issues;
|
|
5863
|
+
return issues;
|
|
5864
|
+
}
|
|
5865
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
5866
|
+
function union(options, message2) {
|
|
5867
|
+
return {
|
|
5868
|
+
kind: "schema",
|
|
5869
|
+
type: "union",
|
|
5870
|
+
reference: union,
|
|
5871
|
+
expects: /* @__PURE__ */ _joinExpects(options.map((option) => option.expects), "|"),
|
|
5872
|
+
async: false,
|
|
5873
|
+
options,
|
|
5874
|
+
message: message2,
|
|
5875
|
+
get "~standard"() {
|
|
5876
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
5877
|
+
},
|
|
5878
|
+
"~run"(dataset, config2) {
|
|
5879
|
+
let validDataset;
|
|
5880
|
+
let typedDatasets;
|
|
5881
|
+
let untypedDatasets;
|
|
5882
|
+
for (const schema of this.options) {
|
|
5883
|
+
const optionDataset = schema["~run"]({ value: dataset.value }, config2);
|
|
5884
|
+
if (optionDataset.typed) if (optionDataset.issues) if (typedDatasets) typedDatasets.push(optionDataset);
|
|
5885
|
+
else typedDatasets = [optionDataset];
|
|
5886
|
+
else {
|
|
5887
|
+
validDataset = optionDataset;
|
|
5888
|
+
break;
|
|
5889
|
+
}
|
|
5890
|
+
else if (untypedDatasets) untypedDatasets.push(optionDataset);
|
|
5891
|
+
else untypedDatasets = [optionDataset];
|
|
5892
|
+
}
|
|
5893
|
+
if (validDataset) return validDataset;
|
|
5894
|
+
if (typedDatasets) {
|
|
5895
|
+
if (typedDatasets.length === 1) return typedDatasets[0];
|
|
5896
|
+
_addIssue(this, "type", dataset, config2, { issues: /* @__PURE__ */ _subIssues(typedDatasets) });
|
|
5897
|
+
dataset.typed = true;
|
|
5898
|
+
} else if (untypedDatasets?.length === 1) return untypedDatasets[0];
|
|
5899
|
+
else _addIssue(this, "type", dataset, config2, { issues: /* @__PURE__ */ _subIssues(untypedDatasets) });
|
|
5900
|
+
return dataset;
|
|
5901
|
+
}
|
|
5902
|
+
};
|
|
5903
|
+
}
|
|
5904
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
5905
|
+
function pipe(...pipe2) {
|
|
5906
|
+
return {
|
|
5907
|
+
...pipe2[0],
|
|
5908
|
+
pipe: pipe2,
|
|
5909
|
+
get "~standard"() {
|
|
5910
|
+
return /* @__PURE__ */ _getStandardProps(this);
|
|
5911
|
+
},
|
|
5912
|
+
"~run"(dataset, config2) {
|
|
5913
|
+
for (const item of pipe2) if (item.kind !== "metadata") {
|
|
5914
|
+
if (dataset.issues && (item.kind === "schema" || item.kind === "transformation")) {
|
|
5915
|
+
dataset.typed = false;
|
|
5916
|
+
break;
|
|
5917
|
+
}
|
|
5918
|
+
if (!dataset.issues || !config2.abortEarly && !config2.abortPipeEarly) dataset = item["~run"](dataset, config2);
|
|
5919
|
+
}
|
|
5920
|
+
return dataset;
|
|
5921
|
+
}
|
|
5922
|
+
};
|
|
5923
|
+
}
|
|
5924
|
+
/* @__NO_SIDE_EFFECTS__ */
|
|
5721
5925
|
function safeParse(schema, input, config2) {
|
|
5722
5926
|
const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig(config2));
|
|
5723
5927
|
return {
|
|
@@ -5730,6 +5934,7 @@ function safeParse(schema, input, config2) {
|
|
|
5730
5934
|
|
|
5731
5935
|
//#endregion
|
|
5732
5936
|
//#region data-loader.ts
|
|
5937
|
+
const getDefaultClaudePath = () => path.join(homedir(), ".claude");
|
|
5733
5938
|
const UsageDataSchema = object({
|
|
5734
5939
|
timestamp: string(),
|
|
5735
5940
|
message: object({ usage: object({
|
|
@@ -5760,7 +5965,8 @@ const formatDate = (dateStr) => {
|
|
|
5760
5965
|
return `${year}-${month}-${day}`;
|
|
5761
5966
|
};
|
|
5762
5967
|
async function loadUsageData(options) {
|
|
5763
|
-
const
|
|
5968
|
+
const claudePath = options?.claudePath ?? getDefaultClaudePath();
|
|
5969
|
+
const claudeDir = path.join(claudePath, "projects");
|
|
5764
5970
|
const files = await glob(["**/*.jsonl"], {
|
|
5765
5971
|
cwd: claudeDir,
|
|
5766
5972
|
absolute: true
|
|
@@ -5802,7 +6008,8 @@ async function loadUsageData(options) {
|
|
|
5802
6008
|
});
|
|
5803
6009
|
}
|
|
5804
6010
|
async function loadSessionData(options) {
|
|
5805
|
-
const
|
|
6011
|
+
const claudePath = options?.claudePath ?? getDefaultClaudePath();
|
|
6012
|
+
const claudeDir = path.join(claudePath, "projects");
|
|
5806
6013
|
const files = await glob(["**/*.jsonl"], {
|
|
5807
6014
|
cwd: claudeDir,
|
|
5808
6015
|
absolute: true
|
|
@@ -6816,7 +7023,7 @@ const consola = createConsola();
|
|
|
6816
7023
|
//#endregion
|
|
6817
7024
|
//#region package.json
|
|
6818
7025
|
var name = "ccusage";
|
|
6819
|
-
var version = "0.1.
|
|
7026
|
+
var version = "0.1.11";
|
|
6820
7027
|
var description = "Usage analysis tool for Claude Code";
|
|
6821
7028
|
|
|
6822
7029
|
//#endregion
|
|
@@ -6824,6 +7031,71 @@ var description = "Usage analysis tool for Claude Code";
|
|
|
6824
7031
|
const logger = consola.withTag(name);
|
|
6825
7032
|
const log = (...args) => console.log(...args);
|
|
6826
7033
|
|
|
7034
|
+
//#endregion
|
|
7035
|
+
//#region types.ts
|
|
7036
|
+
const ModelSpecSchema = object({
|
|
7037
|
+
max_tokens: optional(union([number(), string()])),
|
|
7038
|
+
max_input_tokens: optional(union([number(), string()])),
|
|
7039
|
+
max_output_tokens: optional(union([number(), string()])),
|
|
7040
|
+
input_cost_per_token: optional(number()),
|
|
7041
|
+
output_cost_per_token: optional(number()),
|
|
7042
|
+
output_cost_per_reasoning_token: optional(number()),
|
|
7043
|
+
litellm_provider: optional(string()),
|
|
7044
|
+
mode: optional(string()),
|
|
7045
|
+
supports_function_calling: optional(boolean()),
|
|
7046
|
+
supports_parallel_function_calling: optional(boolean()),
|
|
7047
|
+
supports_vision: optional(boolean()),
|
|
7048
|
+
supports_audio_input: optional(boolean()),
|
|
7049
|
+
supports_audio_output: optional(boolean()),
|
|
7050
|
+
supports_prompt_caching: optional(boolean()),
|
|
7051
|
+
supports_response_schema: optional(boolean()),
|
|
7052
|
+
supports_system_messages: optional(boolean()),
|
|
7053
|
+
supports_reasoning: optional(boolean()),
|
|
7054
|
+
supports_web_search: optional(boolean()),
|
|
7055
|
+
search_context_cost_per_query: optional(object({
|
|
7056
|
+
search_context_size_low: number(),
|
|
7057
|
+
search_context_size_medium: number(),
|
|
7058
|
+
search_context_size_high: number()
|
|
7059
|
+
})),
|
|
7060
|
+
deprecation_date: optional(string())
|
|
7061
|
+
});
|
|
7062
|
+
const LiteLLMModelPricesSchema = record(string(), ModelSpecSchema);
|
|
7063
|
+
const dateSchema = pipe(string(), regex$1(/^\d{8}$/, "Date must be in YYYYMMDD format"));
|
|
7064
|
+
|
|
7065
|
+
//#endregion
|
|
7066
|
+
//#region shared-args.ts
|
|
7067
|
+
const parseDateArg = (value) => {
|
|
7068
|
+
const result = safeParse(dateSchema, value);
|
|
7069
|
+
if (!result.success) throw new TypeError(result.issues[0].message);
|
|
7070
|
+
return result.output;
|
|
7071
|
+
};
|
|
7072
|
+
const sharedArgs = {
|
|
7073
|
+
since: {
|
|
7074
|
+
type: "custom",
|
|
7075
|
+
short: "s",
|
|
7076
|
+
description: "Filter from date (YYYYMMDD format)",
|
|
7077
|
+
parse: parseDateArg
|
|
7078
|
+
},
|
|
7079
|
+
until: {
|
|
7080
|
+
type: "custom",
|
|
7081
|
+
short: "u",
|
|
7082
|
+
description: "Filter until date (YYYYMMDD format)",
|
|
7083
|
+
parse: parseDateArg
|
|
7084
|
+
},
|
|
7085
|
+
path: {
|
|
7086
|
+
type: "string",
|
|
7087
|
+
short: "p",
|
|
7088
|
+
description: "Custom path to Claude data directory",
|
|
7089
|
+
default: getDefaultClaudePath()
|
|
7090
|
+
},
|
|
7091
|
+
json: {
|
|
7092
|
+
type: "boolean",
|
|
7093
|
+
short: "j",
|
|
7094
|
+
description: "Output in JSON format",
|
|
7095
|
+
default: false
|
|
7096
|
+
}
|
|
7097
|
+
};
|
|
7098
|
+
|
|
6827
7099
|
//#endregion
|
|
6828
7100
|
//#region utils.ts
|
|
6829
7101
|
const formatNumber = (num) => {
|
|
@@ -6840,28 +7112,7 @@ var import_picocolors$1 = __toESM(require_picocolors(), 1);
|
|
|
6840
7112
|
const dailyCommand = define({
|
|
6841
7113
|
name: "daily",
|
|
6842
7114
|
description: "Show usage report grouped by date",
|
|
6843
|
-
args:
|
|
6844
|
-
since: {
|
|
6845
|
-
type: "string",
|
|
6846
|
-
short: "s",
|
|
6847
|
-
description: "Filter from date (YYYYMMDD format)"
|
|
6848
|
-
},
|
|
6849
|
-
until: {
|
|
6850
|
-
type: "string",
|
|
6851
|
-
short: "u",
|
|
6852
|
-
description: "Filter until date (YYYYMMDD format)"
|
|
6853
|
-
},
|
|
6854
|
-
path: {
|
|
6855
|
-
type: "string",
|
|
6856
|
-
short: "p",
|
|
6857
|
-
description: "Custom path to Claude data directory (default: ~/.claude)"
|
|
6858
|
-
},
|
|
6859
|
-
json: {
|
|
6860
|
-
type: "boolean",
|
|
6861
|
-
short: "j",
|
|
6862
|
-
description: "Output in JSON format"
|
|
6863
|
-
}
|
|
6864
|
-
},
|
|
7115
|
+
args: sharedArgs,
|
|
6865
7116
|
async run(ctx) {
|
|
6866
7117
|
const options = {
|
|
6867
7118
|
since: ctx.values.since,
|
|
@@ -6952,28 +7203,7 @@ var import_picocolors = __toESM(require_picocolors(), 1);
|
|
|
6952
7203
|
const sessionCommand = define({
|
|
6953
7204
|
name: "session",
|
|
6954
7205
|
description: "Show usage report grouped by conversation session",
|
|
6955
|
-
args:
|
|
6956
|
-
since: {
|
|
6957
|
-
type: "string",
|
|
6958
|
-
short: "s",
|
|
6959
|
-
description: "Filter from date (YYYYMMDD format)"
|
|
6960
|
-
},
|
|
6961
|
-
until: {
|
|
6962
|
-
type: "string",
|
|
6963
|
-
short: "u",
|
|
6964
|
-
description: "Filter until date (YYYYMMDD format)"
|
|
6965
|
-
},
|
|
6966
|
-
path: {
|
|
6967
|
-
type: "string",
|
|
6968
|
-
short: "p",
|
|
6969
|
-
description: "Custom path to Claude data directory (default: ~/.claude)"
|
|
6970
|
-
},
|
|
6971
|
-
json: {
|
|
6972
|
-
type: "boolean",
|
|
6973
|
-
short: "j",
|
|
6974
|
-
description: "Output in JSON format"
|
|
6975
|
-
}
|
|
6976
|
-
},
|
|
7206
|
+
args: sharedArgs,
|
|
6977
7207
|
async run(ctx) {
|
|
6978
7208
|
const options = {
|
|
6979
7209
|
since: ctx.values.since,
|