ccc-notifier 0.1.0 → 0.2.0
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
CHANGED
|
@@ -22,7 +22,7 @@ in 1.2k(cache 40%)/ out 480 · 📁 my-app · 今日: $1.85
|
|
|
22
22
|
- **$ と ¥ を併記** — USD と JPY の両方を毎回表示します(為替レートは自動取得 + キャッシュ + 固定フォールバックの三段構え)
|
|
23
23
|
- **プロンプト全文をローカルに履歴保存** — `~/.ccc-notifier/history.jsonl` にそのターンのプロンプト全文を保存します(外部には送信されません)
|
|
24
24
|
- **HTMLダッシュボード** — `dashboard` コマンドで、サマリー・コスト推移(**日 / 週 / 月**で切替、横スクロールで過去まで)・モデル別/プロジェクト別内訳・検索できるターン履歴を1枚の HTML(完全自己完結・ライト/ダーク対応)に書き出してブラウザで開きます。棒をクリックするとその期間が選択され、内訳・履歴が連動(「通算」で全期間)
|
|
25
|
-
- **月予算(monthly budget)** — 月に使える金額(USD)を設定すると、ダッシュボードに**当月の使用額 / 予算・使用率(%)
|
|
25
|
+
- **月予算(monthly budget)** — 月に使える金額(USD)を設定すると、ダッシュボードに**当月の使用額 / 予算・使用率(%)** をプログレスバーで表示します(`init` の対話、または `ccc-notifier budget <金額>` で設定)
|
|
26
26
|
- **OS 標準の通知機構のみ使用・追加依存ゼロ** — 通知は macOS では `osascript`、Windows では PowerShell 標準のトースト通知機能のみで送信します(node-notifier 等の外部通知ライブラリには一切依存しません)
|
|
27
27
|
- **全処理ローカル・フェイルセーフ設計** — 通知や集計の処理が失敗しても、Claude Code 本体の応答は絶対にブロックしません
|
|
28
28
|
|
|
@@ -72,7 +72,7 @@ node dist/cli.js init
|
|
|
72
72
|
|
|
73
73
|
対話形式で次の4点を聞かれます。
|
|
74
74
|
|
|
75
|
-
- 通知チャネル(OS通知のみ / Slackのみ / OS通知+Slack)
|
|
75
|
+
- 通知チャネル(OS通知のみ / Slackのみ / OS通知+Slack / 通知なし(記録・ダッシュボードのみ))
|
|
76
76
|
- コスト表示ラベル(API換算 / 実額)
|
|
77
77
|
- USD/JPY のフォールバック為替レート(既定 150円)
|
|
78
78
|
- 月の予算(USD、既定 $400。`0` で無効。ダッシュボードに当月の使用率を表示。詳細は [月予算](docs/monthly-budget.md))
|
|
@@ -95,6 +95,7 @@ CI などから非対話で `init` したい場合は次のフラグが使えま
|
|
|
95
95
|
| `--os-only` | Slack を無効化し OS通知のみにする |
|
|
96
96
|
| `--slack-webhook <url>` | Slack Incoming Webhook URL を指定して有効化 |
|
|
97
97
|
| `--slack-only` | Slack のみにする(OS 通知を無効化)。`--slack-webhook` と併用が必須 |
|
|
98
|
+
| `--no-notify` | 通知なし(記録・ダッシュボードのみ)。`--os-only` / `--slack-only` / `--slack-webhook` とは併用不可(例: `npx ccc-notifier init --yes --no-notify`。詳細は [設定](docs/configuration.md#通知なしモード記録ダッシュボードのみ--dashboard-only-mode)) |
|
|
98
99
|
| `--label <api_equivalent\|actual>` | コスト表示ラベルを指定 |
|
|
99
100
|
| `--rate <number>` | USD/JPY フォールバックレートを指定 |
|
|
100
101
|
| `--budget <USD>` | 月予算(USD)を指定(0 で無効)。未指定なら既定 **$400**(既存設定があれば維持) |
|
|
@@ -100,12 +100,13 @@ function takeValue(argv, i, prefix) {
|
|
|
100
100
|
return argv[i + 1];
|
|
101
101
|
}
|
|
102
102
|
function parseInitFlags(argv) {
|
|
103
|
-
const flags = { yes: false, osOnly: false, slackOnly: false };
|
|
103
|
+
const flags = { yes: false, osOnly: false, slackOnly: false, noNotify: false };
|
|
104
104
|
for (let i = 0; i < argv.length; i++) {
|
|
105
105
|
const a = argv[i];
|
|
106
106
|
if (a === "--yes" || a === "-y") flags.yes = true;
|
|
107
107
|
else if (a === "--os-only") flags.osOnly = true;
|
|
108
108
|
else if (a === "--slack-only") flags.slackOnly = true;
|
|
109
|
+
else if (a === "--no-notify") flags.noNotify = true;
|
|
109
110
|
else if (a === "--slack-webhook" || a.startsWith("--slack-webhook=")) {
|
|
110
111
|
flags.slackWebhook = takeValue(argv, i, "--slack-webhook");
|
|
111
112
|
if (!a.includes("=")) i++;
|
|
@@ -174,10 +175,18 @@ function mergeSettings(sPath, command) {
|
|
|
174
175
|
async function runInit(argv) {
|
|
175
176
|
const flags = parseInitFlags(argv);
|
|
176
177
|
const cfg = readConfig();
|
|
178
|
+
const initialChannel = !cfg.notify.os && !cfg.notify.slack ? "none" : cfg.notify.slack ? cfg.notify.os ? "both" : "slack" : "os";
|
|
177
179
|
cfg.notify.os = true;
|
|
178
180
|
const budgetDefault = cfg.monthlyBudgetUSD > 0 ? cfg.monthlyBudgetUSD : DEFAULT_BUDGET_USD;
|
|
179
181
|
if (flags.yes) {
|
|
180
|
-
if (flags.
|
|
182
|
+
if (flags.noNotify) {
|
|
183
|
+
if (flags.osOnly || flags.slackOnly || flags.slackWebhook !== void 0) {
|
|
184
|
+
console.error("--no-notify \u3068 --os-only / --slack-only / --slack-webhook \u306F\u540C\u6642\u306B\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093");
|
|
185
|
+
return 1;
|
|
186
|
+
}
|
|
187
|
+
cfg.notify.os = false;
|
|
188
|
+
cfg.notify.slack = null;
|
|
189
|
+
} else if (flags.slackOnly) {
|
|
181
190
|
if (flags.osOnly) {
|
|
182
191
|
console.error("--slack-only \u3068 --os-only \u306F\u540C\u6642\u306B\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093");
|
|
183
192
|
return 1;
|
|
@@ -233,9 +242,10 @@ async function runInit(argv) {
|
|
|
233
242
|
options: [
|
|
234
243
|
{ value: "os", label: "OS \u901A\u77E5\u306E\u307F" },
|
|
235
244
|
{ value: "slack", label: "Slack \u306E\u307F(OS \u901A\u77E5\u306A\u3057)" },
|
|
236
|
-
{ value: "both", label: "OS \u901A\u77E5 + Slack" }
|
|
245
|
+
{ value: "both", label: "OS \u901A\u77E5 + Slack" },
|
|
246
|
+
{ value: "none", label: "\u901A\u77E5\u306A\u3057(\u8A18\u9332\u30FB\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9\u306E\u307F)" }
|
|
237
247
|
],
|
|
238
|
-
initialValue:
|
|
248
|
+
initialValue: initialChannel
|
|
239
249
|
});
|
|
240
250
|
if (p.isCancel(channel)) {
|
|
241
251
|
p.cancel("\u30AD\u30E3\u30F3\u30BB\u30EB\u3057\u307E\u3057\u305F");
|
|
@@ -259,6 +269,7 @@ async function runInit(argv) {
|
|
|
259
269
|
cfg.notify.os = channel === "both";
|
|
260
270
|
} else {
|
|
261
271
|
cfg.notify.slack = null;
|
|
272
|
+
cfg.notify.os = channel === "os";
|
|
262
273
|
}
|
|
263
274
|
const labelChoice = await p.select({
|
|
264
275
|
message: "\u30B3\u30B9\u30C8\u8868\u793A\u30E9\u30D9\u30EB",
|
|
@@ -313,10 +324,15 @@ async function runInit(argv) {
|
|
|
313
324
|
const sPath = settingsPath();
|
|
314
325
|
const result = mergeSettings(sPath, command);
|
|
315
326
|
if (!result.ok) return 1;
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
327
|
+
const notifyDisabled = !cfg.notify.os && !cfg.notify.slack;
|
|
328
|
+
if (notifyDisabled) {
|
|
329
|
+
console.log("\u30C6\u30B9\u30C8\u901A\u77E5: \u901A\u77E5\u306A\u3057\u30E2\u30FC\u30C9\u306E\u305F\u3081\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3057\u305F");
|
|
330
|
+
} else {
|
|
331
|
+
const testRecord = makeTestRecord();
|
|
332
|
+
await notifyOS(testRecord, cfg);
|
|
333
|
+
if (cfg.notify.slack) {
|
|
334
|
+
await notifySlack(testRecord, cfg);
|
|
335
|
+
}
|
|
320
336
|
}
|
|
321
337
|
console.log("");
|
|
322
338
|
console.log(`settings \u3092\u66F4\u65B0\u3057\u307E\u3057\u305F: ${sPath}`);
|
|
@@ -324,7 +340,13 @@ async function runInit(argv) {
|
|
|
324
340
|
result.backupPath ? ` \u30D0\u30C3\u30AF\u30A2\u30C3\u30D7: ${result.backupPath}` : " (settings.json \u3092\u65B0\u898F\u4F5C\u6210\u3057\u305F\u305F\u3081\u30D0\u30C3\u30AF\u30A2\u30C3\u30D7\u306F\u3042\u308A\u307E\u305B\u3093)"
|
|
325
341
|
);
|
|
326
342
|
console.log(` \u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB: ${cccn.configFile}`);
|
|
327
|
-
|
|
343
|
+
if (notifyDisabled) {
|
|
344
|
+
console.log(
|
|
345
|
+
"\u901A\u77E5\u306A\u3057\u30E2\u30FC\u30C9\u3067\u3059\u3002Claude Code \u306E\u5229\u7528\u306F\u81EA\u52D5\u3067\u8A18\u9332\u3055\u308C\u307E\u3059\u3002\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9: npx ccc-notifier dashboard"
|
|
346
|
+
);
|
|
347
|
+
} else {
|
|
348
|
+
console.log("Claude Code \u3067\u4F55\u304B\u5B9F\u884C\u3059\u308B\u3068\u901A\u77E5\u304C\u5C4A\u304D\u307E\u3059\u3002\u78BA\u8A8D: npx ccc-notifier doctor");
|
|
349
|
+
}
|
|
328
350
|
return 0;
|
|
329
351
|
}
|
|
330
352
|
async function runUninstall(argv) {
|
package/dist/cli.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-KUJZYZSG.js";
|
|
5
5
|
import {
|
|
6
6
|
matchesMarker
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-OXMHOVUL.js";
|
|
8
8
|
import {
|
|
9
9
|
notifyOS,
|
|
10
10
|
notifySlack,
|
|
@@ -258,6 +258,11 @@ async function checkFx(cfg) {
|
|
|
258
258
|
}
|
|
259
259
|
async function checkNotification(cfg) {
|
|
260
260
|
try {
|
|
261
|
+
if (!cfg.notify.os && !cfg.notify.slack) {
|
|
262
|
+
log("ok", "\u901A\u77E5\u30C1\u30E3\u30CD\u30EB\u306F\u3059\u3079\u3066\u7121\u52B9\u3067\u3059(\u901A\u77E5\u306A\u3057\u30FB\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9\u306E\u307F\u30E2\u30FC\u30C9)\u3002\u8A18\u9332\u3068\u30C0\u30C3\u30B7\u30E5\u30DC\u30FC\u30C9\u306F\u52D5\u4F5C\u3057\u307E\u3059");
|
|
263
|
+
log("ok", "\u901A\u77E5\u3092\u6709\u52B9\u306B\u3059\u308B\u306B\u306F npx ccc-notifier init \u3092\u518D\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044");
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
261
266
|
if (isMuted()) {
|
|
262
267
|
const until = readMuteState()?.until;
|
|
263
268
|
log(
|
|
@@ -302,9 +307,6 @@ async function checkNotification(cfg) {
|
|
|
302
307
|
`Slack \u306E\u30C6\u30B9\u30C8\u901A\u77E5\u3092\u9001\u4FE1\u3057\u307E\u3057\u305F${dryRun ? dryHint : "(Slack \u30C1\u30E3\u30F3\u30CD\u30EB\u306B\u5C4A\u3044\u305F\u304B\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u5C4A\u304B\u306A\u3044\u5834\u5408\u306F error.log \u3092\u53C2\u7167)"}`
|
|
303
308
|
);
|
|
304
309
|
}
|
|
305
|
-
if (!cfg.notify.os && !cfg.notify.slack) {
|
|
306
|
-
log("warn", "OS\u30FBSlack \u3068\u3082\u7121\u52B9\u306A\u305F\u3081\u3001\u30C6\u30B9\u30C8\u901A\u77E5\u306F\u9001\u4FE1\u3057\u3066\u3044\u307E\u305B\u3093");
|
|
307
|
-
}
|
|
308
310
|
return true;
|
|
309
311
|
} catch (err) {
|
|
310
312
|
log("warn", `\u30C6\u30B9\u30C8\u901A\u77E5\u306E\u9001\u4FE1\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${errMessage(err)}`);
|
|
@@ -630,18 +632,18 @@ async function main(argv) {
|
|
|
630
632
|
case "track": {
|
|
631
633
|
const text = await readStdin();
|
|
632
634
|
try {
|
|
633
|
-
const trackMod = await import("./track-
|
|
635
|
+
const trackMod = await import("./track-76Q5CZM5.js");
|
|
634
636
|
await trackMod.runTrack(text);
|
|
635
637
|
} catch {
|
|
636
638
|
}
|
|
637
639
|
return 0;
|
|
638
640
|
}
|
|
639
641
|
case "init": {
|
|
640
|
-
const { runInit } = await import("./setup-
|
|
642
|
+
const { runInit } = await import("./setup-IXPUR4CM.js");
|
|
641
643
|
return await runInit(rest);
|
|
642
644
|
}
|
|
643
645
|
case "uninstall": {
|
|
644
|
-
const { runUninstall } = await import("./setup-
|
|
646
|
+
const { runUninstall } = await import("./setup-IXPUR4CM.js");
|
|
645
647
|
return await runUninstall(rest);
|
|
646
648
|
}
|
|
647
649
|
case "doctor":
|
|
@@ -135,7 +135,7 @@ async function runTrack(stdinText) {
|
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
const tasks = [];
|
|
138
|
-
if (record.costUSD >= cfg.minNotifyUSD && !isMuted()) {
|
|
138
|
+
if ((cfg.notify.os || cfg.notify.slack !== null) && record.costUSD >= cfg.minNotifyUSD && !isMuted()) {
|
|
139
139
|
const todayUSD = cfg.includeDailyTotal ? todayTotalUSD() : void 0;
|
|
140
140
|
tasks.push(notifyOS(record, cfg, todayUSD));
|
|
141
141
|
tasks.push(notifySlack(record, cfg, todayUSD));
|