grounder 0.3.0 → 0.4.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.
Files changed (59) hide show
  1. package/README.md +133 -69
  2. package/dist/agents/claude.d.ts.map +1 -1
  3. package/dist/agents/claude.js +2 -3
  4. package/dist/agents/claude.js.map +1 -1
  5. package/dist/agents/cursor.d.ts.map +1 -1
  6. package/dist/agents/cursor.js +2 -3
  7. package/dist/agents/cursor.js.map +1 -1
  8. package/dist/agents/install-command.d.ts +0 -2
  9. package/dist/agents/install-command.d.ts.map +1 -1
  10. package/dist/agents/install-command.js.map +1 -1
  11. package/dist/cli.js +4 -0
  12. package/dist/cli.js.map +1 -1
  13. package/dist/commands/doctor.d.ts.map +1 -1
  14. package/dist/commands/doctor.js +113 -46
  15. package/dist/commands/doctor.js.map +1 -1
  16. package/dist/commands/handoff/list.d.ts +15 -7
  17. package/dist/commands/handoff/list.d.ts.map +1 -1
  18. package/dist/commands/handoff/list.js +16 -13
  19. package/dist/commands/handoff/list.js.map +1 -1
  20. package/dist/commands/note/list.d.ts +28 -0
  21. package/dist/commands/note/list.d.ts.map +1 -0
  22. package/dist/commands/note/list.js +72 -0
  23. package/dist/commands/note/list.js.map +1 -0
  24. package/dist/commands/note.js +1 -1
  25. package/dist/commands/note.js.map +1 -1
  26. package/dist/commands/output.d.ts +27 -0
  27. package/dist/commands/output.d.ts.map +1 -0
  28. package/dist/commands/output.js +51 -0
  29. package/dist/commands/output.js.map +1 -0
  30. package/dist/commands/plan/list.d.ts +12 -4
  31. package/dist/commands/plan/list.d.ts.map +1 -1
  32. package/dist/commands/plan/list.js +15 -9
  33. package/dist/commands/plan/list.js.map +1 -1
  34. package/dist/commands/status.d.ts.map +1 -1
  35. package/dist/commands/status.js +16 -15
  36. package/dist/commands/status.js.map +1 -1
  37. package/dist/connector/state.d.ts +3 -12
  38. package/dist/connector/state.d.ts.map +1 -1
  39. package/dist/connector/state.js +3 -21
  40. package/dist/connector/state.js.map +1 -1
  41. package/dist/help.d.ts +1 -1
  42. package/dist/help.d.ts.map +1 -1
  43. package/dist/help.js +20 -7
  44. package/dist/help.js.map +1 -1
  45. package/dist/util/parse-args.d.ts.map +1 -1
  46. package/dist/util/parse-args.js +11 -2
  47. package/dist/util/parse-args.js.map +1 -1
  48. package/dist/vault/list-notes.d.ts +15 -0
  49. package/dist/vault/list-notes.d.ts.map +1 -0
  50. package/dist/vault/list-notes.js +44 -0
  51. package/dist/vault/list-notes.js.map +1 -0
  52. package/package.json +5 -3
  53. package/templates/agents/claude/commands/grounder-note.md +25 -3
  54. package/templates/agents/claude/commands/grounder-plan.md +20 -16
  55. package/templates/agents/claude/commands/grounder-task.md +4 -2
  56. package/templates/agents/cursor/commands/grounder-note.md +26 -4
  57. package/templates/agents/cursor/commands/grounder-plan.md +21 -17
  58. package/templates/agents/cursor/commands/grounder-task-handoff.md +1 -1
  59. package/templates/agents/cursor/commands/grounder-task.md +5 -3
@@ -0,0 +1,44 @@
1
+ import { readdir, stat } from "node:fs/promises";
2
+ import path from "node:path";
3
+ /**
4
+ * Lists note markdown files under `notesDir`, newest mtime first.
5
+ * Returns absolute paths. Missing or empty dirs yield `[]`.
6
+ * Ties break by filename descending for stable output.
7
+ *
8
+ * Filename-descending alone is a viable alternative for notes (timestamp
9
+ * prefixes, like `listHandoffs`), but this intentionally matches `listPlans`
10
+ * for consistency across list commands.
11
+ */
12
+ export async function listNotes(notesDir, options = {}) {
13
+ let entries;
14
+ try {
15
+ entries = await readdir(notesDir);
16
+ }
17
+ catch (error) {
18
+ if (error.code === "ENOENT") {
19
+ return [];
20
+ }
21
+ throw error;
22
+ }
23
+ const mdNames = entries.filter((name) => name.endsWith(".md"));
24
+ const withMtime = await Promise.all(mdNames.map(async (name) => {
25
+ const filePath = path.join(notesDir, name);
26
+ const { mtimeMs } = await stat(filePath);
27
+ return { filePath, name, mtimeMs };
28
+ }));
29
+ withMtime.sort((a, b) => {
30
+ if (a.mtimeMs !== b.mtimeMs) {
31
+ return b.mtimeMs - a.mtimeMs;
32
+ }
33
+ return a.name < b.name ? 1 : a.name > b.name ? -1 : 0;
34
+ });
35
+ const paths = withMtime.map((entry) => entry.filePath);
36
+ if (options.limit === undefined) {
37
+ return paths;
38
+ }
39
+ if (options.limit <= 0) {
40
+ return [];
41
+ }
42
+ return paths.slice(0, options.limit);
43
+ }
44
+ //# sourceMappingURL=list-notes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-notes.js","sourceRoot":"","sources":["../../src/vault/list-notes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,IAAI,MAAM,WAAW,CAAC;AAO7B;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,QAAgB,EAChB,UAA4B,EAAE;IAE9B,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,GAAG,CACjC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC3C,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACrC,CAAC,CAAC,CACH,CAAC;IAEF,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACtB,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;YAC5B,OAAO,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;QAC/B,CAAC;QACD,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEvD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "grounder",
3
- "version": "0.3.0",
4
- "description": "Connect git projects to Obsidian dev vaults for AI agent memory",
3
+ "version": "0.4.0",
4
+ "description": "Markdown-native memory for Cursor and Claude Code session handoffs and plans in a vault you own",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "grounder": "./dist/cli.js"
@@ -16,7 +16,9 @@
16
16
  "keywords": [
17
17
  "obsidian",
18
18
  "cursor",
19
- "mcp",
19
+ "claude-code",
20
+ "handoff",
21
+ "developer-tools",
20
22
  "ai",
21
23
  "cli"
22
24
  ],
@@ -1,11 +1,33 @@
1
1
  Save a note to the Obsidian vault for this project.
2
2
 
3
- Run from the linked project folder or any subdirectory beneath it:
3
+ Distill the instruction after `/grounder-note` into a clean note body — not a chat transcript.
4
+ Do not dump tool traces, full conversation, or false starts.
4
5
 
5
- {{GROUNDER_CLI}} note "<user text>"
6
+ **Special case: the instruction asks to view existing notes, not write one** (`list`, `list 3 oldest`, `show notes`, etc.) → run `{{GROUNDER_CLI}} note list --limit <N>` (N = count named, else 5; ignore order words like "oldest" — output is always newest-first, never resort or relabel it) and stop — no note write. Relay the CLI stdout as-is (it already includes the count header).
7
+
8
+ Rules:
9
+ - Default → distill the args into a clean note body
10
+ - Exact wording marked to keep (quoted, "save exactly:"/"verbatim:", or a fenced block) → use that verbatim instead, unmodified
11
+ - Empty args → distill the central point of the current thread instead
12
+
13
+ Then run from the linked project folder or any subdirectory beneath it:
14
+
15
+ {{GROUNDER_CLI}} note "<body>"
16
+
17
+ Optional short title slug (filename):
18
+
19
+ {{GROUNDER_CLI}} note --title <slug> "<body>"
20
+
21
+ For multi-line bodies, prefer a shell heredoc so quoting does not break:
22
+
23
+ ```bash
24
+ {{GROUNDER_CLI}} note "$(cat <<'EOF'
25
+
26
+ EOF
27
+ )"
28
+ ```
6
29
 
7
30
  The vault is outside the workspace — grant shell permissions if Claude Code prompts you.
8
31
 
9
- Use the text after `/grounder-note` as the note body.
10
32
  Do not compute vault paths or write files yourself — the CLI handles it.
11
33
  Report the CLI output path from stdout to the user.
@@ -22,31 +22,35 @@ Build a markdown body with these sections:
22
22
 
23
23
  ```
24
24
 
25
- Update vs create — never guess a `--title` for an update:
25
+ **Special case: the instruction asks to view existing plans, not name a new topic** (`list`, `list 3 oldest`, `show plans`, etc.) → run `{{GROUNDER_CLI}} plan list --limit <N>` (N = count named, else 5; ignore order words like "oldest" output is always newest-first, never resort or relabel it) and stop — no plan write, no title. Relay the CLI stdout as-is (it already includes the count header).
26
26
 
27
- **1. Path known** (attached/open in chat, or printed by an earlier `grounder plan` this conversation): update that exact file.
27
+ Otherwise, resolve the target, then **state it plainly before writing** `Updating plan at <path>.` or `Creating new plan titled <title>.` This is a visible record, not a blocking confirmation — updates overwrite with no `--force`, so get the match right.
28
+
29
+ **1. Known path** (attached/open in chat, or printed by an earlier `grounder plan` this conversation) → update it directly.
30
+
31
+ **2. No path, but update intent** (e.g. "update/continue/revise the plan", or a name that sounds like an existing one) → look it up first:
28
32
 
29
33
  ```bash
30
- {{GROUNDER_CLI}} plan "$(cat <<'EOF'
31
- # Plan: …
32
-
33
- EOF
34
- )" --path <path-to-existing-plan.md>
34
+ {{GROUNDER_CLI}} plan list --limit 5
35
35
  ```
36
36
 
37
- `--path` must resolve under this project's `plans/` dir; it always overwrites (no `--force`).
37
+ CLI output starts with a count header, then each result as a numbered two-line block — `N. ` + title (filename stem) on the first line, the absolute path indented beneath it.
38
38
 
39
- **2. Path unknown** (e.g. "update the plan" with nothing attached and no prior path this conversation): look it up, then update as in (1).
39
+ A match counts only if its title actually corresponds to what the user named — not just "it's the only plan in the project." No name given and exactly one plan exists → that counts too. If the user refers to a plan by the number shown in *this* listing (e.g. "update plan 2"), that counts as a match too — resolve it to the path from this same output, don't reuse a number from an earlier listing in the conversation (it's positional, not a stable id, and can shift if plans changed since). Otherwise (no match, several matches, or a name/number that doesn't correspond to any existing plan) → ask; never guess.
40
+
41
+ Cases 1 and 2 (update) — run:
40
42
 
41
43
  ```bash
42
- {{GROUNDER_CLI}} plan list --limit 5
44
+ {{GROUNDER_CLI}} plan "$(cat <<'EOF'
45
+ # Plan: …
46
+
47
+ EOF
48
+ )" --path <path>
43
49
  ```
44
50
 
45
- Pick the path matching the user's intent; ask if none or several match.
51
+ `--path` must resolve under this project's `plans/` dir; it always overwrites (no `--force`).
46
52
 
47
- **3. Genuinely new plan** (not an update): derive a `--title`.
48
- - If the instruction names one explicitly (e.g. `save as "implementation-phase-1"` or `…phase-1.md`), use it (strip a trailing `.md`).
49
- - Otherwise derive a short kebab-case name from the plan's title/goal and confirm it with the user before writing.
53
+ **3. No path, no update intent → genuinely new plan.** Derive a `--title` (the user's explicit name, else a short kebab-case slug from the plan's title/goal) and write immediately — don't ask about the name itself.
50
54
 
51
55
  ```bash
52
56
  {{GROUNDER_CLI}} plan "$(cat <<'EOF'
@@ -56,10 +60,10 @@ EOF
56
60
  )" --title <name>
57
61
  ```
58
62
 
59
- If the CLI refuses because that name already exists (non-zero exit; stderr names the conflict), tell the user and ask whether to overwrite (`--force`) or pick a different name. `--force` only resolves this title collision — it is never how you update a plan you already meant to target (use `--path` for that). **Never** silently pass `--force`.
63
+ If `--title` collides with an existing plan (non-zero exit; stderr names the conflict), ask: overwrite (`--force`) or a different name. `--force` only resolves that collision — **never** use it to update a plan you meant to target with `--path`.
60
64
 
61
65
  Run from the linked project folder or any subdirectory beneath it.
62
66
  The vault is outside the workspace — grant shell permissions if Claude Code prompts you.
63
67
 
64
68
  Do not compute vault paths or write files yourself — the CLI handles it.
65
- Report the CLI output path from stdout to the user.
69
+ Report the exact path the CLI prints on stdout it confirms the real outcome, not just the intent.
@@ -2,7 +2,9 @@ Hydrate this session from the latest vault handoff and repo truth.
2
2
 
3
3
  Read-only — do not write to the vault. Do not invent vault paths.
4
4
 
5
- From the linked project folder or any subdirectory beneath it:
5
+ **Special case: the instruction asks to view existing handoffs, not hydrate** (`list`, `list 3 oldest`, `show handoffs`, etc.) → run `{{GROUNDER_CLI}} handoff list --limit <N>` (N = count named, else 5; ignore order words like "oldest" — output is always newest-first, never resort or relabel it) and stop — no hydrate, no `AGENTS.md`, no “start work.” Relay the CLI stdout as-is (it already includes the count header).
6
+
7
+ Otherwise, from the linked project folder or any subdirectory beneath it:
6
8
 
7
9
  1. Get the current handoff (skips empty/unreadable files, same pick as the session-start teaser):
8
10
 
@@ -10,7 +12,7 @@ From the linked project folder or any subdirectory beneath it:
10
12
 
11
13
  2. If empty: tell the user there are no handoffs yet, then read repo `AGENTS.md` only and proceed.
12
14
 
13
- 3. Otherwise, read that file. If the user names a specific session instead, run `{{GROUNDER_CLI}} handoff list --limit 5` and read the path they mean.
15
+ 3. Otherwise, read that file. If the user names a specific session instead: `{{GROUNDER_CLI}} handoff list --limit 5` match name/index to the indented path in *this* listing (positional, not a stable id). Miss → once with `--limit 50` (*that* listing only). Still miss → tell the user and stop — no guessed hydrate.
14
16
 
15
17
  4. Read repo `AGENTS.md` (project conventions and constraints).
16
18
 
@@ -1,11 +1,33 @@
1
1
  Save a note to the Obsidian vault for this project.
2
2
 
3
- Run from the linked project folder or any subdirectory beneath it:
3
+ Distill the instruction after `/grounder-note` into a clean note body — not a chat transcript.
4
+ Do not dump tool traces, full conversation, or false starts.
4
5
 
5
- {{GROUNDER_CLI}} note "<user text>"
6
+ **Special case: the instruction asks to view existing notes, not write one** (`list`, `list 3 oldest`, `show notes`, etc.) → run `{{GROUNDER_CLI}} note list --limit <N>` (N = count named, else 5; ignore order words like "oldest" — output is always newest-first, never resort or relabel it) and stop — no note write. Relay the CLI stdout as-is (it already includes the count header).
6
7
 
7
- The vault is outside the workspace — approve shell permissions if Cursor prompts you.
8
+ Rules:
9
+ - Default → distill the args into a clean note body
10
+ - Exact wording marked to keep (quoted, "save exactly:"/"verbatim:", or a fenced block) → use that verbatim instead, unmodified
11
+ - Empty args → distill the central point of the current thread instead
12
+
13
+ Then run from the linked project folder or any subdirectory beneath it:
14
+
15
+ {{GROUNDER_CLI}} note "<body>"
16
+
17
+ Optional short title slug (filename):
18
+
19
+ {{GROUNDER_CLI}} note --title <slug> "<body>"
20
+
21
+ For multi-line bodies, prefer a shell heredoc so quoting does not break:
22
+
23
+ ```bash
24
+ {{GROUNDER_CLI}} note "$(cat <<'EOF'
25
+
26
+ EOF
27
+ )"
28
+ ```
29
+
30
+ Run {{GROUNDER_CLI}} with `required_permissions: ["all"]` (vault is outside the workspace).
8
31
 
9
- Use the text after `/grounder-note` as the note body.
10
32
  Do not compute vault paths or write files yourself — the CLI handles it.
11
33
  Report the CLI output path from stdout to the user.
@@ -22,31 +22,35 @@ Build a markdown body with these sections:
22
22
 
23
23
  ```
24
24
 
25
- Update vs create — never guess a `--title` for an update:
25
+ **Special case: the instruction asks to view existing plans, not name a new topic** (`list`, `list 3 oldest`, `show plans`, etc.) → run `{{GROUNDER_CLI}} plan list --limit <N>` (N = count named, else 5; ignore order words like "oldest" output is always newest-first, never resort or relabel it) and stop — no plan write, no title. Relay the CLI stdout as-is (it already includes the count header).
26
26
 
27
- **1. Path known** (attached/open in chat, or printed by an earlier `grounder plan` this conversation): update that exact file.
27
+ Otherwise, resolve the target, then **state it plainly before writing** `Updating plan at <path>.` or `Creating new plan titled <title>.` This is a visible record, not a blocking confirmation — updates overwrite with no `--force`, so get the match right.
28
+
29
+ **1. Known path** (attached/open in chat, or printed by an earlier `grounder plan` this conversation) → update it directly.
30
+
31
+ **2. No path, but update intent** (e.g. "update/continue/revise the plan", or a name that sounds like an existing one) → look it up first:
28
32
 
29
33
  ```bash
30
- {{GROUNDER_CLI}} plan "$(cat <<'EOF'
31
- # Plan: …
32
-
33
- EOF
34
- )" --path <path-to-existing-plan.md>
34
+ {{GROUNDER_CLI}} plan list --limit 5
35
35
  ```
36
36
 
37
- `--path` must resolve under this project's `plans/` dir; it always overwrites (no `--force`).
37
+ CLI output starts with a count header, then each result as a numbered two-line block — `N. ` + title (filename stem) on the first line, the absolute path indented beneath it.
38
38
 
39
- **2. Path unknown** (e.g. "update the plan" with nothing attached and no prior path this conversation): look it up, then update as in (1).
39
+ A match counts only if its title actually corresponds to what the user named — not just "it's the only plan in the project." No name given and exactly one plan exists → that counts too. If the user refers to a plan by the number shown in *this* listing (e.g. "update plan 2"), that counts as a match too — resolve it to the path from this same output, don't reuse a number from an earlier listing in the conversation (it's positional, not a stable id, and can shift if plans changed since). Otherwise (no match, several matches, or a name/number that doesn't correspond to any existing plan) → ask; never guess.
40
+
41
+ Cases 1 and 2 (update) — run:
40
42
 
41
43
  ```bash
42
- {{GROUNDER_CLI}} plan list --limit 5
44
+ {{GROUNDER_CLI}} plan "$(cat <<'EOF'
45
+ # Plan: …
46
+
47
+ EOF
48
+ )" --path <path>
43
49
  ```
44
50
 
45
- Pick the path matching the user's intent; ask if none or several match.
51
+ `--path` must resolve under this project's `plans/` dir; it always overwrites (no `--force`).
46
52
 
47
- **3. Genuinely new plan** (not an update): derive a `--title`.
48
- - If the instruction names one explicitly (e.g. `save as "implementation-phase-1"` or `…phase-1.md`), use it (strip a trailing `.md`).
49
- - Otherwise derive a short kebab-case name from the plan's title/goal and confirm it with the user before writing.
53
+ **3. No path, no update intent → genuinely new plan.** Derive a `--title` (the user's explicit name, else a short kebab-case slug from the plan's title/goal) and write immediately — don't ask about the name itself.
50
54
 
51
55
  ```bash
52
56
  {{GROUNDER_CLI}} plan "$(cat <<'EOF'
@@ -56,10 +60,10 @@ EOF
56
60
  )" --title <name>
57
61
  ```
58
62
 
59
- If the CLI refuses because that name already exists (non-zero exit; stderr names the conflict), tell the user and ask whether to overwrite (`--force`) or pick a different name. `--force` only resolves this title collision — it is never how you update a plan you already meant to target (use `--path` for that). **Never** silently pass `--force`.
63
+ If `--title` collides with an existing plan (non-zero exit; stderr names the conflict), ask: overwrite (`--force`) or a different name. `--force` only resolves that collision — **never** use it to update a plan you meant to target with `--path`.
60
64
 
61
65
  Run from the linked project folder or any subdirectory beneath it.
62
- The vault is outside the workspace — approve shell permissions if Cursor prompts you.
66
+ Run {{GROUNDER_CLI}} with `required_permissions: ["all"]` (vault is outside the workspace).
63
67
 
64
68
  Do not compute vault paths or write files yourself — the CLI handles it.
65
- Report the CLI output path from stdout to the user.
69
+ Report the exact path the CLI prints on stdout it confirms the real outcome, not just the intent.
@@ -48,7 +48,7 @@ EOF
48
48
  )"
49
49
  ```
50
50
 
51
- The vault is outside the workspace — approve shell permissions if Cursor prompts you.
51
+ Run {{GROUNDER_CLI}} with `required_permissions: ["all"]` (vault is outside the workspace).
52
52
 
53
53
  Do not compute vault paths or write files yourself — the CLI handles it.
54
54
  Report the CLI output path from stdout to the user.
@@ -2,7 +2,9 @@ Hydrate this session from the latest vault handoff and repo truth.
2
2
 
3
3
  Read-only — do not write to the vault. Do not invent vault paths.
4
4
 
5
- From the linked project folder or any subdirectory beneath it:
5
+ **Special case: the instruction asks to view existing handoffs, not hydrate** (`list`, `list 3 oldest`, `show handoffs`, etc.) → run `{{GROUNDER_CLI}} handoff list --limit <N>` (N = count named, else 5; ignore order words like "oldest" — output is always newest-first, never resort or relabel it) and stop — no hydrate, no `AGENTS.md`, no “start work.” Relay the CLI stdout as-is (it already includes the count header).
6
+
7
+ Otherwise, from the linked project folder or any subdirectory beneath it:
6
8
 
7
9
  1. Get the current handoff (skips empty/unreadable files, same pick as the session-start teaser):
8
10
 
@@ -10,11 +12,11 @@ From the linked project folder or any subdirectory beneath it:
10
12
 
11
13
  2. If empty: tell the user there are no handoffs yet, then read repo `AGENTS.md` only and proceed.
12
14
 
13
- 3. Otherwise, read that file. If the user names a specific session instead, run `{{GROUNDER_CLI}} handoff list --limit 5` and read the path they mean.
15
+ 3. Otherwise, read that file. If the user names a specific session instead: `{{GROUNDER_CLI}} handoff list --limit 5` match name/index to the indented path in *this* listing (positional, not a stable id). Miss → once with `--limit 50` (*that* listing only). Still miss → tell the user and stop — no guessed hydrate.
14
16
 
15
17
  4. Read repo `AGENTS.md` (project conventions and constraints).
16
18
 
17
19
  5. Summarize briefly what is next (from the handoff `## Next` section when present), then start work.
18
20
 
19
- The vault is outside the workspace — approve shell permissions if Cursor prompts you.
21
+ Run {{GROUNDER_CLI}} with `required_permissions: ["all"]` (vault is outside the workspace).
20
22
  Use free-text after `/grounder-task` as optional focus (session name, index, or task hint).