caveat-cli 0.4.0 → 0.6.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 +31 -5
- package/dist/index.js +6 -105
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# caveat-cli
|
|
2
2
|
|
|
3
|
-
External spec gotcha knowledge base CLI — markdown + SQLite FTS5 + MCP server + Claude Code hooks.
|
|
3
|
+
External spec gotcha knowledge base CLI — markdown + SQLite FTS5 + MCP server + Claude Code hooks, with a shared community knowledge DB out of the box.
|
|
4
4
|
|
|
5
5
|
**Source / full docs**: https://github.com/kitepon-rgb/Caveat
|
|
6
6
|
|
|
@@ -11,22 +11,48 @@ npm install -g caveat-cli
|
|
|
11
11
|
caveat init
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
`caveat init`
|
|
14
|
+
`caveat init` (idempotent, `--dry-run` supported) does 4 things:
|
|
15
|
+
|
|
16
|
+
1. Scaffolds `~/.caveat/own/` (your personal knowledge repo) + `~/.caveat/index/caveat.db`
|
|
17
|
+
2. **Subscribes you to the shared community DB** (`kitepon-rgb/Caveat` by default) — shallow-clones into `~/.caveat/community/Caveat/` and indexes so other users' caveats are immediately searchable
|
|
18
|
+
3. Registers the MCP server with Claude Code (`claude mcp add --scope user`)
|
|
19
|
+
4. Merges `UserPromptSubmit` / `Stop` hooks into `~/.claude/settings.json` (existing entries preserved, backup written before any change)
|
|
20
|
+
|
|
21
|
+
Opt-out flags: `--skip-claude`, `--skip-shared`. `caveat uninstall` reverses the Claude Code changes without touching `~/.caveat/`.
|
|
15
22
|
|
|
16
23
|
## Basic usage
|
|
17
24
|
|
|
18
25
|
```sh
|
|
19
|
-
caveat search "rtx" # FTS
|
|
26
|
+
caveat search "rtx" # FTS across your own entries + the shared community DB
|
|
20
27
|
caveat list # recent entries
|
|
28
|
+
caveat pull # fetch new community contributions + re-index
|
|
29
|
+
caveat push <entry-id> # contribute your entry via fork + PR (requires gh CLI)
|
|
21
30
|
caveat serve # http://localhost:4242 read-only portal
|
|
22
|
-
caveat community add <url> #
|
|
31
|
+
caveat community add <url> # subscribe to an additional community repo
|
|
23
32
|
caveat uninstall # reverse `caveat init` Claude integration
|
|
24
33
|
```
|
|
25
34
|
|
|
35
|
+
## MCP tools (7)
|
|
36
|
+
|
|
37
|
+
Exposed to Claude Code via the MCP server that `caveat init` registers:
|
|
38
|
+
|
|
39
|
+
`caveat_search`, `caveat_get`, `caveat_record`, `caveat_update`, `caveat_list_recent`, `caveat_pull`, `caveat_push`.
|
|
40
|
+
|
|
41
|
+
Claude can autonomously pull community updates (safe, idempotent) and push your recorded caveats (gated by Claude Code's tool permission prompt for user consent — contribution is a public action).
|
|
42
|
+
|
|
43
|
+
## Pointing at a different shared DB
|
|
44
|
+
|
|
45
|
+
For an internal/enterprise shared knowledge pool, override in `~/.caveatrc.json`:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{ "sharedRepo": "https://github.com/your-org/your-caveats" }
|
|
49
|
+
```
|
|
50
|
+
|
|
26
51
|
## Requirements
|
|
27
52
|
|
|
28
53
|
- Node 22.5+ (for built-in `node:sqlite`)
|
|
29
|
-
-
|
|
54
|
+
- `gh` CLI authenticated (`gh auth login`) if you want to use `caveat push`
|
|
55
|
+
- Claude Code installed if you want MCP / hooks integration. Without it, `caveat init --skip-claude` still provisions local state + shared DB
|
|
30
56
|
|
|
31
57
|
## License
|
|
32
58
|
|
package/dist/index.js
CHANGED
|
@@ -15948,8 +15948,7 @@ function recordEntry(input, opts) {
|
|
|
15948
15948
|
source_session: generateSourceSession(now),
|
|
15949
15949
|
created_at: ymd,
|
|
15950
15950
|
updated_at: ymd,
|
|
15951
|
-
last_verified: ymd
|
|
15952
|
-
...input.brief_id !== void 0 ? { brief_id: input.brief_id } : {}
|
|
15951
|
+
last_verified: ymd
|
|
15953
15952
|
};
|
|
15954
15953
|
const sections = {};
|
|
15955
15954
|
if (input.context !== void 0) sections["Context"] = input.context;
|
|
@@ -15996,8 +15995,7 @@ var IMMUTABLE_KEYS = /* @__PURE__ */ new Set([
|
|
|
15996
15995
|
"id",
|
|
15997
15996
|
"created_at",
|
|
15998
15997
|
"source_session",
|
|
15999
|
-
"source_project"
|
|
16000
|
-
"brief_id"
|
|
15998
|
+
"source_project"
|
|
16001
15999
|
]);
|
|
16002
16000
|
function updateEntry(id, patch, opts) {
|
|
16003
16001
|
const source = opts.source ?? "own";
|
|
@@ -16035,9 +16033,6 @@ function updateEntry(id, patch, opts) {
|
|
|
16035
16033
|
if (patch.frontmatter?.tags !== void 0) {
|
|
16036
16034
|
mergedFrontmatter.tags = patch.frontmatter.tags;
|
|
16037
16035
|
}
|
|
16038
|
-
if (parsed.frontmatter.brief_id !== void 0) {
|
|
16039
|
-
mergedFrontmatter.brief_id = parsed.frontmatter.brief_id;
|
|
16040
|
-
}
|
|
16041
16036
|
const mergedSections = { ...parsed.sections };
|
|
16042
16037
|
if (patch.sections) {
|
|
16043
16038
|
for (const [heading2, content] of Object.entries(patch.sections)) {
|
|
@@ -16077,39 +16072,6 @@ function formatYmd2(d) {
|
|
|
16077
16072
|
return `${yyyy}-${mm}-${dd}`;
|
|
16078
16073
|
}
|
|
16079
16074
|
|
|
16080
|
-
// ../../packages/core/dist/brief.js
|
|
16081
|
-
function generateBrief(db, topic, limit = 10) {
|
|
16082
|
-
const related = topic.trim().length > 0 ? search(db, { query: topic, limit }) : [];
|
|
16083
|
-
const brief_id = `brf-${Date.now().toString(36)}-${randomHex(8)}`;
|
|
16084
|
-
const lines = [];
|
|
16085
|
-
lines.push(`# \u8ABF\u67FB\u4F9D\u983C: ${topic}`);
|
|
16086
|
-
lines.push("");
|
|
16087
|
-
lines.push("## \u4F9D\u983C\u306E\u80CC\u666F");
|
|
16088
|
-
lines.push(
|
|
16089
|
-
`\u4EE5\u4E0B\u306E\u8A71\u984C\u306B\u3064\u3044\u3066\u3001\u4E00\u6B21\u30BD\u30FC\u30B9\u4E2D\u5FC3\u3067\u8ABF\u67FB\u3057\u3066\u304F\u3060\u3055\u3044: ${topic}`
|
|
16090
|
-
);
|
|
16091
|
-
lines.push("");
|
|
16092
|
-
if (related.length > 0) {
|
|
16093
|
-
lines.push("## \u65E2\u5B58\u306E\u95A2\u9023 caveat\uFF08\u53C2\u8003\uFF09");
|
|
16094
|
-
for (const r2 of related) {
|
|
16095
|
-
lines.push(`- \`${r2.id}\` (${r2.confidence}) ${r2.title}`);
|
|
16096
|
-
}
|
|
16097
|
-
lines.push("");
|
|
16098
|
-
}
|
|
16099
|
-
lines.push("## \u6C42\u3081\u305F\u3044\u60C5\u5831");
|
|
16100
|
-
lines.push("1. \u516C\u5F0F\u4ED5\u69D8 (RFC / \u4ED5\u69D8\u66F8 / \u30D9\u30F3\u30C0\u30FC\u516C\u5F0F\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8) \u2014 \u30D0\u30FC\u30B8\u30E7\u30F3\u660E\u8A18");
|
|
16101
|
-
lines.push("2. \u65E2\u77E5\u306E\u843D\u3068\u3057\u7A74 (\u30D0\u30FC\u30B8\u30E7\u30F3\u4F9D\u5B58\u3001\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u5DEE\u7570\u3001\u65E2\u5831\u306E\u4E0D\u5177\u5408)");
|
|
16102
|
-
lines.push("3. \u56DE\u907F\u7B56\u3068\u4EE3\u66FF\u624B\u6BB5\uFF08\u52B9\u679C\u306E\u88CF\u53D6\u308A\u3064\u304D\uFF09");
|
|
16103
|
-
lines.push("4. \u4E00\u6B21\u30BD\u30FC\u30B9 URL\u3002\u4E8C\u6B21\u30BD\u30FC\u30B9\uFF08\u30D6\u30ED\u30B0\u7B49\uFF09\u306F\u533A\u5225\u3057\u3066\u8A18\u8F09");
|
|
16104
|
-
lines.push("");
|
|
16105
|
-
lines.push("## \u51FA\u529B\u306E\u5F62");
|
|
16106
|
-
lines.push("Symptom / Cause / Resolution / Evidence \u306E 4 \u30BB\u30AF\u30B7\u30E7\u30F3\u3067\u3001\u5F8C\u7D9A\u306E `ingest_research` \u306B\u6E21\u305B\u308B\u5F62\u5F0F\u3067\u8FD4\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
|
|
16107
|
-
lines.push("");
|
|
16108
|
-
lines.push("---");
|
|
16109
|
-
lines.push(`brief_id: ${brief_id}`);
|
|
16110
|
-
return { brief_id, text: lines.join("\n") };
|
|
16111
|
-
}
|
|
16112
|
-
|
|
16113
16075
|
// ../../packages/core/dist/paths.js
|
|
16114
16076
|
import { existsSync as existsSync4 } from "node:fs";
|
|
16115
16077
|
import { dirname as dirname3, isAbsolute, join as join5, resolve } from "node:path";
|
|
@@ -16139,7 +16101,7 @@ function resolvePaths(caveatHome, knowledgeRepo, userHome) {
|
|
|
16139
16101
|
|
|
16140
16102
|
// ../../packages/core/dist/config.js
|
|
16141
16103
|
import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
16142
|
-
var SHARED_REPO_URL = "https://github.com/kitepon-rgb/
|
|
16104
|
+
var SHARED_REPO_URL = "https://github.com/kitepon-rgb/Caveat";
|
|
16143
16105
|
var DEFAULT_CONFIG = {
|
|
16144
16106
|
knowledgeRepo: "own",
|
|
16145
16107
|
semverKeys: ["driver", "cuda", "node"],
|
|
@@ -44681,8 +44643,7 @@ var recordInputShape = {
|
|
|
44681
44643
|
visibility: visibilitySchema.optional(),
|
|
44682
44644
|
tags: external_exports.array(external_exports.string()).optional(),
|
|
44683
44645
|
environment: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
44684
|
-
category: external_exports.string().optional().describe("Directory under entries/ (e.g., gpu, claude-code). Default: misc")
|
|
44685
|
-
brief_id: external_exports.string().optional()
|
|
44646
|
+
category: external_exports.string().optional().describe("Directory under entries/ (e.g., gpu, claude-code). Default: misc")
|
|
44686
44647
|
};
|
|
44687
44648
|
function handleRecord(ctx, args) {
|
|
44688
44649
|
return recordEntry(args, {
|
|
@@ -44729,48 +44690,6 @@ function handleListRecent(ctx, args) {
|
|
|
44729
44690
|
return listRecent(ctx.db, args.limit ?? 20);
|
|
44730
44691
|
}
|
|
44731
44692
|
|
|
44732
|
-
// ../mcp/dist/tools/nlmBriefFor.js
|
|
44733
|
-
var nlmBriefForInputShape = {
|
|
44734
|
-
topic: external_exports.string().min(1),
|
|
44735
|
-
limit: external_exports.number().int().min(1).max(50).optional()
|
|
44736
|
-
};
|
|
44737
|
-
function handleNlmBriefFor(ctx, args) {
|
|
44738
|
-
return generateBrief(ctx.db, args.topic, args.limit);
|
|
44739
|
-
}
|
|
44740
|
-
|
|
44741
|
-
// ../mcp/dist/tools/ingestResearch.js
|
|
44742
|
-
var ingestResearchInputShape = {
|
|
44743
|
-
title: external_exports.string().min(1),
|
|
44744
|
-
symptom: external_exports.string().min(1),
|
|
44745
|
-
cause: external_exports.string().optional(),
|
|
44746
|
-
resolution: external_exports.string().optional(),
|
|
44747
|
-
evidence: external_exports.array(external_exports.string()).optional(),
|
|
44748
|
-
brief_id: external_exports.string().optional(),
|
|
44749
|
-
tags: external_exports.array(external_exports.string()).optional(),
|
|
44750
|
-
category: external_exports.string().optional()
|
|
44751
|
-
};
|
|
44752
|
-
function handleIngestResearch(ctx, args) {
|
|
44753
|
-
const evidenceText = args.evidence ? args.evidence.map((line) => `- ${line}`).join("\n") : "";
|
|
44754
|
-
return recordEntry(
|
|
44755
|
-
{
|
|
44756
|
-
title: args.title,
|
|
44757
|
-
symptom: args.symptom,
|
|
44758
|
-
cause: args.cause ?? "",
|
|
44759
|
-
resolution: args.resolution ?? "",
|
|
44760
|
-
evidence: evidenceText,
|
|
44761
|
-
confidence: "tentative",
|
|
44762
|
-
outcome: "resolved",
|
|
44763
|
-
tags: args.tags,
|
|
44764
|
-
category: args.category,
|
|
44765
|
-
brief_id: args.brief_id
|
|
44766
|
-
},
|
|
44767
|
-
{
|
|
44768
|
-
db: ctx.db,
|
|
44769
|
-
entriesRoot: ctx.paths.entriesDir
|
|
44770
|
-
}
|
|
44771
|
-
);
|
|
44772
|
-
}
|
|
44773
|
-
|
|
44774
44693
|
// ../mcp/dist/tools/pull.js
|
|
44775
44694
|
var pullInputShape = {};
|
|
44776
44695
|
async function handlePull(ctx, _args = {}) {
|
|
@@ -44856,7 +44775,7 @@ function registerAllTools(server, ctx) {
|
|
|
44856
44775
|
"caveat_update",
|
|
44857
44776
|
{
|
|
44858
44777
|
title: "caveat_update",
|
|
44859
|
-
description: "Patch an existing caveat. Frontmatter shallow-merges (arrays replace). Sections matched by case-insensitive H2 heading. Immutable keys: id, created_at, source_session, source_project
|
|
44778
|
+
description: "Patch an existing caveat. Frontmatter shallow-merges (arrays replace). Sections matched by case-insensitive H2 heading. Immutable keys: id, created_at, source_session, source_project.",
|
|
44860
44779
|
inputSchema: updateInputShape
|
|
44861
44780
|
},
|
|
44862
44781
|
async (args) => jsonResult(handleUpdate(ctx, args))
|
|
@@ -44870,24 +44789,6 @@ function registerAllTools(server, ctx) {
|
|
|
44870
44789
|
},
|
|
44871
44790
|
async (args) => jsonResult(handleListRecent(ctx, args))
|
|
44872
44791
|
);
|
|
44873
|
-
server.registerTool(
|
|
44874
|
-
"nlm_brief_for",
|
|
44875
|
-
{
|
|
44876
|
-
title: "nlm_brief_for",
|
|
44877
|
-
description: "Generate a NotebookLM research brief for a topic. Returns {brief_id, text}. brief_id can be passed to ingest_research when the NLM output is ready. Stateless \u2014 brief_id is not persisted until ingest_research fires.",
|
|
44878
|
-
inputSchema: nlmBriefForInputShape
|
|
44879
|
-
},
|
|
44880
|
-
async (args) => jsonResult(handleNlmBriefFor(ctx, args))
|
|
44881
|
-
);
|
|
44882
|
-
server.registerTool(
|
|
44883
|
-
"ingest_research",
|
|
44884
|
-
{
|
|
44885
|
-
title: "ingest_research",
|
|
44886
|
-
description: "Create a caveat from NotebookLM research output. Always records with confidence: tentative. Pass brief_id to link back to the originating brief.",
|
|
44887
|
-
inputSchema: ingestResearchInputShape
|
|
44888
|
-
},
|
|
44889
|
-
async (args) => jsonResult(handleIngestResearch(ctx, args))
|
|
44890
|
-
);
|
|
44891
44792
|
server.registerTool(
|
|
44892
44793
|
"caveat_pull",
|
|
44893
44794
|
{
|
|
@@ -45121,7 +45022,7 @@ function runCommunityList(ctx) {
|
|
|
45121
45022
|
|
|
45122
45023
|
// src/index.ts
|
|
45123
45024
|
var program = new Command();
|
|
45124
|
-
program.name("caveat").description("External spec gotcha knowledge base CLI").version("0.
|
|
45025
|
+
program.name("caveat").description("External spec gotcha knowledge base CLI").version("0.6.0");
|
|
45125
45026
|
program.command("init").description(
|
|
45126
45027
|
"Initialize ~/.caveatrc.json, ~/.caveat/, subscribe to the shared community DB, and register Claude Code integration"
|
|
45127
45028
|
).option("--skip-claude", "skip Claude Code MCP + hook registration", false).option("--skip-shared", "skip subscribing to the shared community DB", false).option("--dry-run", "show planned changes without writing", false).action(async (opts) => {
|