@usevalt/cli 0.6.0 → 0.7.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/dist/index.js +94 -36
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -499,16 +499,36 @@ var doctorCommand = new Command5("doctor").description("Check Valt configuration
|
|
|
499
499
|
warn("Signing keys: not configured (using ephemeral keys \u2014 certificates will not survive restart)");
|
|
500
500
|
issues++;
|
|
501
501
|
}
|
|
502
|
+
const EXPECTED_HOOKS = [
|
|
503
|
+
"SessionStart",
|
|
504
|
+
"PreToolUse",
|
|
505
|
+
"PostToolUse",
|
|
506
|
+
"PostToolUseFailure",
|
|
507
|
+
"SubagentStart",
|
|
508
|
+
"SubagentStop",
|
|
509
|
+
"UserPromptSubmit",
|
|
510
|
+
"SessionEnd"
|
|
511
|
+
];
|
|
502
512
|
const hooksPath = `${process.env["HOME"] ?? "~"}/.claude/hooks.json`;
|
|
503
513
|
try {
|
|
504
514
|
const { existsSync: exists, readFileSync: read } = await import("fs");
|
|
505
515
|
if (exists(hooksPath)) {
|
|
506
516
|
const hooksContent = read(hooksPath, "utf-8");
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
|
|
517
|
+
const hooksConfig = JSON.parse(hooksContent);
|
|
518
|
+
const registeredHooks = hooksConfig.hooks ?? {};
|
|
519
|
+
const presentHooks = EXPECTED_HOOKS.filter((name) => {
|
|
520
|
+
const hookEntries = registeredHooks[name];
|
|
521
|
+
return Array.isArray(hookEntries) && JSON.stringify(hookEntries).includes("valt");
|
|
522
|
+
});
|
|
523
|
+
const missingHooks = EXPECTED_HOOKS.filter((h) => !presentHooks.includes(h));
|
|
524
|
+
if (missingHooks.length === 0) {
|
|
525
|
+
success(`Claude Code hooks: all ${EXPECTED_HOOKS.length} registered`);
|
|
526
|
+
} else if (presentHooks.length === 0) {
|
|
527
|
+
info("Claude Code hooks: not installed. Run `valt setup` to enable.");
|
|
510
528
|
} else {
|
|
511
|
-
warn(
|
|
529
|
+
warn(
|
|
530
|
+
`Claude Code hooks: ${presentHooks.length}/${EXPECTED_HOOKS.length} registered. Missing: ${missingHooks.join(", ")}. Run \`valt setup\` to update.`
|
|
531
|
+
);
|
|
512
532
|
issues++;
|
|
513
533
|
}
|
|
514
534
|
} else {
|
|
@@ -1685,11 +1705,12 @@ var hookCommand = new Command13("hook").description("Claude Code hook handlers f
|
|
|
1685
1705
|
|
|
1686
1706
|
// src/commands/setup.ts
|
|
1687
1707
|
import { Command as Command14 } from "commander";
|
|
1688
|
-
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync2, existsSync as existsSync4 } from "fs";
|
|
1708
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync2, existsSync as existsSync4, unlinkSync as unlinkSync3 } from "fs";
|
|
1689
1709
|
import { join as join2 } from "path";
|
|
1690
1710
|
import os3 from "os";
|
|
1691
1711
|
var CLAUDE_DIR = join2(os3.homedir(), ".claude");
|
|
1692
|
-
var
|
|
1712
|
+
var SETTINGS_FILE = join2(CLAUDE_DIR, "settings.json");
|
|
1713
|
+
var LEGACY_HOOKS_FILE = join2(CLAUDE_DIR, "hooks.json");
|
|
1693
1714
|
var HOOK_PREFIX = "npx --yes @usevalt/cli";
|
|
1694
1715
|
function getValtHooks() {
|
|
1695
1716
|
return {
|
|
@@ -1794,17 +1815,17 @@ var setupCommand = new Command14("setup").description("Configure Claude Code hoo
|
|
|
1794
1815
|
removeHooks();
|
|
1795
1816
|
return;
|
|
1796
1817
|
}
|
|
1797
|
-
let config = {
|
|
1798
|
-
if (existsSync4(
|
|
1818
|
+
let config = {};
|
|
1819
|
+
if (existsSync4(SETTINGS_FILE)) {
|
|
1799
1820
|
try {
|
|
1800
|
-
const raw = readFileSync4(
|
|
1821
|
+
const raw = readFileSync4(SETTINGS_FILE, "utf-8");
|
|
1801
1822
|
config = JSON.parse(raw);
|
|
1802
|
-
if (!config.hooks) config.hooks = {};
|
|
1803
1823
|
} catch {
|
|
1804
|
-
warn("Could not parse existing
|
|
1805
|
-
config = {
|
|
1824
|
+
warn("Could not parse existing settings.json. Will merge hooks into it.");
|
|
1825
|
+
config = {};
|
|
1806
1826
|
}
|
|
1807
1827
|
}
|
|
1828
|
+
if (!config.hooks) config.hooks = {};
|
|
1808
1829
|
const valtHooks = getValtHooks();
|
|
1809
1830
|
for (const [event, hooks] of Object.entries(valtHooks)) {
|
|
1810
1831
|
const existing = config.hooks[event];
|
|
@@ -1820,12 +1841,19 @@ var setupCommand = new Command14("setup").description("Configure Claude Code hoo
|
|
|
1820
1841
|
config.hooks[event] = hooks;
|
|
1821
1842
|
}
|
|
1822
1843
|
}
|
|
1823
|
-
writeFileSync4(
|
|
1844
|
+
writeFileSync4(SETTINGS_FILE, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
1845
|
+
if (existsSync4(LEGACY_HOOKS_FILE)) {
|
|
1846
|
+
try {
|
|
1847
|
+
removeLegacyHooks();
|
|
1848
|
+
info(`Migrated hooks from legacy hooks.json to settings.json.`);
|
|
1849
|
+
} catch {
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1824
1852
|
success("Claude Code hooks configured.");
|
|
1825
1853
|
info("");
|
|
1826
1854
|
info("Every Claude Code session will now be tracked by Valt.");
|
|
1827
1855
|
info(`Projects are auto-detected from git repo name or folder name.`);
|
|
1828
|
-
info(`Hooks written to: ${dim(
|
|
1856
|
+
info(`Hooks written to: ${dim(SETTINGS_FILE)}`);
|
|
1829
1857
|
info("");
|
|
1830
1858
|
info("To remove: valt setup --remove");
|
|
1831
1859
|
} catch (err) {
|
|
@@ -1833,34 +1861,64 @@ var setupCommand = new Command14("setup").description("Configure Claude Code hoo
|
|
|
1833
1861
|
process.exit(1);
|
|
1834
1862
|
}
|
|
1835
1863
|
});
|
|
1836
|
-
function
|
|
1837
|
-
if (!
|
|
1838
|
-
|
|
1839
|
-
|
|
1864
|
+
function removeValtHooksFromConfig(config) {
|
|
1865
|
+
if (!config.hooks) return;
|
|
1866
|
+
for (const event of Object.keys(config.hooks)) {
|
|
1867
|
+
const entries = config.hooks[event];
|
|
1868
|
+
if (!Array.isArray(entries)) continue;
|
|
1869
|
+
config.hooks[event] = entries.filter((h) => {
|
|
1870
|
+
const entry = h;
|
|
1871
|
+
return !entry.hooks?.some((hk) => hk.command?.includes("valt") && hk.command?.includes("hook"));
|
|
1872
|
+
});
|
|
1873
|
+
if (config.hooks[event].length === 0) {
|
|
1874
|
+
delete config.hooks[event];
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
if (Object.keys(config.hooks).length === 0) {
|
|
1878
|
+
delete config.hooks;
|
|
1840
1879
|
}
|
|
1880
|
+
}
|
|
1881
|
+
function removeLegacyHooks() {
|
|
1882
|
+
if (!existsSync4(LEGACY_HOOKS_FILE)) return;
|
|
1841
1883
|
try {
|
|
1842
|
-
const raw = readFileSync4(
|
|
1884
|
+
const raw = readFileSync4(LEGACY_HOOKS_FILE, "utf-8");
|
|
1843
1885
|
const config = JSON.parse(raw);
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
config.hooks[event] = entries.filter((h) => {
|
|
1852
|
-
const entry = h;
|
|
1853
|
-
return !entry.hooks?.some((hk) => hk.command?.includes("valt") && hk.command?.includes("hook"));
|
|
1854
|
-
});
|
|
1855
|
-
if (config.hooks[event].length === 0) {
|
|
1856
|
-
delete config.hooks[event];
|
|
1886
|
+
removeValtHooksFromConfig(config);
|
|
1887
|
+
if (!config.hooks || Object.keys(config.hooks).length === 0) {
|
|
1888
|
+
const remaining = Object.keys(config).filter((k) => k !== "hooks");
|
|
1889
|
+
if (remaining.length === 0) {
|
|
1890
|
+
unlinkSync3(LEGACY_HOOKS_FILE);
|
|
1891
|
+
} else {
|
|
1892
|
+
writeFileSync4(LEGACY_HOOKS_FILE, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
1857
1893
|
}
|
|
1894
|
+
} else {
|
|
1895
|
+
writeFileSync4(LEGACY_HOOKS_FILE, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
1858
1896
|
}
|
|
1859
|
-
writeFileSync4(HOOKS_FILE, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
1860
|
-
success("Valt hooks removed from Claude Code.");
|
|
1861
1897
|
} catch {
|
|
1862
|
-
|
|
1863
|
-
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
function removeHooks() {
|
|
1901
|
+
if (existsSync4(SETTINGS_FILE)) {
|
|
1902
|
+
try {
|
|
1903
|
+
const raw = readFileSync4(SETTINGS_FILE, "utf-8");
|
|
1904
|
+
const config = JSON.parse(raw);
|
|
1905
|
+
removeValtHooksFromConfig(config);
|
|
1906
|
+
writeFileSync4(SETTINGS_FILE, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
1907
|
+
success("Valt hooks removed from Claude Code settings.");
|
|
1908
|
+
} catch {
|
|
1909
|
+
error("Could not parse settings.json.");
|
|
1910
|
+
process.exit(1);
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
if (existsSync4(LEGACY_HOOKS_FILE)) {
|
|
1914
|
+
try {
|
|
1915
|
+
removeLegacyHooks();
|
|
1916
|
+
info("Legacy hooks.json cleaned up.");
|
|
1917
|
+
} catch {
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
if (!existsSync4(SETTINGS_FILE) && !existsSync4(LEGACY_HOOKS_FILE)) {
|
|
1921
|
+
info("No hooks configured. Nothing to remove.");
|
|
1864
1922
|
}
|
|
1865
1923
|
}
|
|
1866
1924
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usevalt/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Valt CLI — trust layer for AI-assisted development",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"tsup": "^8.4.0",
|
|
40
40
|
"typescript": "^5.7.0",
|
|
41
41
|
"vitest": "^3.2.0",
|
|
42
|
-
"@usevalt/
|
|
43
|
-
"@usevalt/
|
|
42
|
+
"@usevalt/typescript-config": "0.0.0",
|
|
43
|
+
"@usevalt/eslint-config": "0.0.0"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "tsup",
|