grounder 0.1.0 → 0.3.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 +115 -28
- package/dist/agents/claude.d.ts +15 -0
- package/dist/agents/claude.d.ts.map +1 -1
- package/dist/agents/claude.js +256 -11
- package/dist/agents/claude.js.map +1 -1
- package/dist/agents/cursor-hook-input.d.ts +14 -0
- package/dist/agents/cursor-hook-input.d.ts.map +1 -0
- package/dist/agents/cursor-hook-input.js +80 -0
- package/dist/agents/cursor-hook-input.js.map +1 -0
- package/dist/agents/cursor.d.ts +11 -0
- package/dist/agents/cursor.d.ts.map +1 -1
- package/dist/agents/cursor.js +206 -11
- package/dist/agents/cursor.js.map +1 -1
- package/dist/agents/hook-runtime.d.ts +152 -0
- package/dist/agents/hook-runtime.d.ts.map +1 -0
- package/dist/agents/hook-runtime.js +401 -0
- package/dist/agents/hook-runtime.js.map +1 -0
- package/dist/agents/index.d.ts +18 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +27 -4
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/install-command.d.ts +37 -0
- package/dist/agents/install-command.d.ts.map +1 -0
- package/dist/agents/install-command.js +65 -0
- package/dist/agents/install-command.js.map +1 -0
- package/dist/agents/types.d.ts +23 -1
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/cli.js +62 -53
- package/dist/cli.js.map +1 -1
- package/dist/commands/apply-agent-installs.d.ts +34 -0
- package/dist/commands/apply-agent-installs.d.ts.map +1 -0
- package/dist/commands/apply-agent-installs.js +137 -0
- package/dist/commands/apply-agent-installs.js.map +1 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +231 -14
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/handoff/list.d.ts +9 -0
- package/dist/commands/handoff/list.d.ts.map +1 -1
- package/dist/commands/handoff/list.js +20 -4
- package/dist/commands/handoff/list.js.map +1 -1
- package/dist/commands/handoff/peek.d.ts +41 -0
- package/dist/commands/handoff/peek.d.ts.map +1 -0
- package/dist/commands/handoff/peek.js +161 -0
- package/dist/commands/handoff/peek.js.map +1 -0
- package/dist/commands/handoff.d.ts.map +1 -1
- package/dist/commands/handoff.js +5 -0
- package/dist/commands/handoff.js.map +1 -1
- package/dist/commands/migrate.d.ts +23 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +104 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/note.d.ts.map +1 -1
- package/dist/commands/note.js +5 -0
- package/dist/commands/note.js.map +1 -1
- package/dist/commands/package-version-notice.d.ts +18 -0
- package/dist/commands/package-version-notice.d.ts.map +1 -0
- package/dist/commands/package-version-notice.js +39 -0
- package/dist/commands/package-version-notice.js.map +1 -0
- package/dist/commands/path/logs.d.ts +1 -1
- package/dist/commands/path/logs.d.ts.map +1 -1
- package/dist/commands/path/logs.js +6 -1
- package/dist/commands/path/logs.js.map +1 -1
- package/dist/commands/path/notes.d.ts +1 -1
- package/dist/commands/path/notes.d.ts.map +1 -1
- package/dist/commands/path/notes.js +6 -1
- package/dist/commands/path/notes.js.map +1 -1
- package/dist/commands/path/plans.d.ts +7 -0
- package/dist/commands/path/plans.d.ts.map +1 -0
- package/dist/commands/path/plans.js +22 -0
- package/dist/commands/path/plans.js.map +1 -0
- package/dist/commands/plan/list.d.ts +23 -0
- package/dist/commands/plan/list.d.ts.map +1 -0
- package/dist/commands/plan/list.js +69 -0
- package/dist/commands/plan/list.js.map +1 -0
- package/dist/commands/plan.d.ts +34 -0
- package/dist/commands/plan.d.ts.map +1 -0
- package/dist/commands/plan.js +121 -0
- package/dist/commands/plan.js.map +1 -0
- package/dist/commands/repo/init.d.ts.map +1 -1
- package/dist/commands/repo/init.js +12 -1
- package/dist/commands/repo/init.js.map +1 -1
- package/dist/commands/status.d.ts +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +52 -9
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/upgrade-banner.d.ts +9 -0
- package/dist/commands/upgrade-banner.d.ts.map +1 -0
- package/dist/commands/upgrade-banner.js +27 -0
- package/dist/commands/upgrade-banner.js.map +1 -0
- package/dist/commands/vault/init.d.ts +2 -0
- package/dist/commands/vault/init.d.ts.map +1 -1
- package/dist/commands/vault/init.js +28 -11
- package/dist/commands/vault/init.js.map +1 -1
- package/dist/connector/repo.d.ts +2 -0
- package/dist/connector/repo.d.ts.map +1 -1
- package/dist/connector/repo.js +12 -1
- package/dist/connector/repo.js.map +1 -1
- package/dist/connector/state.d.ts +95 -0
- package/dist/connector/state.d.ts.map +1 -0
- package/dist/connector/state.js +189 -0
- package/dist/connector/state.js.map +1 -0
- package/dist/connector/unsupported-schema.d.ts +9 -0
- package/dist/connector/unsupported-schema.d.ts.map +1 -0
- package/dist/connector/unsupported-schema.js +14 -0
- package/dist/connector/unsupported-schema.js.map +1 -0
- package/dist/connector/vault.d.ts +2 -0
- package/dist/connector/vault.d.ts.map +1 -1
- package/dist/connector/vault.js +6 -1
- package/dist/connector/vault.js.map +1 -1
- package/dist/help.d.ts +45 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/help.js +355 -0
- package/dist/help.js.map +1 -0
- package/dist/util/frontmatter.d.ts +11 -0
- package/dist/util/frontmatter.d.ts.map +1 -0
- package/dist/util/frontmatter.js +69 -0
- package/dist/util/frontmatter.js.map +1 -0
- package/dist/util/fs.d.ts +6 -0
- package/dist/util/fs.d.ts.map +1 -1
- package/dist/util/fs.js +15 -1
- package/dist/util/fs.js.map +1 -1
- package/dist/util/hash.d.ts +3 -0
- package/dist/util/hash.d.ts.map +1 -0
- package/dist/util/hash.js +6 -0
- package/dist/util/hash.js.map +1 -0
- package/dist/util/merge-json.d.ts +15 -0
- package/dist/util/merge-json.d.ts.map +1 -0
- package/dist/util/merge-json.js +40 -0
- package/dist/util/merge-json.js.map +1 -0
- package/dist/util/path.d.ts +10 -0
- package/dist/util/path.d.ts.map +1 -1
- package/dist/util/path.js +31 -0
- package/dist/util/path.js.map +1 -1
- package/dist/util/plan-name.d.ts +10 -0
- package/dist/util/plan-name.d.ts.map +1 -0
- package/dist/util/plan-name.js +18 -0
- package/dist/util/plan-name.js.map +1 -0
- package/dist/util/semver.d.ts +10 -0
- package/dist/util/semver.d.ts.map +1 -0
- package/dist/util/semver.js +40 -0
- package/dist/util/semver.js.map +1 -0
- package/dist/vault/find-usable-handoff.d.ts +19 -0
- package/dist/vault/find-usable-handoff.d.ts.map +1 -0
- package/dist/vault/find-usable-handoff.js +28 -0
- package/dist/vault/find-usable-handoff.js.map +1 -0
- package/dist/vault/layout.d.ts +2 -0
- package/dist/vault/layout.d.ts.map +1 -1
- package/dist/vault/layout.js +4 -0
- package/dist/vault/layout.js.map +1 -1
- package/dist/vault/list-plans.d.ts +11 -0
- package/dist/vault/list-plans.d.ts.map +1 -0
- package/dist/vault/list-plans.js +40 -0
- package/dist/vault/list-plans.js.map +1 -0
- package/dist/vault/write-plan.d.ts +28 -0
- package/dist/vault/write-plan.d.ts.map +1 -0
- package/dist/vault/write-plan.js +61 -0
- package/dist/vault/write-plan.js.map +1 -0
- package/package.json +1 -1
- package/templates/agents/claude/commands/grounder-note.md +1 -1
- package/templates/agents/claude/commands/grounder-plan.md +65 -0
- package/templates/agents/claude/commands/grounder-task-handoff.md +3 -3
- package/templates/agents/claude/commands/grounder-task.md +4 -4
- package/templates/agents/cursor/commands/grounder-note.md +1 -1
- package/templates/agents/cursor/commands/grounder-plan.md +65 -0
- package/templates/agents/cursor/commands/grounder-task-handoff.md +3 -3
- package/templates/agents/cursor/commands/grounder-task.md +4 -4
- package/templates/vault/plan.md +16 -0
package/README.md
CHANGED
|
@@ -3,16 +3,17 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/grounder)
|
|
4
4
|
[](../../LICENSE)
|
|
5
5
|
|
|
6
|
-
AI coding agents forget everything between sessions. Grounder gives them persistent memory in a personal Obsidian vault — notes and
|
|
6
|
+
AI coding agents forget everything between sessions. Grounder gives them persistent memory in a personal Obsidian vault — notes, handoffs, and plans live outside the repo, under your control, and never get committed.
|
|
7
7
|
|
|
8
8
|
- **Private by default** — vault notes live outside the project tree; only a small `projectId` marker is safe to commit
|
|
9
|
-
- **Built for agents** — installs `/grounder-note`, `/grounder-task`, `/grounder-task-handoff` slash commands in Cursor and Claude Code
|
|
9
|
+
- **Built for agents** — installs `/grounder-note`, `/grounder-task`, `/grounder-task-handoff`, `/grounder-plan` slash commands in Cursor and Claude Code
|
|
10
10
|
- **Structured handoffs** — end a session with a Done/Next/Blockers/Decisions checkpoint; resume next time by hydrating from it
|
|
11
|
-
- **
|
|
11
|
+
- **Named plans** — living docs under `plans/` you update in place (`--force` to overwrite; unlike dated notes/handoffs)
|
|
12
|
+
- **Zero per-project install** — slash commands run through a small per-machine runtime that `vault init` keeps current; nothing to add to the repo besides the marker file
|
|
12
13
|
|
|
13
14
|
**Requirements:** Node.js 18+ and an Obsidian vault on disk. Git is optional but used when present (project id detection and link lookup bounds).
|
|
14
15
|
|
|
15
|
-
**Contents:** [Install](#install) · [Quickstart](#quickstart) · [Setup overview](#setup-overview) · [Commands](#commands) · [Configuration](#configuration) · [Agents](#agents) · [Troubleshooting](#troubleshooting)
|
|
16
|
+
**Contents:** [Install](#install) · [Upgrading](#upgrading) · [Quickstart](#quickstart) · [Setup overview](#setup-overview) · [Commands](#commands) · [Configuration](#configuration) · [Agents](#agents) · [Session-start hooks](#session-start-hooks) · [Troubleshooting](#troubleshooting)
|
|
16
17
|
|
|
17
18
|
## Install
|
|
18
19
|
|
|
@@ -26,7 +27,17 @@ Or run without installing:
|
|
|
26
27
|
npx grounder --help
|
|
27
28
|
```
|
|
28
29
|
|
|
29
|
-
`grounder -h` prints the full reference; `grounder -v` prints the installed version.
|
|
30
|
+
`grounder -h` prints a short synopsis; `grounder --help` (or `grounder help`) prints the full reference; `grounder -v` prints the installed version.
|
|
31
|
+
|
|
32
|
+
## Upgrading
|
|
33
|
+
|
|
34
|
+
After upgrading the package, refresh agent installs:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
grounder migrate
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Run `grounder doctor` if you’re unsure — it hints when plain `migrate` is enough vs `migrate --force` (needed **once** when upgrading from Grounder before 0.3, or when command files were edited locally). Most grounder commands and session-start teasers will also tell you when a migrate is due. Flag details: [Migrate flags](#migrate-flags).
|
|
30
41
|
|
|
31
42
|
## Quickstart
|
|
32
43
|
|
|
@@ -34,9 +45,10 @@ npx grounder --help
|
|
|
34
45
|
|
|
35
46
|
```bash
|
|
36
47
|
# Once per machine — set vault location + install agent slash commands
|
|
37
|
-
|
|
48
|
+
# --hooks adds an optional one-line session-start reminder (see Session-start hooks)
|
|
49
|
+
grounder vault init <path-to-your-vault> --hooks
|
|
38
50
|
|
|
39
|
-
# Once per project folder — link project id to vault notes/ + logs/
|
|
51
|
+
# Once per project folder — link project id to vault notes/ + logs/ + plans/
|
|
40
52
|
cd your-project
|
|
41
53
|
grounder init
|
|
42
54
|
```
|
|
@@ -60,38 +72,47 @@ Both commands preview what they'll write and ask to confirm; add `--yes` to skip
|
|
|
60
72
|
Wrote handoff → <vault>/10-Projects/your-project/logs/2026-07-28-143200-auth-middleware.md
|
|
61
73
|
```
|
|
62
74
|
|
|
63
|
-
`/grounder-task` hydrates the agent from the newest handoff plus `AGENTS.md`; `/grounder-task-handoff` writes the next checkpoint when you close the session. Behind the scenes these run `grounder handoff list` and `grounder handoff <text>` for you — see [Session loop](#session-loop).
|
|
75
|
+
`/grounder-task` hydrates the agent from the newest *usable* handoff plus `AGENTS.md`; `/grounder-task-handoff` writes the next checkpoint when you close the session. Behind the scenes these run `grounder handoff list --head` and `grounder handoff <text>` for you — see [Session loop](#session-loop).
|
|
64
76
|
|
|
65
77
|
No agent, or want to write by hand? The same actions are plain CLI commands:
|
|
66
78
|
|
|
67
79
|
```bash
|
|
68
|
-
grounder note "Investigate auth middleware"
|
|
69
|
-
grounder handoff
|
|
70
|
-
grounder handoff list
|
|
80
|
+
grounder note "Investigate auth middleware" # ad-hoc note
|
|
81
|
+
grounder handoff $'# Handoff: ...\n\n## Next\n1. ...' # session checkpoint
|
|
82
|
+
grounder handoff list # newest handoffs, for manual hydrate
|
|
83
|
+
grounder plan $'# Goal\n\nShip it' --title phase-1 # named living plan
|
|
71
84
|
```
|
|
72
85
|
|
|
73
86
|
Notes land in `<vault>/10-Projects/{projectId}/notes/`.
|
|
74
|
-
Handoffs land in `<vault>/10-Projects/{projectId}/logs/` (one file per close; newest wins).
|
|
87
|
+
Handoffs land in `<vault>/10-Projects/{projectId}/logs/` (one file per close; newest *usable* file wins — an empty or unreadable newest file falls back to the next one).
|
|
88
|
+
Plans land in `<vault>/10-Projects/{projectId}/plans/` (one file per `--title`; overwrite only with `--force`).
|
|
89
|
+
|
|
90
|
+
Unlike `note` (one-off) and `handoff` (per-session checkpoint), `plan` is for anything spanning multiple sessions — write it once with the goal + steps, then re-run with `--force` as the work progresses to keep one file current instead of scattering updates across handoffs.
|
|
75
91
|
|
|
76
92
|
Inspect or debug setup any time with `grounder status` / `grounder doctor` — see [Troubleshooting](#troubleshooting).
|
|
77
93
|
|
|
78
94
|
### Session loop
|
|
79
95
|
|
|
80
96
|
```text
|
|
81
|
-
/grounder-task → work → /grounder-task-handoff → next
|
|
97
|
+
(optional teaser) → /grounder-task → work → /grounder-task-handoff → next session
|
|
82
98
|
```
|
|
83
99
|
|
|
84
|
-
| Slash command | CLI | Role |
|
|
100
|
+
| Slash command | Equivalent CLI | Role |
|
|
85
101
|
| --- | --- | --- |
|
|
86
102
|
| `/grounder-note` | `grounder note` | Ad-hoc vault note |
|
|
87
103
|
| `/grounder-task-handoff` | `grounder handoff` | Write session checkpoint to `logs/` |
|
|
88
|
-
| `/grounder-task` | `grounder handoff list` + read
|
|
104
|
+
| `/grounder-task` | `grounder handoff list --head` + read it | Read-only hydrate from newest usable handoff + `AGENTS.md` |
|
|
105
|
+
| `/grounder-plan` | `grounder plan` | Named living plan under `plans/` |
|
|
106
|
+
|
|
107
|
+
The "Equivalent CLI" column is what you'd type by hand — under the hood, slash commands invoke a small runtime `vault init` maintains at `~/.grounder/runtime` (see [Agents](#agents)), not whatever `grounder` binary happens to be on your `PATH`.
|
|
108
|
+
|
|
109
|
+
With `--hooks` on `vault init`, a new Cursor/Claude session may also print a one-line teaser when a handoff exists — never the full body. See [Session-start hooks](#session-start-hooks).
|
|
89
110
|
|
|
90
111
|
## Setup overview
|
|
91
112
|
|
|
92
113
|
- **`grounder vault init <path>`** (once per machine) writes `~/.grounder/config.json`, creates `<vault>/10-Projects/`, and installs slash commands for detected agents (Cursor → `~/.cursor/commands/`, Claude Code → `~/.claude/commands/`; override with `--agent=<id>`).
|
|
93
|
-
- **`grounder init`** (once per project folder) writes `.grounder.json` (`projectId` — safe to commit) and creates `<vault>/10-Projects/{projectId}/notes
|
|
94
|
-
- **Daily use** — notes, handoffs, and recall via CLI or slash commands; no further install.
|
|
114
|
+
- **`grounder init`** (once per project folder) writes `.grounder.json` (`projectId` — safe to commit) and creates `<vault>/10-Projects/{projectId}/notes/`, `logs/`, and `plans/`.
|
|
115
|
+
- **Daily use** — notes, handoffs, plans, and recall via CLI or slash commands; no further install.
|
|
95
116
|
|
|
96
117
|
Nothing is written into the repo except the small `.grounder.json` marker. Agent artifacts stay under the user’s home directory; vault notes stay outside the project tree.
|
|
97
118
|
|
|
@@ -103,10 +124,16 @@ grounder init Connect the current folder to your vault
|
|
|
103
124
|
grounder note <text> Write a note to the vault
|
|
104
125
|
grounder handoff <text> Write a session handoff to vault logs/
|
|
105
126
|
grounder handoff list Print recent handoff paths (newest first)
|
|
127
|
+
grounder handoff list --head Print only the newest usable handoff path
|
|
128
|
+
grounder handoff peek One-line latest-handoff teaser (used by session hooks)
|
|
129
|
+
grounder plan <text> Write/update a named plan under vault plans/
|
|
130
|
+
grounder plan list Print recent plan paths (newest first)
|
|
106
131
|
grounder path notes Print resolved notes directory
|
|
107
132
|
grounder path logs Print resolved logs directory
|
|
133
|
+
grounder path plans Print resolved plans directory
|
|
108
134
|
grounder status Snapshot of machine + project link + resolved paths
|
|
109
135
|
grounder doctor Health checks with fix hints
|
|
136
|
+
grounder migrate Refresh agent install after upgrading grounder
|
|
110
137
|
```
|
|
111
138
|
|
|
112
139
|
### Init flags
|
|
@@ -114,17 +141,40 @@ grounder doctor Health checks with fix hints
|
|
|
114
141
|
| Flag | Commands | Description |
|
|
115
142
|
| --- | --- | --- |
|
|
116
143
|
| `--yes` | `vault init`, `init` | Skip confirmation prompts |
|
|
117
|
-
| `--force` | `vault init`, `init` | Overwrite existing generated files |
|
|
144
|
+
| `--force` | `vault init`, `init`, `migrate` | Overwrite existing generated / locally-modified files |
|
|
118
145
|
| `--id <id>` | `init` | Override detected project id |
|
|
119
146
|
| `--vault <path>` | `init` | Override home vault root for this run |
|
|
120
|
-
| `--agent <id>` | `vault init` | Install for a specific agent (repeatable; default: auto-detect). Supported: `cursor`, `claude` |
|
|
147
|
+
| `--agent <id>` | `vault init`, `migrate` | Install for a specific agent (repeatable; default: auto-detect). Supported: `cursor`, `claude` |
|
|
148
|
+
| `--hooks` | `vault init`, `migrate` | Also install session-start teaser hooks (opt-in; see [Session-start hooks](#session-start-hooks)) |
|
|
149
|
+
|
|
150
|
+
### Migrate flags
|
|
151
|
+
|
|
152
|
+
| Flag | Description |
|
|
153
|
+
| --- | --- |
|
|
154
|
+
| `--force` | Overwrite slash command files you edited locally; also needed **once** when upgrading from Grounder before 0.3 |
|
|
155
|
+
| `--dry-run` | Preview without writing |
|
|
156
|
+
| `--agent <id>` | Limit to a specific agent (repeatable) |
|
|
157
|
+
| `--hooks` | Install hooks even if they were never installed before |
|
|
158
|
+
|
|
159
|
+
See [Upgrading](#upgrading) for the usual post-package-upgrade flow. Untouched command files update automatically; locally edited ones (and pre-0.3 installs with no ledger) are skipped unless you pass `--force`.
|
|
121
160
|
|
|
122
161
|
### Note / handoff flags
|
|
123
162
|
|
|
124
163
|
| Flag | Commands | Description |
|
|
125
164
|
| --- | --- | --- |
|
|
126
165
|
| `--title <slug>` | `note`, `handoff` | Filename slug (default: slugified text / first line) |
|
|
127
|
-
| `--limit <n>` | `handoff list` | Max paths to print (default: 5) |
|
|
166
|
+
| `--limit <n>` | `handoff list`, `plan list` | Max paths to print (default: 5) |
|
|
167
|
+
| `--head` | `handoff list` | Print only the newest *usable* handoff path — skips empty/unreadable files, same pick as `handoff peek` |
|
|
168
|
+
|
|
169
|
+
### Plan flags
|
|
170
|
+
|
|
171
|
+
| Flag | Commands | Description |
|
|
172
|
+
| --- | --- | --- |
|
|
173
|
+
| `--title <name>` | `plan` | Filename stem when creating/updating by name (trailing `.md` ok; sanitized, max 80 chars; no auto-slug). Mutually exclusive with `--path`. |
|
|
174
|
+
| `--path <file>` | `plan` | Update an existing plan by path (must resolve under this project's `plans/`; no title sanitization; always overwrites). Mutually exclusive with `--title`. |
|
|
175
|
+
| `--force` | `plan` | With `--title`: overwrite an existing plan (preserves original `created`, sets `updated`). Not used with `--path`. |
|
|
176
|
+
|
|
177
|
+
Unlike `note` / `handoff` (always a new dated file), `plan` is living: create or collide by `--title` (use `--force` to overwrite), or update an existing file in place with `--path`.
|
|
128
178
|
|
|
129
179
|
### Doctor flags
|
|
130
180
|
|
|
@@ -138,7 +188,7 @@ Run `grounder --help` for the full reference.
|
|
|
138
188
|
|
|
139
189
|
| Command | Job | When to use |
|
|
140
190
|
| --- | --- | --- |
|
|
141
|
-
| `grounder status` | Snapshot of Machine (home config + vault path) and Project (link, id, notes/logs, git) | “Am I wired?” — see paths and link state |
|
|
191
|
+
| `grounder status` | Snapshot of Machine (home config + vault path) and Project (link, id, notes/logs/plans, git) | “Am I wired?” — see paths and link state |
|
|
142
192
|
| `grounder doctor` | Health checklist (`ok` / `fail` / `warn`) with fix hints; exit `1` on any fail | “Why isn’t memory working?” — verify setup |
|
|
143
193
|
|
|
144
194
|
Both are read-only. `status` exits `0` even when unlinked; `doctor` fails when checks fail. Use `doctor --global` to check the machine without a project link.
|
|
@@ -161,7 +211,7 @@ Written by `grounder vault init`. Holds the vault path for this machine only.
|
|
|
161
211
|
|
|
162
212
|
Written by `grounder init` in the **current working directory**. Project id detection (when `--id` is omitted): `package.json` name in that folder → git `origin` remote (if inside a git repo) → folder basename.
|
|
163
213
|
|
|
164
|
-
`grounder note`, `grounder handoff`, and `grounder path *` walk up from the current directory to find the nearest `.grounder.json`, stopping at the git root when one exists (or at the filesystem root otherwise).
|
|
214
|
+
`grounder note`, `grounder handoff`, `grounder plan`, and `grounder path *` walk up from the current directory to find the nearest `.grounder.json`, stopping at the git root when one exists (or at the filesystem root otherwise).
|
|
165
215
|
|
|
166
216
|
**Environment variables**
|
|
167
217
|
|
|
@@ -176,8 +226,8 @@ The vault layout is agent-agnostic. `grounder vault init` installs thin glue art
|
|
|
176
226
|
|
|
177
227
|
| Agent | Detection | Artifacts |
|
|
178
228
|
| --- | --- | --- |
|
|
179
|
-
| Cursor | `~/.cursor` exists | `~/.cursor/commands/grounder-{note,task,task-handoff}.md` |
|
|
180
|
-
| Claude Code | `~/.claude` exists | `~/.claude/commands/grounder-{note,task,task-handoff}.md` |
|
|
229
|
+
| Cursor | `~/.cursor` exists | `~/.cursor/commands/grounder-{note,task,task-handoff,plan}.md` |
|
|
230
|
+
| Claude Code | `~/.claude` exists | `~/.claude/commands/grounder-{note,task,task-handoff,plan}.md` |
|
|
181
231
|
|
|
182
232
|
No `--agent` flag: auto-detect installed agents. Explicit install:
|
|
183
233
|
|
|
@@ -185,20 +235,57 @@ No `--agent` flag: auto-detect installed agents. Explicit install:
|
|
|
185
235
|
grounder vault init <path-to-your-vault> --agent=cursor --agent=claude
|
|
186
236
|
```
|
|
187
237
|
|
|
188
|
-
Slash commands
|
|
238
|
+
Slash commands invoke `~/.grounder/runtime/dist/cli.js` directly (not `npx`) — see [Session-start hooks](#session-start-hooks) for how that runtime stays current. Command files that still match what Grounder last wrote are refreshed by `grounder migrate` without `--force`. Locally edited files are left alone unless you pass `--force`.
|
|
239
|
+
|
|
240
|
+
After upgrading the package, see [Upgrading](#upgrading). `vault init --force` still works for scripts that already use it; it shares the same install path as `migrate`.
|
|
189
241
|
|
|
190
242
|
Templates live under `templates/agents/{id}/`. Adding another agent means one adapter file + one template directory — `vault init` stays agent-blind.
|
|
191
243
|
|
|
244
|
+
## Session-start hooks
|
|
245
|
+
|
|
246
|
+
Opt-in safety net for the session loop: when a Cursor or Claude Code session starts in a linked project that already has a handoff, Grounder prints **one line** reminding you it exists. You (or the agent) still decide whether to run `/grounder-task`.
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
grounder vault init <path-to-your-vault> --hooks
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Example teaser:
|
|
253
|
+
|
|
254
|
+
```text
|
|
255
|
+
[grounder] Latest handoff: "auth middleware" (2026-07-28). Run /grounder-task to load it, or ignore if unrelated.
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
What hooks do **not** do:
|
|
259
|
+
|
|
260
|
+
- They never auto-load the full handoff body into context
|
|
261
|
+
- They never block or delay a session from starting
|
|
262
|
+
- Unlinked folders and projects with no handoffs print nothing (exit 0, silent)
|
|
263
|
+
|
|
264
|
+
`doctor` reports a `warn` (never a `fail`) when a detected agent has no Grounder hook installed, and when `~/.grounder/runtime` is stale or missing.
|
|
265
|
+
|
|
266
|
+
Hooks *and* slash commands both run `~/.grounder/runtime/dist/cli.js` directly (never `npx`) — `vault init` materializes it, regardless of whether `--hooks` is passed:
|
|
267
|
+
|
|
268
|
+
- **Real install** (`npm i -g grounder`, `pnpm add -g grounder`, or a monorepo checkout) → symlinked. Upgrading overwrites the same path in place, so both stay current with **no re-run needed**.
|
|
269
|
+
- **Bare `npx grounder vault init …`** (nothing installed) → copied, since each `npx` invocation resolves to a disposable, version-pinned cache dir that can't be symlinked durably. Re-run `grounder migrate` (or `vault init`) after upgrading grounder to refresh (no `--force` needed).
|
|
270
|
+
|
|
271
|
+
If you want the runtime to stay current with zero maintenance, install grounder rather than using bare `npx` for this step.
|
|
272
|
+
|
|
273
|
+
That refresh only touches the shared runtime, not installed command files — see [Upgrading](#upgrading) if `doctor` flags stale command schemas.
|
|
274
|
+
|
|
192
275
|
## Troubleshooting
|
|
193
276
|
|
|
194
277
|
| Symptom | Try |
|
|
195
278
|
| --- | --- |
|
|
196
279
|
| Not sure if this folder is linked | `grounder status` — check Project `Linked:` and paths |
|
|
197
|
-
| Notes / handoffs fail or slash commands missing | `grounder doctor` — follow fix hints |
|
|
280
|
+
| Notes / handoffs / plans fail or slash commands missing | `grounder doctor` — follow fix hints |
|
|
198
281
|
| Machine setup only (no project yet) | `grounder doctor --global` |
|
|
199
282
|
| Home config / vault missing | `grounder vault init <path>` |
|
|
200
|
-
| No `.grounder.json` / notes dirs | `grounder init` |
|
|
201
|
-
| Agent slash commands stale
|
|
283
|
+
| No `.grounder.json` / notes / logs / plans dirs | `grounder init` |
|
|
284
|
+
| Agent slash commands stale (`doctor` warns) | `grounder migrate` — if migrate skips everything as “locally modified”, use `grounder migrate --force` once (typical when upgrading from before 0.3) |
|
|
285
|
+
| Session-start teaser missing (optional) | `grounder migrate --hooks` — `doctor` warns when absent |
|
|
286
|
+
| Shared runtime stale after upgrade (bare npx install) | `grounder migrate` — `doctor` warns when `hook-runtime` is stale |
|
|
287
|
+
| Migrate skips all commands as locally modified (first run after upgrade) | `grounder migrate --force` once, then plain `migrate` on later upgrades |
|
|
288
|
+
| Node binary gone / not executable (`doctor` fails on hook or command interpreter path) | `grounder migrate` (add `--force` if command files were edited or you’re still on a pre-0.3 install) |
|
|
202
289
|
|
|
203
290
|
## Development
|
|
204
291
|
|
package/dist/agents/claude.d.ts
CHANGED
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
import type { AgentAdapter } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Canonical SessionStart command for Claude Code (home-local runtime, not `npx`).
|
|
4
|
+
* @see {@link peekHookCommand} — REVERT: restore `"npx grounder handoff peek"` and drop runtime.
|
|
5
|
+
*/
|
|
6
|
+
export declare function claudePeekHookCommand(homeDir?: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* SessionStart matcher Grounder owns.
|
|
9
|
+
* Excludes `resume` and `fork` — those sessions already carry prior context.
|
|
10
|
+
*/
|
|
11
|
+
export declare const CLAUDE_SESSION_START_MATCHER = "startup|clear|compact";
|
|
2
12
|
export declare function claudeCommandsDir(homeDir?: string): string;
|
|
13
|
+
/** Absolute path to Claude Code's shared settings file (`~/.claude/settings.json`). */
|
|
14
|
+
export declare function claudeSettingsJsonPath(homeDir?: string): string;
|
|
3
15
|
export declare function grounderNoteCommandPath(homeDir?: string): string;
|
|
16
|
+
export declare function grounderPlanCommandPath(homeDir?: string): string;
|
|
4
17
|
export declare function grounderTaskHandoffCommandPath(homeDir?: string): string;
|
|
5
18
|
export declare function grounderTaskCommandPath(homeDir?: string): string;
|
|
6
19
|
export declare function expectedArtifacts(homeDir?: string): string[];
|
|
20
|
+
/** Paths of hook config this adapter touches — currently just `settings.json`. */
|
|
21
|
+
export declare function expectedHookArtifacts(homeDir?: string): string[];
|
|
7
22
|
export declare const claude: AgentAdapter;
|
|
8
23
|
//# sourceMappingURL=claude.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,YAAY,CAAC;AAYpB;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,0BAA0B,CAAC;AAEpE,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAgB,8BAA8B,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvE;AAED,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAE5D;AAED,kFAAkF;AAClF,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAEhE;AA+ND,eAAO,MAAM,MAAM,EAAE,YAyCpB,CAAC"}
|
package/dist/agents/claude.js
CHANGED
|
@@ -1,17 +1,44 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { resolveHomeDir } from "../connector/home.js";
|
|
5
5
|
import { fileExists } from "../util/fs.js";
|
|
6
|
+
import { mergeJsonFile } from "../util/merge-json.js";
|
|
7
|
+
import { installHookRuntime, isGrounderPeekHookCommand, isHookRuntimeStale, peekHookCommand, } from "./hook-runtime.js";
|
|
8
|
+
import { installCommandFile, recordCommandFileHashes } from "./install-command.js";
|
|
6
9
|
const pkgRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
7
10
|
const templateDir = path.join(pkgRoot, "templates", "agents", "claude", "commands");
|
|
8
|
-
const COMMANDS = [
|
|
11
|
+
const COMMANDS = [
|
|
12
|
+
"grounder-note.md",
|
|
13
|
+
"grounder-plan.md",
|
|
14
|
+
"grounder-task-handoff.md",
|
|
15
|
+
"grounder-task.md",
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* Canonical SessionStart command for Claude Code (home-local runtime, not `npx`).
|
|
19
|
+
* @see {@link peekHookCommand} — REVERT: restore `"npx grounder handoff peek"` and drop runtime.
|
|
20
|
+
*/
|
|
21
|
+
export function claudePeekHookCommand(homeDir) {
|
|
22
|
+
return peekHookCommand(homeDir);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* SessionStart matcher Grounder owns.
|
|
26
|
+
* Excludes `resume` and `fork` — those sessions already carry prior context.
|
|
27
|
+
*/
|
|
28
|
+
export const CLAUDE_SESSION_START_MATCHER = "startup|clear|compact";
|
|
9
29
|
export function claudeCommandsDir(homeDir) {
|
|
10
30
|
return path.join(resolveHomeDir(homeDir), ".claude", "commands");
|
|
11
31
|
}
|
|
32
|
+
/** Absolute path to Claude Code's shared settings file (`~/.claude/settings.json`). */
|
|
33
|
+
export function claudeSettingsJsonPath(homeDir) {
|
|
34
|
+
return path.join(resolveHomeDir(homeDir), ".claude", "settings.json");
|
|
35
|
+
}
|
|
12
36
|
export function grounderNoteCommandPath(homeDir) {
|
|
13
37
|
return path.join(claudeCommandsDir(homeDir), "grounder-note.md");
|
|
14
38
|
}
|
|
39
|
+
export function grounderPlanCommandPath(homeDir) {
|
|
40
|
+
return path.join(claudeCommandsDir(homeDir), "grounder-plan.md");
|
|
41
|
+
}
|
|
15
42
|
export function grounderTaskHandoffCommandPath(homeDir) {
|
|
16
43
|
return path.join(claudeCommandsDir(homeDir), "grounder-task-handoff.md");
|
|
17
44
|
}
|
|
@@ -21,30 +48,248 @@ export function grounderTaskCommandPath(homeDir) {
|
|
|
21
48
|
export function expectedArtifacts(homeDir) {
|
|
22
49
|
return COMMANDS.map((filename) => path.join(claudeCommandsDir(homeDir), filename));
|
|
23
50
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
51
|
+
/** Paths of hook config this adapter touches — currently just `settings.json`. */
|
|
52
|
+
export function expectedHookArtifacts(homeDir) {
|
|
53
|
+
return [claudeSettingsJsonPath(homeDir)];
|
|
54
|
+
}
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Session-start hook install (~/.claude/settings.json)
|
|
57
|
+
//
|
|
58
|
+
// Claude Code settings are a shared JSON object. Grounder only owns one nested
|
|
59
|
+
// command entry; unrelated keys (permissions, other hook events, etc.) must
|
|
60
|
+
// survive merge. Relevant shape after install (path varies by home / Node):
|
|
61
|
+
//
|
|
62
|
+
// {
|
|
63
|
+
// "hooks": {
|
|
64
|
+
// "SessionStart": [
|
|
65
|
+
// {
|
|
66
|
+
// "matcher": "startup|clear|compact",
|
|
67
|
+
// "hooks": [
|
|
68
|
+
// {
|
|
69
|
+
// "type": "command",
|
|
70
|
+
// "command": "'/path/to/node' '/path/to/.grounder/runtime/dist/cli.js' handoff peek"
|
|
71
|
+
// }
|
|
72
|
+
// ]
|
|
73
|
+
// }
|
|
74
|
+
// ]
|
|
75
|
+
// }
|
|
76
|
+
// }
|
|
77
|
+
//
|
|
78
|
+
// Terminology used below:
|
|
79
|
+
// - settings root → the whole settings.json object
|
|
80
|
+
// - hooks → settings.hooks (map of event name → matcher groups)
|
|
81
|
+
// - SessionStart → hooks.SessionStart (array of matcher groups)
|
|
82
|
+
// - matcher group → { matcher, hooks: Hook[] }
|
|
83
|
+
// - hook entry → { type: "command", command: string }
|
|
84
|
+
//
|
|
85
|
+
// Idempotency: {@link isGrounderPeekHookCommand} (runtime path or legacy npx).
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
function peekHookEntry(homeDir) {
|
|
88
|
+
return { type: "command", command: claudePeekHookCommand(homeDir) };
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Locate Grounder's peek command inside a `hooks.SessionStart` array.
|
|
92
|
+
*
|
|
93
|
+
* @param sessionStart - `settings.hooks.SessionStart` — array of matcher groups
|
|
94
|
+
* @returns Indices into that array / the group's `hooks` array, or `null` if absent
|
|
95
|
+
*/
|
|
96
|
+
function findPeekHook(sessionStart) {
|
|
97
|
+
for (let groupIdx = 0; groupIdx < sessionStart.length; groupIdx++) {
|
|
98
|
+
const group = sessionStart[groupIdx];
|
|
99
|
+
if (!group || typeof group !== "object" || Array.isArray(group)) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const hooks = group.hooks;
|
|
103
|
+
if (!Array.isArray(hooks)) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
for (let hookIdx = 0; hookIdx < hooks.length; hookIdx++) {
|
|
107
|
+
const hook = hooks[hookIdx];
|
|
108
|
+
if (hook &&
|
|
109
|
+
typeof hook === "object" &&
|
|
110
|
+
!Array.isArray(hook) &&
|
|
111
|
+
isGrounderPeekHookCommand(hook.command)) {
|
|
112
|
+
return { groupIdx, hookIdx };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
/** Whether `settings.json` already lists any Grounder peek command (for status labeling). */
|
|
119
|
+
async function peekHookHadGrounderEntry(filePath) {
|
|
120
|
+
try {
|
|
121
|
+
const parsed = JSON.parse(await readFile(filePath, "utf8"));
|
|
122
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
const hooks = parsed.hooks;
|
|
126
|
+
if (!hooks || typeof hooks !== "object" || Array.isArray(hooks)) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
const sessionStart = hooks.SessionStart;
|
|
130
|
+
return Array.isArray(sessionStart) && findPeekHook(sessionStart) !== null;
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Skip only when the canonical command is already present *and* the runtime is
|
|
138
|
+
* current for the running grounder version/source. Legacy `npx` entries or a
|
|
139
|
+
* stale runtime (missing, or symlinked/copied from a different source) always
|
|
140
|
+
* refresh — no `--force` required to migrate or to pick up an upgrade.
|
|
141
|
+
*/
|
|
142
|
+
async function peekHookUpToDate(filePath, homeDir) {
|
|
143
|
+
if (!(await fileExists(filePath))) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
if (await isHookRuntimeStale(homeDir)) {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
const parsed = JSON.parse(await readFile(filePath, "utf8"));
|
|
151
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
const hooks = parsed.hooks;
|
|
155
|
+
if (!hooks || typeof hooks !== "object" || Array.isArray(hooks)) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
const sessionStart = hooks.SessionStart;
|
|
159
|
+
if (!Array.isArray(sessionStart)) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
const found = findPeekHook(sessionStart);
|
|
163
|
+
if (!found) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
const group = sessionStart[found.groupIdx];
|
|
167
|
+
return group.hooks[found.hookIdx]?.command === claudePeekHookCommand(homeDir);
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Deep-merge Grounder's SessionStart hook into an existing settings object.
|
|
175
|
+
*
|
|
176
|
+
* Preserves every key except the nested path it owns. Strategy:
|
|
177
|
+
* 1. If a Grounder peek hook already exists (runtime or legacy npx) → replace in place.
|
|
178
|
+
* 2. Else if a matcher group with `matcher === CLAUDE_SESSION_START_MATCHER` exists →
|
|
179
|
+
* append Grounder's hook to that group's `hooks` array.
|
|
180
|
+
* 3. Else → push a new matcher group with Grounder's hook.
|
|
181
|
+
*
|
|
182
|
+
* @param current - Parsed settings.json root (object). Other top-level keys untouched.
|
|
183
|
+
* @param homeDir - Home override for the canonical command path
|
|
184
|
+
* @returns New settings object with `hooks.SessionStart` updated
|
|
185
|
+
*/
|
|
186
|
+
function mergeClaudeHooks(current, homeDir) {
|
|
187
|
+
const hooks = current.hooks && typeof current.hooks === "object" && !Array.isArray(current.hooks)
|
|
188
|
+
? { ...current.hooks }
|
|
189
|
+
: {};
|
|
190
|
+
const sessionStart = Array.isArray(hooks.SessionStart) ? [...hooks.SessionStart] : [];
|
|
191
|
+
const found = findPeekHook(sessionStart);
|
|
192
|
+
const entry = peekHookEntry(homeDir);
|
|
193
|
+
if (found) {
|
|
194
|
+
// Path 1: refresh existing Grounder hook entry in place
|
|
195
|
+
const group = { ...sessionStart[found.groupIdx] };
|
|
196
|
+
const groupHooks = Array.isArray(group.hooks) ? [...group.hooks] : [];
|
|
197
|
+
groupHooks[found.hookIdx] = entry;
|
|
198
|
+
group.hooks = groupHooks;
|
|
199
|
+
sessionStart[found.groupIdx] = group;
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
const matcherIdx = sessionStart.findIndex((group) => group &&
|
|
203
|
+
typeof group === "object" &&
|
|
204
|
+
!Array.isArray(group) &&
|
|
205
|
+
group.matcher === CLAUDE_SESSION_START_MATCHER);
|
|
206
|
+
if (matcherIdx >= 0) {
|
|
207
|
+
// Path 2: same matcher group already exists (e.g. user hooks) — append ours
|
|
208
|
+
const group = { ...sessionStart[matcherIdx] };
|
|
209
|
+
const groupHooks = Array.isArray(group.hooks) ? [...group.hooks] : [];
|
|
210
|
+
groupHooks.push(entry);
|
|
211
|
+
group.hooks = groupHooks;
|
|
212
|
+
sessionStart[matcherIdx] = group;
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
// Path 3: no matching group — create the canonical SessionStart entry
|
|
216
|
+
sessionStart.push({
|
|
217
|
+
matcher: CLAUDE_SESSION_START_MATCHER,
|
|
218
|
+
hooks: [entry],
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return { ...current, hooks: { ...hooks, SessionStart: sessionStart } };
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Install (or refresh) Grounder's SessionStart teaser hook into `~/.claude/settings.json`.
|
|
226
|
+
*
|
|
227
|
+
* Also materializes `~/.grounder/runtime` (see {@link installHookRuntime}).
|
|
228
|
+
*
|
|
229
|
+
* Force semantics:
|
|
230
|
+
* - Up-to-date canonical entry + fresh runtime and `force` false → skip
|
|
231
|
+
* - Otherwise → refresh runtime + merge host config
|
|
232
|
+
*
|
|
233
|
+
* Unparseable settings.json: {@link mergeJsonFile} backs off and this throws (never clobbers).
|
|
234
|
+
*/
|
|
235
|
+
async function installHooks(opts) {
|
|
236
|
+
const dest = claudeSettingsJsonPath(opts.homeDir);
|
|
237
|
+
const upToDate = await peekHookUpToDate(dest, opts.homeDir);
|
|
238
|
+
if (upToDate && !opts.force) {
|
|
239
|
+
return { artifacts: { [dest]: "skipped" } };
|
|
240
|
+
}
|
|
241
|
+
if (opts.dryRun) {
|
|
242
|
+
const fileExisted = await fileExists(dest);
|
|
243
|
+
const hadGrounderEntry = fileExisted && (await peekHookHadGrounderEntry(dest));
|
|
244
|
+
const status = hadGrounderEntry ? "overwritten" : "created";
|
|
245
|
+
return { artifacts: { [dest]: status } };
|
|
246
|
+
}
|
|
247
|
+
await installHookRuntime({ homeDir: opts.homeDir });
|
|
248
|
+
const fileExisted = await fileExists(dest);
|
|
249
|
+
const hadGrounderEntry = fileExisted && (await peekHookHadGrounderEntry(dest));
|
|
250
|
+
const result = await mergeJsonFile(dest, (current) => mergeClaudeHooks(current, opts.homeDir));
|
|
251
|
+
if (!result.ok) {
|
|
252
|
+
throw new Error(result.message);
|
|
29
253
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return { dest, status: existed ? "overwritten" : "created" };
|
|
254
|
+
const status = hadGrounderEntry ? "overwritten" : "created";
|
|
255
|
+
return { artifacts: { [dest]: status } };
|
|
33
256
|
}
|
|
34
257
|
export const claude = {
|
|
35
258
|
id: "claude",
|
|
36
259
|
name: "Claude Code",
|
|
260
|
+
commandsSchema: 1,
|
|
261
|
+
hooksSchema: 1,
|
|
37
262
|
async isInstalled() {
|
|
38
263
|
return fileExists(path.join(resolveHomeDir(), ".claude"));
|
|
39
264
|
},
|
|
40
265
|
expectedArtifacts,
|
|
266
|
+
expectedHookArtifacts,
|
|
41
267
|
async install(opts) {
|
|
42
268
|
const artifacts = {};
|
|
269
|
+
const files = {};
|
|
43
270
|
for (const filename of COMMANDS) {
|
|
44
|
-
const { dest, status } = await
|
|
271
|
+
const { dest, status, hash } = await installCommandFile({
|
|
272
|
+
...opts,
|
|
273
|
+
agentId: claude.id,
|
|
274
|
+
commandsSchema: claude.commandsSchema,
|
|
275
|
+
templateDir,
|
|
276
|
+
commandsDir: claudeCommandsDir(opts.homeDir),
|
|
277
|
+
filename,
|
|
278
|
+
});
|
|
45
279
|
artifacts[dest] = status;
|
|
280
|
+
if (hash) {
|
|
281
|
+
files[dest] = { schema: claude.commandsSchema, hash };
|
|
282
|
+
}
|
|
46
283
|
}
|
|
284
|
+
await recordCommandFileHashes({
|
|
285
|
+
agentId: claude.id,
|
|
286
|
+
commandsSchema: claude.commandsSchema,
|
|
287
|
+
files,
|
|
288
|
+
homeDir: opts.homeDir,
|
|
289
|
+
dryRun: opts.dryRun,
|
|
290
|
+
});
|
|
47
291
|
return { artifacts };
|
|
48
292
|
},
|
|
293
|
+
installHooks,
|
|
49
294
|
};
|
|
50
295
|
//# sourceMappingURL=claude.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read Cursor's sessionStart hook payload from stdin and return the first
|
|
3
|
+
* workspace root when present.
|
|
4
|
+
*
|
|
5
|
+
* Cursor pipes JSON like `{ "workspace_roots": ["/path/to/repo"] }` into
|
|
6
|
+
* user-level hooks, whose `cwd` is `~/.cursor` — not the open project.
|
|
7
|
+
*
|
|
8
|
+
* Never throws. Returns `undefined` for TTY stdin, empty/malformed input,
|
|
9
|
+
* missing `workspace_roots`, or when no data arrives within the timeout
|
|
10
|
+
* (so interactive/`grounder handoff peek` runs never hang). If data arrived
|
|
11
|
+
* but stdin has not ended yet, the buffered payload is still parsed.
|
|
12
|
+
*/
|
|
13
|
+
export declare function readCursorHookWorkspaceRoot(stdin?: NodeJS.ReadableStream): Promise<string | undefined>;
|
|
14
|
+
//# sourceMappingURL=cursor-hook-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor-hook-input.d.ts","sourceRoot":"","sources":["../../src/agents/cursor-hook-input.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;GAWG;AACH,wBAAsB,2BAA2B,CAC/C,KAAK,GAAE,MAAM,CAAC,cAA8B,GAC3C,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA2B7B"}
|