codealmanac 0.1.2 → 0.1.4
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 +53 -40
- package/dist/codealmanac.js +1331 -787
- package/dist/codealmanac.js.map +1 -1
- package/guides/mini.md +50 -14
- package/guides/reference.md +178 -91
- package/package.json +1 -1
package/guides/mini.md
CHANGED
|
@@ -43,7 +43,9 @@ The output is page slugs. Pick 1-3 that look relevant, `almanac show <slug>`, fo
|
|
|
43
43
|
|
|
44
44
|
---
|
|
45
45
|
|
|
46
|
-
## The
|
|
46
|
+
## The commands you'll use
|
|
47
|
+
|
|
48
|
+
Other commands exist (`list`, `tag`, `untag`, `hook`, `uninstall`, `doctor`, etc.) — most are administrative. See `almanac --help` or `@~/.claude/codealmanac-reference.md` for the full surface. In normal sessions you'll live in the four commands below.
|
|
47
49
|
|
|
48
50
|
### 1. `almanac search` — the starting point
|
|
49
51
|
|
|
@@ -122,32 +124,40 @@ Almost always existing. Skim `almanac topics` before creating. New topic is just
|
|
|
122
124
|
### "Can I just `almanac tag`?"
|
|
123
125
|
Yes — safe, idempotent, preserves body bytes. Use `almanac tag` / `untag` rather than hand-editing frontmatter.
|
|
124
126
|
|
|
127
|
+
### "The wiki returned nothing. Now what?"
|
|
128
|
+
Trust the silence. Empty stdout with `# 0 results` on stderr means the query ran cleanly and matched nothing — the wiki doesn't have a page on that yet, or the query needs to be broader. That is the answer, not a bug. Don't fall back to guessing; fall back to the code, and trust that capture will surface the knowledge the next time a session naturally discovers it.
|
|
129
|
+
|
|
130
|
+
If stderr shows a real error (an `almanac:` prefix or a commander parse failure), the invocation is broken — re-read `almanac --help` for the right flags.
|
|
131
|
+
|
|
125
132
|
---
|
|
126
133
|
|
|
127
134
|
## A concrete example
|
|
128
135
|
|
|
129
|
-
User: *"
|
|
136
|
+
User: *"the indexer isn't picking up my new page, what's going on?"*
|
|
130
137
|
|
|
131
138
|
```bash
|
|
132
|
-
# 1. Find
|
|
133
|
-
$ almanac search --mentions src/
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
stripe-async-migration
|
|
139
|
+
# 1. Find pages touching the indexer
|
|
140
|
+
$ almanac search --mentions src/indexer/
|
|
141
|
+
sqlite-indexer
|
|
142
|
+
wikilink-syntax
|
|
137
143
|
|
|
138
144
|
# 2. Triage with --lead
|
|
139
|
-
$ almanac show
|
|
140
|
-
|
|
145
|
+
$ almanac show sqlite-indexer --lead
|
|
146
|
+
The indexer (`src/indexer/`) builds and maintains `.almanac/index.db` — a
|
|
147
|
+
SQLite database that powers all query commands (`search`, `info`, `health`,
|
|
148
|
+
`topics show`). It runs silently before every query command, comparing page
|
|
149
|
+
file mtimes against the stored `content_hash`; only changed or new pages are
|
|
150
|
+
re-parsed.
|
|
141
151
|
|
|
142
152
|
# 3. Read the most relevant
|
|
143
|
-
$ almanac show
|
|
144
|
-
# ...
|
|
153
|
+
$ almanac show sqlite-indexer
|
|
154
|
+
# ...covers the schema, freshness rules, and where new pages get picked up
|
|
145
155
|
|
|
146
|
-
# 4. Before
|
|
147
|
-
$ almanac show
|
|
156
|
+
# 4. Before you touch anything, check backlinks
|
|
157
|
+
$ almanac show sqlite-indexer --backlinks
|
|
148
158
|
```
|
|
149
159
|
|
|
150
|
-
You now know:
|
|
160
|
+
You now know: the indexer only re-parses pages whose mtime is newer than the stored `content_hash`, runs on every query command, and backing it is a schema you can read at `src/indexer/schema.ts`. The lead alone ruled out two entire hypotheses ("maybe it only indexes on startup", "maybe I need to restart something") before you read any source code.
|
|
151
161
|
|
|
152
162
|
You don't write anything. At session end the capture agent reads the transcript, sees your discovery, writes or updates pages. Next session, a different agent running a related task sees it surface in `--mentions`.
|
|
153
163
|
|
|
@@ -180,6 +190,32 @@ The reviewer subagent (run by capture at session end) enforces these. Stricter w
|
|
|
180
190
|
|
|
181
191
|
---
|
|
182
192
|
|
|
193
|
+
## Troubleshooting
|
|
194
|
+
|
|
195
|
+
### `almanac doctor` is the catchall
|
|
196
|
+
When anything feels off and you don't know where to start, run `almanac doctor`. It reports the install (binary, native SQLite binding, Claude auth, hook, guides, CLAUDE.md import) and the current wiki (registered, page/topic counts, index freshness, last capture age, health problems). Every ✗ comes with a one-line `run: …` fix. Add `--json` for scripting.
|
|
197
|
+
|
|
198
|
+
### "better-sqlite3 bindings failed"
|
|
199
|
+
Node version or arch mismatch with the prebuilt native binding. `almanac doctor` reports this under `install.sqlite` with the raw error. Fix by rebuilding the native binding:
|
|
200
|
+
```bash
|
|
201
|
+
npm rebuild better-sqlite3 # in the install directory
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### "search returned nothing"
|
|
205
|
+
Empty stdout plus `# 0 results` on stderr means the query ran and genuinely matched nothing. Don't retry with random flag permutations — either broaden the query, or accept the wiki hasn't covered that area yet. A real error would have come with an `almanac:`-prefixed stderr line.
|
|
206
|
+
|
|
207
|
+
`--json` is silent on stderr — the `[]` array is the empty signal there.
|
|
208
|
+
|
|
209
|
+
### "capture didn't fire after my last session"
|
|
210
|
+
```bash
|
|
211
|
+
almanac doctor # install.hook: ok/problem, wiki.capture: last capture age
|
|
212
|
+
almanac hook status # just the hook entry
|
|
213
|
+
ls -lah .almanac/.capture-*.log
|
|
214
|
+
```
|
|
215
|
+
No logs at all → the hook isn't installed, or bailed before backgrounding, or `cwd` was outside any wiki (silent correct no-op). Capture ran but wrote nothing → the reviewer rejected the draft for notability, or the session was pure-read. Check the `.capture-<id>.log` for the writer/reviewer transcript.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
183
219
|
## When in doubt
|
|
184
220
|
|
|
185
221
|
- `.almanac/README.md` — repo-specific conventions + notability bar
|
package/guides/reference.md
CHANGED
|
@@ -4,12 +4,14 @@ Long-form manual for the `almanac` / `codealmanac` CLI. The mini guide at `~/.cl
|
|
|
4
4
|
|
|
5
5
|
Groupings match `almanac --help`:
|
|
6
6
|
|
|
7
|
-
1. **Query** — `search`, `show`, `
|
|
8
|
-
2. **Edit** — `tag`, `untag`, `topics
|
|
9
|
-
3. **Wiki lifecycle** — `
|
|
10
|
-
4. **
|
|
7
|
+
1. **Query** — `search`, `show`, `health`, `list`
|
|
8
|
+
2. **Edit** — `tag`, `untag`, `topics ...`
|
|
9
|
+
3. **Wiki lifecycle** — `bootstrap`, `capture`, `hook ...`, `reindex`
|
|
10
|
+
4. **Setup** — `setup`, `uninstall`, `doctor`
|
|
11
11
|
|
|
12
|
-
Every command auto-registers the current repo in `~/.almanac/registry.json` on first run. Exceptions: `
|
|
12
|
+
Every query/edit command auto-registers the current repo in `~/.almanac/registry.json` on first run. Exceptions: `list --drop` (skips auto-register so the removal intent isn't undone) and the setup group (installers, not wiki commands — they never touch the registry).
|
|
13
|
+
|
|
14
|
+
There is no `almanac init` command. The two ways a wiki gets scaffolded are `almanac bootstrap` (agent reads the repo and seeds stub pages) and committing a `.almanac/` that someone else authored and cloning into it (auto-registered on first query command).
|
|
13
15
|
|
|
14
16
|
---
|
|
15
17
|
|
|
@@ -23,7 +25,7 @@ Every command auto-registers the current repo in `~/.almanac/registry.json` on f
|
|
|
23
25
|
|---|---|---|---|
|
|
24
26
|
| `[query]` | string | — | FTS5 MATCH against titles + bodies. Omit for pure-filter queries. |
|
|
25
27
|
| `--topic <name...>` | repeatable | `[]` | AND-intersect filter. Walks the DAG subtree — `--topic auth` matches `auth` or any descendant. |
|
|
26
|
-
| `--mentions <path>` | string | — | Pages referencing this
|
|
28
|
+
| `--mentions <path>` | string | — | Pages referencing this path. Matches exact file, trailing-slash folders, and any file under a folder prefix. Case-insensitive. |
|
|
27
29
|
| `--since <duration>` | duration | — | Updated within window. Format: `<int>[smhdw]` (`2w`, `30d`, `48h`). By file mtime. |
|
|
28
30
|
| `--stale <duration>` | duration | — | Inverse of `--since`. |
|
|
29
31
|
| `--orphan` | bool | false | Pages with zero topics. |
|
|
@@ -33,52 +35,36 @@ Every command auto-registers the current repo in `~/.almanac/registry.json` on f
|
|
|
33
35
|
| `--json` | bool | false | Structured JSON. |
|
|
34
36
|
| `--limit <n>` | int ≥0 | unbounded | Cap results. |
|
|
35
37
|
|
|
36
|
-
**Default output:** one slug per line to stdout.
|
|
37
|
-
**`--json` schema:**
|
|
38
|
-
**Exit:** `0` always (empty result isn't an error). `
|
|
38
|
+
**Default output:** one slug per line to stdout. When zero pages match, stdout is empty and stderr emits `# 0 results` (a breadcrumb so users can tell "matched nothing" apart from "command broken"). `--json` is silent on stderr — `[]` is the unambiguous empty signal there.
|
|
39
|
+
**`--json` schema:** JSON array of `{slug, title, updated_at, topics, path}`.
|
|
40
|
+
**Exit:** `0` always (empty result isn't an error). Arg-parse failures exit `1` with an `almanac:` error.
|
|
39
41
|
|
|
40
42
|
#### `almanac show [slug]`
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|---|---|
|
|
44
|
-
| `[slug]` | Required unless `--stdin`. Slugs are kebab-canonicalized before lookup. |
|
|
45
|
-
| `--stdin` | Read slugs from stdin. Pages separated by form-feed (`\f`) in output. |
|
|
46
|
-
| `--wiki <name>` | Target a specific registered wiki. |
|
|
47
|
-
|
|
48
|
-
Projections (if available in the installed build — check `--help`): `--raw` (body only), `--meta` (metadata only), `--lead` (first paragraph), `--backlinks` (pages linking in), `--links` (pages this links out to). Falls back to `almanac info` + `path` if missing.
|
|
49
|
-
|
|
50
|
-
**Exit:** `0` on success, `1` if slug not found, `2` on flag errors.
|
|
51
|
-
|
|
52
|
-
#### `almanac path [slug]`
|
|
44
|
+
Unified reader. Absorbs the old `info` and `path` commands — pick fields with flags.
|
|
53
45
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
#### `almanac topics` (and subcommands)
|
|
78
|
-
|
|
79
|
-
`almanac topics` — list all with page counts. `--json` emits `[{slug, description, parents[], children[], page_count}]`.
|
|
80
|
-
|
|
81
|
-
`almanac topics show <slug>` — description, parents, children, pages. `--descendants` includes pages tagged with descendant topics (walks the DAG subtree).
|
|
46
|
+
| Flag | Default | Semantics |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| `[slug]` | — | Required unless `--stdin`. Slugs are kebab-canonicalized before lookup. |
|
|
49
|
+
| `--stdin` | false | Read slugs from stdin, one per line. JSON Lines output for `--json` mode. |
|
|
50
|
+
| `--wiki <name>` | current repo | Target a specific registered wiki. |
|
|
51
|
+
| `--json` | false | Structured JSON. Overrides every view/field flag. |
|
|
52
|
+
| `--raw` / `--body` | false | Body only (alias pair). Guarantees exactly one trailing newline — shell redirect produces a well-formed file. |
|
|
53
|
+
| `--meta` | false | Metadata header only, no body. |
|
|
54
|
+
| `--lead` | false | First paragraph of the body only (cheap preview). |
|
|
55
|
+
| `--title` | false | Print title. |
|
|
56
|
+
| `--topics` | false | Print topics. |
|
|
57
|
+
| `--files` | false | Print file refs. |
|
|
58
|
+
| `--links` | false | Print outgoing wikilinks. |
|
|
59
|
+
| `--backlinks` | false | Print incoming wikilinks. |
|
|
60
|
+
| `--xwiki` | false | Print cross-wiki links. |
|
|
61
|
+
| `--lineage` | false | Print `archived_at` / `supersedes` / `superseded_by`. |
|
|
62
|
+
| `--updated` | false | Print updated timestamp. |
|
|
63
|
+
| `--path` | false | Print absolute file path (`info` + `path` replacement). |
|
|
64
|
+
|
|
65
|
+
Combining field flags emits labeled sections in canonical order. `--meta` is the full labeled header; individual flags like `--title --topics` give you just those two sections.
|
|
66
|
+
|
|
67
|
+
**Exit:** `0` on success, `1` if slug not found, non-zero on flag/input errors.
|
|
82
68
|
|
|
83
69
|
#### `almanac health`
|
|
84
70
|
|
|
@@ -94,75 +80,137 @@ Eight independent categories. One failing doesn't skip the others.
|
|
|
94
80
|
|
|
95
81
|
**Categories:** `orphans`, `stale`, `dead-refs`, `broken-links`, `broken-xwiki`, `empty-topics`, `empty-pages`, `slug-collisions`. Archived pages are exempt from most (see §4). Exit `0` always — the report IS the output.
|
|
96
82
|
|
|
83
|
+
#### `almanac list`
|
|
84
|
+
|
|
85
|
+
| Flag | Semantics |
|
|
86
|
+
|---|---|
|
|
87
|
+
| `--json` | Structured JSON. |
|
|
88
|
+
| `--drop <name>` | Remove a wiki from the registry. The **only** way entries are ever removed. Skips auto-register. |
|
|
89
|
+
|
|
97
90
|
### 1.2 Edit
|
|
98
91
|
|
|
99
92
|
#### `almanac tag [page] [topics...]`
|
|
100
93
|
|
|
101
94
|
Add topics to a page. Auto-creates missing topics. Idempotent. Rewrites only the frontmatter block; body bytes preserved. `--stdin` tags every page-slug from stdin with the same topic set — in that mode all positionals are topics.
|
|
102
95
|
|
|
96
|
+
Flags: `--stdin`, `--wiki <name>`.
|
|
97
|
+
|
|
103
98
|
#### `almanac untag <page> <topic>`
|
|
104
99
|
|
|
105
|
-
Remove one topic. Idempotent (silent 0 if page wasn't tagged).
|
|
100
|
+
Remove one topic. Idempotent (silent `0` if page wasn't tagged).
|
|
101
|
+
|
|
102
|
+
Flags: `--wiki <name>`.
|
|
106
103
|
|
|
107
|
-
#### `almanac topics
|
|
104
|
+
#### `almanac topics` (DAG management)
|
|
108
105
|
|
|
109
|
-
|
|
106
|
+
- `almanac topics list` — list all topics with page counts. `--json` emits an array of `{slug, description, parents[], children[], page_count}`.
|
|
107
|
+
- `almanac topics show <slug>` — description, parents, children, pages. `--descendants` includes pages tagged with descendant topics (walks the DAG subtree).
|
|
108
|
+
- `almanac topics create <name>` — `--parent <slug>` repeatable. Rejects if any parent slug doesn't exist.
|
|
109
|
+
- `almanac topics link <child> <parent>` / `almanac topics unlink <child> <parent>` — add/remove a DAG edge. `link` is cycle-checked (§5). `unlink` is idempotent.
|
|
110
|
+
- `almanac topics rename <old> <new>` — rewrites `topics.yaml` first (atomic tmp+rename), then every affected page's `topics:` frontmatter. YAML-first so a mid-pass crash leaves the graph, not the pages, as the source of truth.
|
|
111
|
+
- `almanac topics delete <slug>` — removes from `topics.yaml`, untags every affected page. Does **not** cascade to children — orphaned children become top-level. Run `almanac health` to surface stragglers.
|
|
112
|
+
- `almanac topics describe <slug> <text>` — set the topic's one-line description.
|
|
113
|
+
|
|
114
|
+
All topic subcommands accept `--wiki <name>`. `list` / `show` accept `--json`.
|
|
115
|
+
|
|
116
|
+
### 1.3 Wiki lifecycle
|
|
117
|
+
|
|
118
|
+
#### `almanac bootstrap`
|
|
110
119
|
|
|
111
|
-
|
|
120
|
+
Spawns an agent to create initial wiki stubs. Requires `ANTHROPIC_API_KEY` or a logged-in Claude subscription. `--quiet` suppresses per-tool streaming. `--model <model>` overrides the model. `--force` overwrites an existing populated wiki. Writes `.almanac/.bootstrap-<timestamp>.log`.
|
|
112
121
|
|
|
113
|
-
|
|
122
|
+
Bootstrap is the scaffolding path — it creates `.almanac/pages/`, `.almanac/topics.yaml`, `.almanac/README.md`, and stub entity pages based on what the agent reads in the repo.
|
|
114
123
|
|
|
115
|
-
#### `almanac
|
|
124
|
+
#### `almanac capture [transcript]`
|
|
116
125
|
|
|
117
|
-
|
|
126
|
+
Run the writer/reviewer pipeline on a Claude Code session transcript. Usually automatic — the `SessionEnd` hook invokes this. Refuses if no `.almanac/` exists in cwd or any parent (capture maintains wikis, doesn't create them; run `almanac bootstrap` first).
|
|
118
127
|
|
|
119
|
-
|
|
128
|
+
| Flag | Semantics |
|
|
129
|
+
|---|---|
|
|
130
|
+
| `[transcript]` | Explicit path. Falls back to `--session` match or most-recent-by-cwd. |
|
|
131
|
+
| `--session <id>` | Target a specific session by ID. Matches filename under `~/.claude/projects/`. |
|
|
132
|
+
| `--quiet` | Suppress per-tool streaming; print only the final summary. |
|
|
133
|
+
| `--model <model>` | Override the agent model. |
|
|
120
134
|
|
|
121
|
-
|
|
135
|
+
Writes SDK transcript to `.almanac/.capture-<session-id>.log`. A writer subagent drafts pages; a reviewer subagent enforces notability + writing conventions (§9) before drafts land.
|
|
122
136
|
|
|
123
|
-
#### `almanac
|
|
137
|
+
#### `almanac hook install | uninstall | status`
|
|
124
138
|
|
|
125
|
-
|
|
139
|
+
See §7 — the hook is complex enough to warrant its own section.
|
|
126
140
|
|
|
127
141
|
#### `almanac reindex`
|
|
128
142
|
|
|
129
143
|
Forces a full rebuild of `.almanac/index.db`. Rarely needed — every query calls `ensureFreshIndex` first. Use after manual `topics.yaml` edits or when clock skew defeats mtime checks.
|
|
130
144
|
|
|
131
|
-
|
|
145
|
+
Flag: `--wiki <name>`.
|
|
132
146
|
|
|
133
|
-
|
|
147
|
+
### 1.4 Setup
|
|
134
148
|
|
|
135
|
-
|
|
149
|
+
#### `almanac setup` (alias: bare `codealmanac`)
|
|
136
150
|
|
|
137
|
-
|
|
151
|
+
Install the SessionEnd hook + the two CLAUDE.md guides (`codealmanac.md`, `codealmanac-reference.md`) + the `@~/.claude/codealmanac.md` import line. Idempotent.
|
|
138
152
|
|
|
139
|
-
|
|
153
|
+
| Flag | Semantics |
|
|
154
|
+
|---|---|
|
|
155
|
+
| `-y, --yes` | Skip prompts; install everything. |
|
|
156
|
+
| `--skip-hook` | Opt out of the SessionEnd hook. |
|
|
157
|
+
| `--skip-guides` | Opt out of the CLAUDE.md guides. |
|
|
140
158
|
|
|
141
|
-
|
|
159
|
+
Both `almanac setup` and bare `codealmanac` route here. `codealmanac --yes`, `codealmanac --skip-hook`, and `codealmanac --skip-guides` are the typical first-run invocations. Passing `--skip-hook --skip-guides` together short-circuits with a terse line — nothing was installed, no banner drawn.
|
|
142
160
|
|
|
143
|
-
|
|
161
|
+
#### `almanac uninstall`
|
|
144
162
|
|
|
145
|
-
|
|
163
|
+
Remove the hook + guides + import line.
|
|
146
164
|
|
|
147
|
-
|
|
165
|
+
| Flag | Semantics |
|
|
166
|
+
|---|---|
|
|
167
|
+
| `-y, --yes` | Skip confirmations; remove everything. |
|
|
168
|
+
| `--keep-hook` | Don't remove the SessionEnd hook (guides still prompted unless `--yes`). |
|
|
169
|
+
| `--keep-guides` | Don't remove the guides or CLAUDE.md import (hook still prompted unless `--yes`). |
|
|
148
170
|
|
|
149
|
-
|
|
171
|
+
#### `almanac doctor`
|
|
150
172
|
|
|
151
|
-
|
|
173
|
+
Read-only install + current-wiki health report. Every check reports a state; none of them mutate. Exit always `0` — doctor is a report, not a test.
|
|
152
174
|
|
|
153
|
-
|
|
175
|
+
| Flag | Semantics |
|
|
176
|
+
|---|---|
|
|
177
|
+
| `--json` | Structured JSON. |
|
|
178
|
+
| `--install-only` | Report only on the install (skip the wiki section). |
|
|
179
|
+
| `--wiki-only` | Report only on the current wiki (skip the install section). |
|
|
154
180
|
|
|
155
|
-
|
|
181
|
+
**JSON shape:**
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"version": "0.1.3",
|
|
185
|
+
"install": [
|
|
186
|
+
{ "key": "install.path", "status": "ok", "message": "..." },
|
|
187
|
+
{ "key": "install.sqlite", "status": "ok", "message": "..." },
|
|
188
|
+
{ "key": "install.auth", "status": "problem", "message": "...", "fix": "run: claude auth login --claudeai" },
|
|
189
|
+
{ "key": "install.hook", "status": "ok", "message": "..." },
|
|
190
|
+
{ "key": "install.guides", "status": "ok", "message": "..." },
|
|
191
|
+
{ "key": "install.import", "status": "ok", "message": "..." }
|
|
192
|
+
],
|
|
193
|
+
"wiki": [
|
|
194
|
+
{ "key": "wiki.repo", "status": "info", "message": "repo: /abs/path" },
|
|
195
|
+
{ "key": "wiki.registered", "status": "ok", "message": "registered as '...'" },
|
|
196
|
+
{ "key": "wiki.pages", "status": "info", "message": "pages: 42" },
|
|
197
|
+
{ "key": "wiki.topics", "status": "info", "message": "topics: 7" },
|
|
198
|
+
{ "key": "wiki.index", "status": "info", "message": "index: rebuilt 2m ago" },
|
|
199
|
+
{ "key": "wiki.capture", "status": "info", "message": "last capture: 1h ago (.capture-<id>.log)" },
|
|
200
|
+
{ "key": "wiki.health", "status": "ok", "message": "almanac health reports 0 problems" }
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
```
|
|
156
204
|
|
|
157
|
-
|
|
205
|
+
Each check has a stable `key` safe for scripting. ✗ entries include a `fix` field with a one-line "run: …" hint. Parse `--json` and count `status === "problem"` for a pass/fail gate.
|
|
158
206
|
|
|
159
207
|
### 1.5 `--stdin` pipe semantics
|
|
160
208
|
|
|
161
|
-
Commands that accept `--stdin`: `show`, `
|
|
209
|
+
Commands that accept `--stdin`: `show`, `tag`, `health`.
|
|
162
210
|
|
|
163
211
|
- One slug per line; blank lines ignored; whitespace trimmed.
|
|
164
|
-
- Output order mirrors input order
|
|
165
|
-
- Missing slugs don't abort — logged to stderr, pipeline continues. `show --stdin` writes a "not found" marker and keeps exit `0` for pipeline resilience
|
|
212
|
+
- Output order mirrors input order.
|
|
213
|
+
- Missing slugs don't abort — logged to stderr, pipeline continues. `show --stdin` writes a "not found" marker per slug and keeps exit `0` for pipeline resilience.
|
|
166
214
|
- `--stdin` must be explicit. No `isTTY` auto-detection (confusing under script redirection).
|
|
167
215
|
|
|
168
216
|
---
|
|
@@ -230,6 +278,8 @@ inventory lock row to Supabase, returns the PI client secret. See
|
|
|
230
278
|
[[inventory-lock-gotcha]] for the deadlock we hit in March.
|
|
231
279
|
```
|
|
232
280
|
|
|
281
|
+
CRLF-terminated files are handled transparently — `show --raw` strips frontmatter without leaving a stray `\r` at the body head.
|
|
282
|
+
|
|
233
283
|
---
|
|
234
284
|
|
|
235
285
|
## 4. Archive / lineage
|
|
@@ -348,7 +398,7 @@ almanac topics delete old-payments
|
|
|
348
398
|
**List pages that lack `files:` frontmatter for files they mention in prose:**
|
|
349
399
|
```bash
|
|
350
400
|
almanac search | while read slug; do
|
|
351
|
-
info=$(almanac
|
|
401
|
+
info=$(almanac show "$slug" --json)
|
|
352
402
|
prose=$(echo "$info" | jq -r '.file_refs[].path' | sort -u)
|
|
353
403
|
fm=$(echo "$info" | jq -r '.files[]' | sort -u)
|
|
354
404
|
missing=$(comm -23 <(echo "$prose") <(echo "$fm"))
|
|
@@ -358,7 +408,17 @@ done
|
|
|
358
408
|
|
|
359
409
|
**Open every orphan page in `$EDITOR`:**
|
|
360
410
|
```bash
|
|
361
|
-
almanac search --orphan | almanac
|
|
411
|
+
almanac search --orphan | almanac show --stdin --path | xargs -n 1 "$EDITOR"
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**Export a page's body to a standalone markdown file:**
|
|
415
|
+
```bash
|
|
416
|
+
almanac show checkout-flow --raw > checkout-flow.md # exactly one trailing \n
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**Doctor a flaky install in CI:**
|
|
420
|
+
```bash
|
|
421
|
+
almanac doctor --json | jq '.install[] | select(.status == "problem")'
|
|
362
422
|
```
|
|
363
423
|
|
|
364
424
|
---
|
|
@@ -396,11 +456,14 @@ Falls back to `npx --no-install codealmanac` if `almanac` isn't on `PATH`.
|
|
|
396
456
|
**`status`:**
|
|
397
457
|
- Reports installed / not installed, the script path, the settings path. Non-interactive.
|
|
398
458
|
|
|
459
|
+
`almanac setup` wraps `hook install` alongside the guides. `almanac uninstall` wraps `hook uninstall` alongside guide removal. You rarely invoke `hook *` directly.
|
|
460
|
+
|
|
399
461
|
### Diagnosing "capture didn't run"
|
|
400
462
|
|
|
401
463
|
```bash
|
|
402
|
-
almanac hook
|
|
403
|
-
|
|
464
|
+
almanac doctor # catch-all — reports hook state + last capture age
|
|
465
|
+
almanac hook status # just the hook entry
|
|
466
|
+
ls -lah .almanac/.capture-*.log
|
|
404
467
|
```
|
|
405
468
|
|
|
406
469
|
Installed but no log: `SessionEnd` didn't fire (rare, hard crash), or script bailed before backgrounding (add `set -x` to trace), or no `.almanac/` upward from `cwd` (silent correct no-op).
|
|
@@ -434,13 +497,13 @@ Common causes:
|
|
|
434
497
|
|
|
435
498
|
### Registration paths
|
|
436
499
|
|
|
437
|
-
-
|
|
438
|
-
-
|
|
500
|
+
- **Silent auto-register** — every query/edit command (except `list --drop`) calls `autoRegisterIfNeeded` on cwd. A repo with `.almanac/` but no registry entry → added with `name = basename(cwd)`, no description. Makes "cloned a repo with `.almanac/` committed" just work.
|
|
501
|
+
- **`almanac bootstrap`** — auto-registers as a side effect of scaffolding. `name` defaults to the repo basename; edit `~/.almanac/registry.json` or re-bootstrap to rename.
|
|
439
502
|
- **`almanac list --drop <name>`** — the only removal path. Skips auto-register so the removal isn't immediately undone.
|
|
440
503
|
|
|
441
504
|
### `--wiki <name>`
|
|
442
505
|
|
|
443
|
-
Route the command at a specific registered wiki. Used when you're in one repo but querying another. Without `--wiki`, commands resolve to the wiki whose `path` is an ancestor of cwd. If none, commands error: `almanac: no
|
|
506
|
+
Route the command at a specific registered wiki. Used when you're in one repo but querying another. Without `--wiki`, commands resolve to the wiki whose `path` is an ancestor of cwd. If none, commands error: `almanac: no .almanac/ found in this directory or any parent; run 'almanac bootstrap' first`.
|
|
444
507
|
|
|
445
508
|
### Cross-wiki link resolution
|
|
446
509
|
|
|
@@ -563,31 +626,54 @@ one, usually the webhook, leaving orders silently stuck in pending.
|
|
|
563
626
|
|
|
564
627
|
## 10. Troubleshooting
|
|
565
628
|
|
|
566
|
-
###
|
|
567
|
-
|
|
629
|
+
### Catch-all: `almanac doctor`
|
|
630
|
+
|
|
631
|
+
When something feels off and you don't know where to start, run `almanac doctor`. It reports install state (binary, native binding, Claude auth, hook, guides, import line) and current-wiki state (registered, page/topic counts, index freshness, last capture age, health problems). Every ✗ comes with a one-line `run: …` fix. `--json` for scripting.
|
|
632
|
+
|
|
633
|
+
### "better-sqlite3 bindings missing"
|
|
634
|
+
Node version / arch mismatch with the prebuilt binary. `almanac doctor` reports it as `install.sqlite: problem` with the underlying error's first line. Fix:
|
|
635
|
+
```bash
|
|
636
|
+
npm rebuild better-sqlite3 # in the install directory
|
|
637
|
+
```
|
|
638
|
+
On M-series Macs with x64+arm64 Node installs, bindings are arch-specific — rebuild in the arch you'll run from. Node ≥20 required (`engines.node`).
|
|
639
|
+
|
|
640
|
+
### "search returns nothing"
|
|
641
|
+
|
|
642
|
+
Two different outcomes to distinguish:
|
|
643
|
+
- **Silent stdout, stderr says `# 0 results`.** The query ran and genuinely matched nothing — this is an answer, not a failure. Either the wiki doesn't cover that area yet, or the query needs broadening.
|
|
644
|
+
- **An actual error on stderr.** Commander or `almanac:` prefix. That's a broken invocation; re-read the `--help`.
|
|
645
|
+
|
|
646
|
+
`--json` is silent on stderr — the `[]` array is the unambiguous empty signal.
|
|
568
647
|
|
|
569
648
|
### "pages don't show up in `--mentions`"
|
|
649
|
+
|
|
570
650
|
Missing `files:` frontmatter, OR path referenced only in inline prose (not via `[[...]]`). Inline prose isn't indexed. If neither: `almanac reindex`.
|
|
571
651
|
|
|
572
652
|
### "topics missing after rename"
|
|
653
|
+
|
|
573
654
|
`topics rename` bumps `topics.yaml` mtime → next query's `ensureFreshIndex` catches up. Hand-edited `topics.yaml` without page rewrites leaves frontmatter out of sync — `almanac reindex` then audit with `almanac health --orphans --empty-topics`.
|
|
574
655
|
|
|
575
656
|
### "capture didn't fire"
|
|
657
|
+
|
|
576
658
|
```bash
|
|
577
|
-
almanac hook
|
|
578
|
-
claude auth status
|
|
579
|
-
echo "${ANTHROPIC_API_KEY:0:10}"
|
|
659
|
+
almanac doctor # reports hook state + last capture age + auth
|
|
660
|
+
claude auth status # OAuth token present?
|
|
661
|
+
echo "${ANTHROPIC_API_KEY:0:10}" # API key fallback?
|
|
580
662
|
ls -lah .almanac/.capture-*.log
|
|
581
663
|
```
|
|
582
|
-
|
|
664
|
+
|
|
665
|
+
No logs at all → script bailed pre-background. Add `set -x` to `hooks/almanac-capture.sh` to trace. If the hook itself isn't installed, `almanac doctor` reports `install.hook: problem` with `run: almanac setup --yes`.
|
|
583
666
|
|
|
584
667
|
### "slug collision warnings"
|
|
668
|
+
|
|
585
669
|
Two files kebab-case to the same slug (`Checkout Flow.md` and `checkout-flow.md`). `health --slug-collisions` lists them. Rename one, grep `.almanac/pages/` for any `[[...]]` references, update them.
|
|
586
670
|
|
|
587
|
-
### "
|
|
588
|
-
|
|
671
|
+
### "dead-refs reports files that exist"
|
|
672
|
+
|
|
673
|
+
Case sensitivity on Linux. Schema v2 stores `original_path` for case-preserving stat; upgrade from pre-v2 requires `almanac reindex`. Dangling symlinks also fail `existsSync`.
|
|
589
674
|
|
|
590
675
|
### Forensics files
|
|
676
|
+
|
|
591
677
|
- `.almanac/.capture-<session-id>.log` — per-session SDK transcript from capture. Writer + reviewer interleaved.
|
|
592
678
|
- `.almanac/.bootstrap-<timestamp>.log` — one per bootstrap. Gitignored by default.
|
|
593
679
|
|
|
@@ -596,4 +682,5 @@ Node version / arch mismatch with the prebuilt binary. `npm rebuild better-sqlit
|
|
|
596
682
|
## When in doubt
|
|
597
683
|
|
|
598
684
|
- `almanac --help` / `almanac <command> --help` — flags are always current for the installed build.
|
|
685
|
+
- `almanac doctor` — one command that reports everything relevant about install + current wiki.
|
|
599
686
|
- `.almanac/README.md` in the repo — the notability bar and topic taxonomy for *this* repo override anything here.
|
package/package.json
CHANGED