@codacy/verity-cli 0.20.2 → 0.21.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 +14 -2
- package/bin/verity.js +137 -1
- package/data/skills/verity-setup/SKILL.md +55 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,13 +24,25 @@ source ~/.zshrc
|
|
|
24
24
|
npm install -g @codacy/verity-cli
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
## Upgrade
|
|
27
|
+
## Upgrade
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
30
|
npm install -g @codacy/verity-cli@latest
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
Existing projects
|
|
33
|
+
Existing projects keep working — new compound features (knowledge extraction, graph memory, pre-work injection) activate automatically.
|
|
34
|
+
|
|
35
|
+
### Coming from GATE.md (`@codacy/gate-cli`)?
|
|
36
|
+
|
|
37
|
+
GATE.md is now Verity. One-time switch:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm rm -g @codacy/gate-cli
|
|
41
|
+
npm install -g @codacy/verity-cli
|
|
42
|
+
verity init # per project — moves .gate→.verity, keeps your token, Standard & memory
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
No re-setup needed: your token, Standard, and run history all carry over.
|
|
34
46
|
|
|
35
47
|
## Quick reference
|
|
36
48
|
|
package/bin/verity.js
CHANGED
|
@@ -15800,8 +15800,143 @@ function registerRunCommand(program2) {
|
|
|
15800
15800
|
});
|
|
15801
15801
|
}
|
|
15802
15802
|
|
|
15803
|
+
// src/lib/telemetry.ts
|
|
15804
|
+
var import_promises13 = require("node:fs/promises");
|
|
15805
|
+
var import_node_path18 = require("node:path");
|
|
15806
|
+
var SETTINGS_LOCAL_FILE2 = ".claude/settings.local.json";
|
|
15807
|
+
var GITIGNORE_FILE = ".gitignore";
|
|
15808
|
+
var GITIGNORE_ENTRY = ".claude/settings.local.json";
|
|
15809
|
+
function deriveOtlpEndpoint(serviceUrl) {
|
|
15810
|
+
return serviceUrl.replace(/\/+$/, "").replace(/\/v1$/, "") + "/v1/otlp";
|
|
15811
|
+
}
|
|
15812
|
+
function buildTelemetryEnv(serviceUrl, token) {
|
|
15813
|
+
return {
|
|
15814
|
+
CLAUDE_CODE_ENABLE_TELEMETRY: "1",
|
|
15815
|
+
OTEL_METRICS_EXPORTER: "otlp",
|
|
15816
|
+
OTEL_TRACES_EXPORTER: "otlp",
|
|
15817
|
+
CLAUDE_CODE_ENHANCED_TELEMETRY_BETA: "1",
|
|
15818
|
+
OTEL_EXPORTER_OTLP_PROTOCOL: "http/json",
|
|
15819
|
+
OTEL_EXPORTER_OTLP_ENDPOINT: deriveOtlpEndpoint(serviceUrl),
|
|
15820
|
+
// <token> is whatever is in .verity/credentials — verity_ OR legacy gate_.
|
|
15821
|
+
// The server hashes the raw token regardless of prefix.
|
|
15822
|
+
OTEL_EXPORTER_OTLP_HEADERS: `Authorization=Bearer ${token}`,
|
|
15823
|
+
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE: "delta",
|
|
15824
|
+
OTEL_LOG_USER_PROMPTS: "0",
|
|
15825
|
+
OTEL_LOG_TOOL_DETAILS: "0",
|
|
15826
|
+
OTEL_LOG_TOOL_CONTENT: "0",
|
|
15827
|
+
OTEL_METRICS_INCLUDE_SESSION_ID: "true",
|
|
15828
|
+
OTEL_METRICS_INCLUDE_ACCOUNT_UUID: "false",
|
|
15829
|
+
OTEL_METRICS_INCLUDE_VERSION: "false",
|
|
15830
|
+
OTEL_METRIC_EXPORT_INTERVAL: "60000"
|
|
15831
|
+
};
|
|
15832
|
+
}
|
|
15833
|
+
var VERITY_TELEMETRY_KEYS = Object.keys(buildTelemetryEnv("", ""));
|
|
15834
|
+
async function readSettingsLocal() {
|
|
15835
|
+
try {
|
|
15836
|
+
return JSON.parse(await (0, import_promises13.readFile)(projectPath(SETTINGS_LOCAL_FILE2), "utf-8"));
|
|
15837
|
+
} catch {
|
|
15838
|
+
return {};
|
|
15839
|
+
}
|
|
15840
|
+
}
|
|
15841
|
+
async function writeSettingsLocal(settings) {
|
|
15842
|
+
const file = projectPath(SETTINGS_LOCAL_FILE2);
|
|
15843
|
+
await (0, import_promises13.mkdir)((0, import_node_path18.dirname)(file), { recursive: true });
|
|
15844
|
+
await (0, import_promises13.writeFile)(file, JSON.stringify(settings, null, 2) + "\n");
|
|
15845
|
+
}
|
|
15846
|
+
async function ensureGitignore() {
|
|
15847
|
+
const file = projectPath(GITIGNORE_FILE);
|
|
15848
|
+
let content = "";
|
|
15849
|
+
try {
|
|
15850
|
+
content = await (0, import_promises13.readFile)(file, "utf-8");
|
|
15851
|
+
} catch {
|
|
15852
|
+
}
|
|
15853
|
+
const lines = content.split("\n").map((l) => l.trim());
|
|
15854
|
+
if (lines.includes(GITIGNORE_ENTRY) || lines.includes(".claude/") || lines.includes(".claude")) {
|
|
15855
|
+
return;
|
|
15856
|
+
}
|
|
15857
|
+
const block = "# Verity telemetry \u2014 holds your project token\n" + GITIGNORE_ENTRY + "\n";
|
|
15858
|
+
const next = content ? content + (content.endsWith("\n") ? "" : "\n") + "\n" + block : block;
|
|
15859
|
+
await (0, import_promises13.writeFile)(file, next);
|
|
15860
|
+
}
|
|
15861
|
+
async function installTelemetry(serviceUrl, token) {
|
|
15862
|
+
const env = buildTelemetryEnv(serviceUrl, token);
|
|
15863
|
+
const settings = await readSettingsLocal();
|
|
15864
|
+
settings.env = { ...settings.env ?? {}, ...env };
|
|
15865
|
+
await writeSettingsLocal(settings);
|
|
15866
|
+
await ensureGitignore();
|
|
15867
|
+
return { ok: true, data: { endpoint: env.OTEL_EXPORTER_OTLP_ENDPOINT } };
|
|
15868
|
+
}
|
|
15869
|
+
async function checkTelemetry() {
|
|
15870
|
+
const env = (await readSettingsLocal()).env ?? {};
|
|
15871
|
+
const enabled = env.CLAUDE_CODE_ENABLE_TELEMETRY === "1" && !!env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
15872
|
+
return { enabled, endpoint: env.OTEL_EXPORTER_OTLP_ENDPOINT ?? null, settingsPath: SETTINGS_LOCAL_FILE2 };
|
|
15873
|
+
}
|
|
15874
|
+
async function uninstallTelemetry() {
|
|
15875
|
+
const settings = await readSettingsLocal();
|
|
15876
|
+
if (!settings.env) return { ok: true, data: { removed: 0 } };
|
|
15877
|
+
let removed = 0;
|
|
15878
|
+
for (const key of VERITY_TELEMETRY_KEYS) {
|
|
15879
|
+
if (key in settings.env) {
|
|
15880
|
+
delete settings.env[key];
|
|
15881
|
+
removed++;
|
|
15882
|
+
}
|
|
15883
|
+
}
|
|
15884
|
+
if (Object.keys(settings.env).length === 0) delete settings.env;
|
|
15885
|
+
await writeSettingsLocal(settings);
|
|
15886
|
+
return { ok: true, data: { removed } };
|
|
15887
|
+
}
|
|
15888
|
+
|
|
15889
|
+
// src/commands/telemetry.ts
|
|
15890
|
+
function registerTelemetryCommands(program2) {
|
|
15891
|
+
const telemetry = program2.command("telemetry").description("Manage Claude Code OpenTelemetry export to Verity (cost & usage)");
|
|
15892
|
+
telemetry.command("install").description("Enable Claude Code telemetry export to Verity (writes .claude/settings.local.json)").action(async () => {
|
|
15893
|
+
const globals = program2.opts();
|
|
15894
|
+
const tokenResult = await resolveToken(globals.token);
|
|
15895
|
+
if (!tokenResult.ok) {
|
|
15896
|
+
printError(tokenResult.error);
|
|
15897
|
+
process.exit(1);
|
|
15898
|
+
}
|
|
15899
|
+
const urlResult = await resolveServiceUrl(globals.serviceUrl);
|
|
15900
|
+
if (!urlResult.ok) {
|
|
15901
|
+
printError(urlResult.error);
|
|
15902
|
+
process.exit(1);
|
|
15903
|
+
}
|
|
15904
|
+
const result = await installTelemetry(urlResult.data, tokenResult.data.token);
|
|
15905
|
+
if (!result.ok) {
|
|
15906
|
+
printError(result.error);
|
|
15907
|
+
process.exit(1);
|
|
15908
|
+
}
|
|
15909
|
+
printInfo(`Telemetry enabled \u2192 ${result.data.endpoint}`);
|
|
15910
|
+
printInfo(` wrote ${SETTINGS_LOCAL_FILE2} (gitignored \u2014 it holds your project token)`);
|
|
15911
|
+
printInfo(" takes effect on your NEXT Claude Code session; first metrics appear within ~60s of activity");
|
|
15912
|
+
printInfo(" view cost & usage at /usage");
|
|
15913
|
+
});
|
|
15914
|
+
telemetry.command("check").description("Show whether Claude Code telemetry export to Verity is enabled").option("--json", "Output status as JSON").action(async (opts) => {
|
|
15915
|
+
const status = await checkTelemetry();
|
|
15916
|
+
if (opts.json) {
|
|
15917
|
+
printJson(status);
|
|
15918
|
+
return;
|
|
15919
|
+
}
|
|
15920
|
+
if (status.enabled) {
|
|
15921
|
+
printInfo(`Telemetry: enabled \u2192 ${status.endpoint}`);
|
|
15922
|
+
} else {
|
|
15923
|
+
printWarn('Telemetry: disabled. Run "verity telemetry install" to enable cost & usage tracking.');
|
|
15924
|
+
}
|
|
15925
|
+
});
|
|
15926
|
+
telemetry.command("uninstall").description("Disable Claude Code telemetry export to Verity").action(async () => {
|
|
15927
|
+
const result = await uninstallTelemetry();
|
|
15928
|
+
if (!result.ok) {
|
|
15929
|
+
printError(result.error);
|
|
15930
|
+
process.exit(1);
|
|
15931
|
+
}
|
|
15932
|
+
printInfo(
|
|
15933
|
+
result.data.removed > 0 ? `Telemetry disabled (${result.data.removed} keys removed from ${SETTINGS_LOCAL_FILE2})` : "Telemetry was not enabled \u2014 nothing to remove."
|
|
15934
|
+
);
|
|
15935
|
+
});
|
|
15936
|
+
}
|
|
15937
|
+
|
|
15803
15938
|
// src/cli.ts
|
|
15804
|
-
program.name("verity").description("CLI for Verity quality gate service").version("0.
|
|
15939
|
+
program.name("verity").description("CLI for Verity quality gate service").version("0.21.0").option("--token <token>", "Override authentication token").option("--service-url <url>", "Override service URL").option("--verbose", "Log HTTP requests/responses to stderr");
|
|
15805
15940
|
registerAuthCommands(program);
|
|
15806
15941
|
registerHooksCommands(program);
|
|
15807
15942
|
registerIntentCommands(program);
|
|
@@ -15819,4 +15954,5 @@ registerReflectCommand(program);
|
|
|
15819
15954
|
registerMemoryCommand(program);
|
|
15820
15955
|
registerRunCommand(program);
|
|
15821
15956
|
registerMigrateCommand(program);
|
|
15957
|
+
registerTelemetryCommands(program);
|
|
15822
15958
|
program.parse();
|
|
@@ -75,6 +75,36 @@ Default to `balanced` if the user says "default" or doesn't specify a preference
|
|
|
75
75
|
|
|
76
76
|
---
|
|
77
77
|
|
|
78
|
+
## Step 3b: Ask about cost & usage telemetry (opt-in)
|
|
79
|
+
|
|
80
|
+
Cost & usage observability is **opt-in** and **required** for the `/usage` dashboard — all
|
|
81
|
+
cost and token data comes from Claude Code's own OpenTelemetry export, so with telemetry off
|
|
82
|
+
the dashboard stays empty.
|
|
83
|
+
|
|
84
|
+
First check the current state (so you don't re-ask if it's already on):
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
verity telemetry check
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
- If it reports **enabled**, don't re-ask — tell the user telemetry is already on and continue
|
|
91
|
+
(mention `verity telemetry uninstall` only if they want to turn it off).
|
|
92
|
+
- If **disabled**, use the **AskUserQuestion** tool:
|
|
93
|
+
|
|
94
|
+
> **Enable Claude Code cost & usage telemetry for this project?**
|
|
95
|
+
> Verity can show cost, tokens, a per-agent / per-session / model breakdown, and a fleet cost
|
|
96
|
+
> tree — by receiving Claude Code's built-in **OpenTelemetry** export. This sends usage
|
|
97
|
+
> **metrics and traces only** (model names, token counts, USD cost, agent types, session IDs).
|
|
98
|
+
> It does **NOT** send your prompts, code, or tool input/output. Without it, the `/usage`
|
|
99
|
+
> dashboard stays empty.
|
|
100
|
+
> - **Yes** (recommended) — enable telemetry
|
|
101
|
+
> - **No** — skip (you can enable later with `verity telemetry install`)
|
|
102
|
+
|
|
103
|
+
Remember the answer; you act on it in Step 7b (the token must exist first). **Declining is
|
|
104
|
+
fine and reversible** — nothing is written, and the next `/verity-setup` re-offers it.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
78
108
|
## Step 4: Synthesize the Standard
|
|
79
109
|
|
|
80
110
|
Read `.claude/skills/verity-setup/patterns-reference.yaml` and `.claude/skills/verity-setup/standard-template.yaml` from the project root.
|
|
@@ -301,6 +331,25 @@ This derives a small set of descriptive memory nodes from what you already analy
|
|
|
301
331
|
|
|
302
332
|
---
|
|
303
333
|
|
|
334
|
+
## Step 7b: Enable telemetry (only if the user opted in at Step 3b)
|
|
335
|
+
|
|
336
|
+
If — and only if — the user said **Yes** in Step 3b, enable the Claude Code telemetry export
|
|
337
|
+
now (the token from Step 6 must already exist):
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
verity telemetry install
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
This writes the `OTEL_*` env block to the gitignored `.claude/settings.local.json` (which
|
|
344
|
+
holds your token) and points Claude Code's OpenTelemetry exporter at Verity's OTLP endpoint.
|
|
345
|
+
Tell the user it takes effect on their **next** Claude Code session, that first metrics appear
|
|
346
|
+
within ~60s of activity, and point them at `/usage`.
|
|
347
|
+
|
|
348
|
+
If the user declined, skip this step and note that `/usage` will stay empty until they run
|
|
349
|
+
`verity telemetry install`.
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
304
353
|
## Step 8: Generate VERITY.md file
|
|
305
354
|
|
|
306
355
|
Create `VERITY.md` at the project root with this content:
|
|
@@ -404,8 +453,12 @@ Add these entries to `.gitignore` (create it if it doesn't exist, append if it d
|
|
|
404
453
|
.verity/.last-intent
|
|
405
454
|
.verity/.memory-sync-state.json
|
|
406
455
|
.verity/memory/log.md
|
|
456
|
+
.claude/settings.local.json
|
|
407
457
|
```
|
|
408
458
|
|
|
459
|
+
`.claude/settings.local.json` holds the telemetry env block **including your token**, so it
|
|
460
|
+
must never be committed (`verity telemetry install` also adds this entry automatically).
|
|
461
|
+
|
|
409
462
|
Do NOT gitignore `.verity/standard.yaml` or `VERITY.md` — those should be committed.
|
|
410
463
|
|
|
411
464
|
**Commit the knowledge graph, but not its log.** The nodes under `.verity/memory/<domain>/` and `.verity/memory/index.md` are durable project knowledge meant to be committed and reviewed. But `.verity/memory/log.md` is an append-only, per-run timestamped activity log — it churns on every analysis and carries no reviewable content, so it is gitignored above. If a project already committed it, untrack it once with `git rm --cached .verity/memory/log.md`.
|
|
@@ -431,12 +484,14 @@ Standard: v1 (4 quality, 7 security, N custom patterns)
|
|
|
431
484
|
Tools: ${TOOL_LIST}
|
|
432
485
|
Service: registered (project_id: ${PROJECT_ID})
|
|
433
486
|
Hooks: installed (verity analyze + verity intent capture)
|
|
487
|
+
Telemetry: ${TELEMETRY_STATUS} (enabled → cost+usage at /usage, or disabled)
|
|
434
488
|
|
|
435
489
|
Files created:
|
|
436
490
|
.verity/standard.yaml — Quality standard
|
|
437
491
|
.codacy/codacy.config.json — Analysis CLI config
|
|
438
492
|
VERITY.md — Project quality overview
|
|
439
493
|
.claude/settings.json — Hook configuration (verified)
|
|
494
|
+
.claude/settings.local.json — Telemetry env (only if enabled; gitignored)
|
|
440
495
|
.gitignore — Updated with Verity entries
|
|
441
496
|
|
|
442
497
|
Next: You should now be seeing the first analysis happening below. The hook will fire automatically every time your agent stops working on something.
|