grounder 0.0.1 → 0.1.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 (147) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +204 -2
  3. package/dist/agents/claude.d.ts +8 -0
  4. package/dist/agents/claude.d.ts.map +1 -0
  5. package/dist/agents/claude.js +50 -0
  6. package/dist/agents/claude.js.map +1 -0
  7. package/dist/agents/cursor.d.ts +8 -0
  8. package/dist/agents/cursor.d.ts.map +1 -0
  9. package/dist/agents/cursor.js +50 -0
  10. package/dist/agents/cursor.js.map +1 -0
  11. package/dist/agents/index.d.ts +11 -0
  12. package/dist/agents/index.d.ts.map +1 -0
  13. package/dist/agents/index.js +23 -0
  14. package/dist/agents/index.js.map +1 -0
  15. package/dist/agents/types.d.ts +22 -0
  16. package/dist/agents/types.d.ts.map +1 -0
  17. package/dist/agents/types.js +2 -0
  18. package/dist/agents/types.js.map +1 -0
  19. package/dist/cli.d.ts +3 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +108 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/commands/check.d.ts +13 -0
  24. package/dist/commands/check.d.ts.map +1 -0
  25. package/dist/commands/check.js +21 -0
  26. package/dist/commands/check.js.map +1 -0
  27. package/dist/commands/doctor.d.ts +9 -0
  28. package/dist/commands/doctor.d.ts.map +1 -0
  29. package/dist/commands/doctor.js +204 -0
  30. package/dist/commands/doctor.js.map +1 -0
  31. package/dist/commands/handoff/list.d.ts +23 -0
  32. package/dist/commands/handoff/list.d.ts.map +1 -0
  33. package/dist/commands/handoff/list.js +64 -0
  34. package/dist/commands/handoff/list.js.map +1 -0
  35. package/dist/commands/handoff.d.ts +25 -0
  36. package/dist/commands/handoff.d.ts.map +1 -0
  37. package/dist/commands/handoff.js +47 -0
  38. package/dist/commands/handoff.js.map +1 -0
  39. package/dist/commands/note.d.ts +10 -0
  40. package/dist/commands/note.d.ts.map +1 -0
  41. package/dist/commands/note.js +33 -0
  42. package/dist/commands/note.js.map +1 -0
  43. package/dist/commands/path/logs.d.ts +7 -0
  44. package/dist/commands/path/logs.d.ts.map +1 -0
  45. package/dist/commands/path/logs.js +17 -0
  46. package/dist/commands/path/logs.js.map +1 -0
  47. package/dist/commands/path/notes.d.ts +7 -0
  48. package/dist/commands/path/notes.d.ts.map +1 -0
  49. package/dist/commands/path/notes.js +17 -0
  50. package/dist/commands/path/notes.js.map +1 -0
  51. package/dist/commands/repo/init.d.ts +11 -0
  52. package/dist/commands/repo/init.d.ts.map +1 -0
  53. package/dist/commands/repo/init.js +78 -0
  54. package/dist/commands/repo/init.js.map +1 -0
  55. package/dist/commands/require-linked.d.ts +7 -0
  56. package/dist/commands/require-linked.d.ts.map +1 -0
  57. package/dist/commands/require-linked.js +19 -0
  58. package/dist/commands/require-linked.js.map +1 -0
  59. package/dist/commands/status.d.ts +7 -0
  60. package/dist/commands/status.d.ts.map +1 -0
  61. package/dist/commands/status.js +101 -0
  62. package/dist/commands/status.js.map +1 -0
  63. package/dist/commands/vault/init.d.ts +11 -0
  64. package/dist/commands/vault/init.d.ts.map +1 -0
  65. package/dist/commands/vault/init.js +73 -0
  66. package/dist/commands/vault/init.js.map +1 -0
  67. package/dist/connector/git.d.ts +12 -0
  68. package/dist/connector/git.d.ts.map +1 -0
  69. package/dist/connector/git.js +53 -0
  70. package/dist/connector/git.js.map +1 -0
  71. package/dist/connector/home.d.ts +13 -0
  72. package/dist/connector/home.d.ts.map +1 -0
  73. package/dist/connector/home.js +52 -0
  74. package/dist/connector/home.js.map +1 -0
  75. package/dist/connector/linked.d.ts +25 -0
  76. package/dist/connector/linked.d.ts.map +1 -0
  77. package/dist/connector/linked.js +24 -0
  78. package/dist/connector/linked.js.map +1 -0
  79. package/dist/connector/project-id.d.ts +17 -0
  80. package/dist/connector/project-id.d.ts.map +1 -0
  81. package/dist/connector/project-id.js +102 -0
  82. package/dist/connector/project-id.js.map +1 -0
  83. package/dist/connector/repo.d.ts +9 -0
  84. package/dist/connector/repo.d.ts.map +1 -0
  85. package/dist/connector/repo.js +41 -0
  86. package/dist/connector/repo.js.map +1 -0
  87. package/dist/connector/vault.d.ts +12 -0
  88. package/dist/connector/vault.d.ts.map +1 -0
  89. package/dist/connector/vault.js +27 -0
  90. package/dist/connector/vault.js.map +1 -0
  91. package/dist/index.d.ts +2 -0
  92. package/dist/index.d.ts.map +1 -0
  93. package/dist/index.js +7 -0
  94. package/dist/index.js.map +1 -0
  95. package/dist/util/fs.d.ts +8 -0
  96. package/dist/util/fs.d.ts.map +1 -0
  97. package/dist/util/fs.js +36 -0
  98. package/dist/util/fs.js.map +1 -0
  99. package/dist/util/parse-args.d.ts +12 -0
  100. package/dist/util/parse-args.d.ts.map +1 -0
  101. package/dist/util/parse-args.js +49 -0
  102. package/dist/util/parse-args.js.map +1 -0
  103. package/dist/util/path.d.ts +10 -0
  104. package/dist/util/path.d.ts.map +1 -0
  105. package/dist/util/path.js +22 -0
  106. package/dist/util/path.js.map +1 -0
  107. package/dist/util/project-id.d.ts +2 -0
  108. package/dist/util/project-id.d.ts.map +1 -0
  109. package/dist/util/project-id.js +8 -0
  110. package/dist/util/project-id.js.map +1 -0
  111. package/dist/util/prompt.d.ts +2 -0
  112. package/dist/util/prompt.d.ts.map +1 -0
  113. package/dist/util/prompt.js +19 -0
  114. package/dist/util/prompt.js.map +1 -0
  115. package/dist/util/timestamp-slug.d.ts +38 -0
  116. package/dist/util/timestamp-slug.d.ts.map +1 -0
  117. package/dist/util/timestamp-slug.js +66 -0
  118. package/dist/util/timestamp-slug.js.map +1 -0
  119. package/dist/util/yaml.d.ts +6 -0
  120. package/dist/util/yaml.d.ts.map +1 -0
  121. package/dist/util/yaml.js +13 -0
  122. package/dist/util/yaml.js.map +1 -0
  123. package/dist/vault/layout.d.ts +13 -0
  124. package/dist/vault/layout.d.ts.map +1 -0
  125. package/dist/vault/layout.js +22 -0
  126. package/dist/vault/layout.js.map +1 -0
  127. package/dist/vault/list-handoffs.d.ts +10 -0
  128. package/dist/vault/list-handoffs.d.ts.map +1 -0
  129. package/dist/vault/list-handoffs.js +30 -0
  130. package/dist/vault/list-handoffs.js.map +1 -0
  131. package/dist/vault/write-handoff.d.ts +21 -0
  132. package/dist/vault/write-handoff.d.ts.map +1 -0
  133. package/dist/vault/write-handoff.js +40 -0
  134. package/dist/vault/write-handoff.js.map +1 -0
  135. package/dist/vault/write-note.d.ts +11 -0
  136. package/dist/vault/write-note.d.ts.map +1 -0
  137. package/dist/vault/write-note.js +15 -0
  138. package/dist/vault/write-note.js.map +1 -0
  139. package/package.json +45 -10
  140. package/templates/agents/claude/commands/grounder-note.md +11 -0
  141. package/templates/agents/claude/commands/grounder-task-handoff.md +54 -0
  142. package/templates/agents/claude/commands/grounder-task.md +20 -0
  143. package/templates/agents/cursor/commands/grounder-note.md +11 -0
  144. package/templates/agents/cursor/commands/grounder-task-handoff.md +54 -0
  145. package/templates/agents/cursor/commands/grounder-task.md +20 -0
  146. package/templates/vault/session-handoff.md +19 -0
  147. package/index.js +0 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Grounder contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,205 @@
1
- # grounder
1
+ # Grounder
2
2
 
3
- Setting up Git connections for Obsidian vaults to play nice with AI agents.
3
+ [![npm version](https://img.shields.io/npm/v/grounder.svg)](https://www.npmjs.com/package/grounder)
4
+ [![license](https://img.shields.io/npm/l/grounder.svg)](../../LICENSE)
5
+
6
+ AI coding agents forget everything between sessions. Grounder gives them persistent memory in a personal Obsidian vault — notes and handoffs live outside the repo, under your control, and never get committed.
7
+
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
10
+ - **Structured handoffs** — end a session with a Done/Next/Blockers/Decisions checkpoint; resume next time by hydrating from it
11
+ - **Zero per-project install** — slash commands shell out via `npx`; nothing to add to the repo besides the marker file
12
+
13
+ **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
+ **Contents:** [Install](#install) · [Quickstart](#quickstart) · [Setup overview](#setup-overview) · [Commands](#commands) · [Configuration](#configuration) · [Agents](#agents) · [Troubleshooting](#troubleshooting)
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ npm install -g grounder
21
+ ```
22
+
23
+ Or run without installing:
24
+
25
+ ```bash
26
+ npx grounder --help
27
+ ```
28
+
29
+ `grounder -h` prints the full reference; `grounder -v` prints the installed version.
30
+
31
+ ## Quickstart
32
+
33
+ **1. One-time setup:**
34
+
35
+ ```bash
36
+ # Once per machine — set vault location + install agent slash commands
37
+ grounder vault init <path-to-your-vault>
38
+
39
+ # Once per project folder — link project id to vault notes/ + logs/
40
+ cd your-project
41
+ grounder init
42
+ ```
43
+
44
+ Both commands preview what they'll write and ask to confirm; add `--yes` to skip the prompt (e.g. in scripts).
45
+
46
+ **2. Daily use — from your agent's chat:**
47
+
48
+ ```text
49
+ > /grounder-task
50
+
51
+ Reading latest handoff… (logs/2026-07-21-091500-auth-middleware.md)
52
+ Done: mapped middleware order.
53
+ Next: 1. Add tests for 401 path
54
+ Starting on tests for the 401 path now.
55
+
56
+ > ...you work with the agent...
57
+
58
+ > /grounder-task-handoff
59
+
60
+ Wrote handoff → <vault>/10-Projects/your-project/logs/2026-07-28-143200-auth-middleware.md
61
+ ```
62
+
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).
64
+
65
+ No agent, or want to write by hand? The same actions are plain CLI commands:
66
+
67
+ ```bash
68
+ grounder note "Investigate auth middleware" # ad-hoc note
69
+ grounder handoff "# Handoff: ...\n\n## Next\n1. ..." # session checkpoint
70
+ grounder handoff list # newest handoffs, for manual hydrate
71
+ ```
72
+
73
+ Notes land in `<vault>/10-Projects/{projectId}/notes/`.
74
+ Handoffs land in `<vault>/10-Projects/{projectId}/logs/` (one file per close; newest wins).
75
+
76
+ Inspect or debug setup any time with `grounder status` / `grounder doctor` — see [Troubleshooting](#troubleshooting).
77
+
78
+ ### Session loop
79
+
80
+ ```text
81
+ /grounder-task → work → /grounder-task-handoff → next /grounder-task
82
+ ```
83
+
84
+ | Slash command | CLI | Role |
85
+ | --- | --- | --- |
86
+ | `/grounder-note` | `grounder note` | Ad-hoc vault note |
87
+ | `/grounder-task-handoff` | `grounder handoff` | Write session checkpoint to `logs/` |
88
+ | `/grounder-task` | `grounder handoff list` + read newest | Read-only hydrate from newest handoff + `AGENTS.md` |
89
+
90
+ ## Setup overview
91
+
92
+ - **`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/` and `logs/`.
94
+ - **Daily use** — notes, handoffs, and recall via CLI or slash commands; no further install.
95
+
96
+ 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
+
98
+ ## Commands
99
+
100
+ ```text
101
+ grounder vault init <path> Initialize vault + home config (once per machine)
102
+ grounder init Connect the current folder to your vault
103
+ grounder note <text> Write a note to the vault
104
+ grounder handoff <text> Write a session handoff to vault logs/
105
+ grounder handoff list Print recent handoff paths (newest first)
106
+ grounder path notes Print resolved notes directory
107
+ grounder path logs Print resolved logs directory
108
+ grounder status Snapshot of machine + project link + resolved paths
109
+ grounder doctor Health checks with fix hints
110
+ ```
111
+
112
+ ### Init flags
113
+
114
+ | Flag | Commands | Description |
115
+ | --- | --- | --- |
116
+ | `--yes` | `vault init`, `init` | Skip confirmation prompts |
117
+ | `--force` | `vault init`, `init` | Overwrite existing generated files |
118
+ | `--id <id>` | `init` | Override detected project id |
119
+ | `--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` |
121
+
122
+ ### Note / handoff flags
123
+
124
+ | Flag | Commands | Description |
125
+ | --- | --- | --- |
126
+ | `--title <slug>` | `note`, `handoff` | Filename slug (default: slugified text / first line) |
127
+ | `--limit <n>` | `handoff list` | Max paths to print (default: 5) |
128
+
129
+ ### Doctor flags
130
+
131
+ | Flag | Description |
132
+ | --- | --- |
133
+ | `--global` | Machine-only checks (skip project/link checks) |
134
+
135
+ Run `grounder --help` for the full reference.
136
+
137
+ ### Status vs doctor
138
+
139
+ | Command | Job | When to use |
140
+ | --- | --- | --- |
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 |
142
+ | `grounder doctor` | Health checklist (`ok` / `fail` / `warn`) with fix hints; exit `1` on any fail | “Why isn’t memory working?” — verify setup |
143
+
144
+ 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.
145
+
146
+ ## Configuration
147
+
148
+ **Machine config** — `~/.grounder/config.json`:
149
+
150
+ ```json
151
+ { "vaultRoot": "/path/to/your/vault" }
152
+ ```
153
+
154
+ Written by `grounder vault init`. Holds the vault path for this machine only.
155
+
156
+ **Link marker** — `.grounder.json` in the folder where you run `grounder init` (safe to commit):
157
+
158
+ ```json
159
+ { "version": 1, "projectId": "your-project" }
160
+ ```
161
+
162
+ 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
+
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).
165
+
166
+ **Environment variables**
167
+
168
+ | Variable | Description |
169
+ | --- | --- |
170
+ | `GROUNDER_VAULT` | Override vault root for the current session |
171
+ | `GROUNDER_HOME` | Override home directory (default: `~`) for config resolution |
172
+
173
+ ## Agents
174
+
175
+ The vault layout is agent-agnostic. `grounder vault init` installs thin glue artifacts per detected agent via a pluggable adapter registry (`src/agents/`).
176
+
177
+ | Agent | Detection | Artifacts |
178
+ | --- | --- | --- |
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` |
181
+
182
+ No `--agent` flag: auto-detect installed agents. Explicit install:
183
+
184
+ ```bash
185
+ grounder vault init <path-to-your-vault> --agent=cursor --agent=claude
186
+ ```
187
+
188
+ Slash commands tell the agent to run `npx grounder …` from the linked project folder (no global install required). Re-run with `--force` to refresh existing installs.
189
+
190
+ Templates live under `templates/agents/{id}/`. Adding another agent means one adapter file + one template directory — `vault init` stays agent-blind.
191
+
192
+ ## Troubleshooting
193
+
194
+ | Symptom | Try |
195
+ | --- | --- |
196
+ | 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 |
198
+ | Machine setup only (no project yet) | `grounder doctor --global` |
199
+ | Home config / vault missing | `grounder vault init <path>` |
200
+ | No `.grounder.json` / notes dirs | `grounder init` |
201
+ | Agent slash commands stale or partial | `grounder vault init <path> --force` (or `--agent=<id>`) |
202
+
203
+ ## Development
204
+
205
+ Source, tests, and contribution workflow live in the [Grounder monorepo](https://github.com/andrej-kolic/grounder).
@@ -0,0 +1,8 @@
1
+ import type { AgentAdapter } from "./types.js";
2
+ export declare function claudeCommandsDir(homeDir?: string): string;
3
+ export declare function grounderNoteCommandPath(homeDir?: string): string;
4
+ export declare function grounderTaskHandoffCommandPath(homeDir?: string): string;
5
+ export declare function grounderTaskCommandPath(homeDir?: string): string;
6
+ export declare function expectedArtifacts(homeDir?: string): string[];
7
+ export declare const claude: AgentAdapter;
8
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,YAAY,CAAC;AAOpB,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1D;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;AAkBD,eAAO,MAAM,MAAM,EAAE,YAkBpB,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { copyFile, mkdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { resolveHomeDir } from "../connector/home.js";
5
+ import { fileExists } from "../util/fs.js";
6
+ const pkgRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
7
+ const templateDir = path.join(pkgRoot, "templates", "agents", "claude", "commands");
8
+ const COMMANDS = ["grounder-note.md", "grounder-task-handoff.md", "grounder-task.md"];
9
+ export function claudeCommandsDir(homeDir) {
10
+ return path.join(resolveHomeDir(homeDir), ".claude", "commands");
11
+ }
12
+ export function grounderNoteCommandPath(homeDir) {
13
+ return path.join(claudeCommandsDir(homeDir), "grounder-note.md");
14
+ }
15
+ export function grounderTaskHandoffCommandPath(homeDir) {
16
+ return path.join(claudeCommandsDir(homeDir), "grounder-task-handoff.md");
17
+ }
18
+ export function grounderTaskCommandPath(homeDir) {
19
+ return path.join(claudeCommandsDir(homeDir), "grounder-task.md");
20
+ }
21
+ export function expectedArtifacts(homeDir) {
22
+ return COMMANDS.map((filename) => path.join(claudeCommandsDir(homeDir), filename));
23
+ }
24
+ async function installCommand(filename, opts) {
25
+ const dest = path.join(claudeCommandsDir(opts.homeDir), filename);
26
+ const existed = await fileExists(dest);
27
+ if (existed && !opts.force) {
28
+ return { dest, status: "skipped" };
29
+ }
30
+ await mkdir(path.dirname(dest), { recursive: true });
31
+ await copyFile(path.join(templateDir, filename), dest);
32
+ return { dest, status: existed ? "overwritten" : "created" };
33
+ }
34
+ export const claude = {
35
+ id: "claude",
36
+ name: "Claude Code",
37
+ async isInstalled() {
38
+ return fileExists(path.join(resolveHomeDir(), ".claude"));
39
+ },
40
+ expectedArtifacts,
41
+ async install(opts) {
42
+ const artifacts = {};
43
+ for (const filename of COMMANDS) {
44
+ const { dest, status } = await installCommand(filename, opts);
45
+ artifacts[dest] = status;
46
+ }
47
+ return { artifacts };
48
+ },
49
+ };
50
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/agents/claude.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { AgentAdapter } from "./types.js";
2
+ export declare function cursorCommandsDir(homeDir?: string): string;
3
+ export declare function grounderNoteCommandPath(homeDir?: string): string;
4
+ export declare function grounderTaskHandoffCommandPath(homeDir?: string): string;
5
+ export declare function grounderTaskCommandPath(homeDir?: string): string;
6
+ export declare function expectedArtifacts(homeDir?: string): string[];
7
+ export declare const cursor: AgentAdapter;
8
+ //# sourceMappingURL=cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../src/agents/cursor.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,YAAY,CAAC;AAOpB,wBAAgB,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE1D;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;AAkBD,eAAO,MAAM,MAAM,EAAE,YAkBpB,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { copyFile, mkdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { resolveHomeDir } from "../connector/home.js";
5
+ import { fileExists } from "../util/fs.js";
6
+ const pkgRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
7
+ const templateDir = path.join(pkgRoot, "templates", "agents", "cursor", "commands");
8
+ const COMMANDS = ["grounder-note.md", "grounder-task-handoff.md", "grounder-task.md"];
9
+ export function cursorCommandsDir(homeDir) {
10
+ return path.join(resolveHomeDir(homeDir), ".cursor", "commands");
11
+ }
12
+ export function grounderNoteCommandPath(homeDir) {
13
+ return path.join(cursorCommandsDir(homeDir), "grounder-note.md");
14
+ }
15
+ export function grounderTaskHandoffCommandPath(homeDir) {
16
+ return path.join(cursorCommandsDir(homeDir), "grounder-task-handoff.md");
17
+ }
18
+ export function grounderTaskCommandPath(homeDir) {
19
+ return path.join(cursorCommandsDir(homeDir), "grounder-task.md");
20
+ }
21
+ export function expectedArtifacts(homeDir) {
22
+ return COMMANDS.map((filename) => path.join(cursorCommandsDir(homeDir), filename));
23
+ }
24
+ async function installCommand(filename, opts) {
25
+ const dest = path.join(cursorCommandsDir(opts.homeDir), filename);
26
+ const existed = await fileExists(dest);
27
+ if (existed && !opts.force) {
28
+ return { dest, status: "skipped" };
29
+ }
30
+ await mkdir(path.dirname(dest), { recursive: true });
31
+ await copyFile(path.join(templateDir, filename), dest);
32
+ return { dest, status: existed ? "overwritten" : "created" };
33
+ }
34
+ export const cursor = {
35
+ id: "cursor",
36
+ name: "Cursor",
37
+ async isInstalled() {
38
+ return fileExists(path.join(resolveHomeDir(), ".cursor"));
39
+ },
40
+ expectedArtifacts,
41
+ async install(opts) {
42
+ const artifacts = {};
43
+ for (const filename of COMMANDS) {
44
+ const { dest, status } = await installCommand(filename, opts);
45
+ artifacts[dest] = status;
46
+ }
47
+ return { artifacts };
48
+ },
49
+ };
50
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/agents/cursor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { AgentAdapter } from "./types.js";
2
+ export { claude } from "./claude.js";
3
+ export { cursor } from "./cursor.js";
4
+ export type { AgentAdapter, AgentInstallOptions, AgentInstallResult, ArtifactStatus, } from "./types.js";
5
+ /**
6
+ * Resolve which adapters to run:
7
+ * - If `ids` is provided, return those adapters (throws on unknown id).
8
+ * - Otherwise, auto-detect by checking isInstalled() for each adapter.
9
+ */
10
+ export declare function resolveAgents(ids?: string[]): Promise<AgentAdapter[]>;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EACV,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,GACf,MAAM,YAAY,CAAC;AAIpB;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAc3E"}
@@ -0,0 +1,23 @@
1
+ import { claude } from "./claude.js";
2
+ import { cursor } from "./cursor.js";
3
+ export { claude } from "./claude.js";
4
+ export { cursor } from "./cursor.js";
5
+ const ALL_ADAPTERS = [cursor, claude];
6
+ /**
7
+ * Resolve which adapters to run:
8
+ * - If `ids` is provided, return those adapters (throws on unknown id).
9
+ * - Otherwise, auto-detect by checking isInstalled() for each adapter.
10
+ */
11
+ export async function resolveAgents(ids) {
12
+ if (ids && ids.length > 0) {
13
+ const found = ALL_ADAPTERS.filter((a) => ids.includes(a.id));
14
+ const unknown = ids.filter((id) => !ALL_ADAPTERS.some((a) => a.id === id));
15
+ if (unknown.length > 0) {
16
+ throw new Error(`Unknown agent id(s): ${unknown.join(", ")}`);
17
+ }
18
+ return found;
19
+ }
20
+ const results = await Promise.all(ALL_ADAPTERS.map(async (a) => ({ adapter: a, ok: await a.isInstalled() })));
21
+ return results.filter((r) => r.ok).map((r) => r.adapter);
22
+ }
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAQrC,MAAM,YAAY,GAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,GAAc;IAChD,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QAC3E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAC3E,CAAC;IACF,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,22 @@
1
+ export type ArtifactStatus = "created" | "skipped" | "overwritten";
2
+ export interface AgentInstallOptions {
3
+ force?: boolean;
4
+ homeDir?: string;
5
+ }
6
+ export interface AgentInstallResult {
7
+ /** Map of installed file path → what happened to it. */
8
+ artifacts: Record<string, ArtifactStatus>;
9
+ }
10
+ export interface AgentAdapter {
11
+ /** Stable lowercase id used in config and flags, e.g. "cursor". */
12
+ readonly id: string;
13
+ /** Human-readable display name, e.g. "Cursor". */
14
+ readonly name: string;
15
+ /** Returns true when this agent appears to be installed on the machine. */
16
+ isInstalled(): Promise<boolean>;
17
+ /** Absolute paths of artifacts this adapter installs (read-only inspect). */
18
+ expectedArtifacts(homeDir?: string): string[];
19
+ /** Install all agent-specific artifacts (commands, rules, etc.). */
20
+ install(opts: AgentInstallOptions): Promise<AgentInstallResult>;
21
+ }
22
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;AAEnE,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,kBAAkB;IACjC,wDAAwD;IACxD,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,YAAY;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,2EAA2E;IAC3E,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,6EAA6E;IAC7E,iBAAiB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC9C,oEAAoE;IACpE,OAAO,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACjE"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":""}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { runDoctor } from "./commands/doctor.js";
6
+ import { runHandoffList } from "./commands/handoff/list.js";
7
+ import { runHandoff } from "./commands/handoff.js";
8
+ import { runNote } from "./commands/note.js";
9
+ import { runPathLogs } from "./commands/path/logs.js";
10
+ import { runPathNotes } from "./commands/path/notes.js";
11
+ import { runRepoInit } from "./commands/repo/init.js";
12
+ import { runStatus } from "./commands/status.js";
13
+ import { runVaultInit } from "./commands/vault/init.js";
14
+ const pkgRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
15
+ const pkg = JSON.parse(readFileSync(path.join(pkgRoot, "package.json"), "utf8"));
16
+ const USAGE = `grounder — connect git projects to Obsidian dev vaults for AI agents
17
+
18
+ Usage:
19
+ grounder vault init <path> Initialize vault + home config (once per machine)
20
+ grounder init Connect the current repo to your vault
21
+ grounder note <text> Write a note to the vault
22
+ grounder handoff <text> Write a session handoff to vault logs/
23
+ grounder handoff list Print recent handoff paths (newest first)
24
+ grounder path notes Print resolved notes directory
25
+ grounder path logs Print resolved logs directory
26
+ grounder status Snapshot of machine + project link + resolved paths
27
+ grounder doctor Health checks with fix hints
28
+
29
+ Options:
30
+ -h, --help Show this help
31
+ -v, --version Show version
32
+
33
+ Init flags:
34
+ --yes Skip confirmation prompts
35
+ --force Overwrite existing generated files
36
+ --id <id> Override detected project id (grounder init)
37
+ --vault <path> Override home vault root for this run (grounder init)
38
+ --agent <id> Install for a specific agent (repeatable; default: auto-detect)
39
+ Supported: cursor, claude
40
+
41
+ Doctor flags:
42
+ --global Machine-only checks (skip project/link checks)
43
+
44
+ Note / handoff flags:
45
+ --title <slug> Short slug in filename (default: slugified first line)
46
+ --limit <n> Max paths for handoff list (default: 5)
47
+
48
+ Quickstart:
49
+ grounder vault init ~/Documents/obsidian/dev
50
+ grounder init
51
+ grounder note "my first note"
52
+ grounder handoff "# Handoff\\n\\n## Next\\n1. …"
53
+ grounder handoff list
54
+ `;
55
+ function printHelp() {
56
+ process.stdout.write(USAGE);
57
+ }
58
+ function printVersion() {
59
+ process.stdout.write(`${pkg.version}\n`);
60
+ }
61
+ async function main() {
62
+ const args = process.argv.slice(2);
63
+ if (args.length === 0 || args[0] === "-h" || args[0] === "--help") {
64
+ printHelp();
65
+ process.exit(0);
66
+ }
67
+ if (args[0] === "-v" || args[0] === "--version") {
68
+ printVersion();
69
+ return;
70
+ }
71
+ const [command, ...rest] = args;
72
+ if (command === "vault" && rest[0] === "init") {
73
+ process.exit(await runVaultInit(rest.slice(1)));
74
+ }
75
+ if (command === "init") {
76
+ process.exit(await runRepoInit(rest));
77
+ }
78
+ if (command === "note") {
79
+ process.exit(await runNote(rest));
80
+ }
81
+ if (command === "handoff" && rest[0] === "list") {
82
+ process.exit(await runHandoffList(rest.slice(1)));
83
+ }
84
+ if (command === "handoff") {
85
+ process.exit(await runHandoff(rest));
86
+ }
87
+ if (command === "path" && rest[0] === "notes") {
88
+ process.exit(await runPathNotes(rest.slice(1)));
89
+ }
90
+ if (command === "path" && rest[0] === "logs") {
91
+ process.exit(await runPathLogs(rest.slice(1)));
92
+ }
93
+ if (command === "status") {
94
+ process.exit(await runStatus(rest));
95
+ }
96
+ if (command === "doctor") {
97
+ process.exit(await runDoctor(rest));
98
+ }
99
+ process.stderr.write(`Unknown command: ${args.join(" ")}\n\n`);
100
+ printHelp();
101
+ process.exit(1);
102
+ }
103
+ main().catch((error) => {
104
+ const message = error instanceof Error ? error.message : String(error);
105
+ process.stderr.write(`${message}\n`);
106
+ process.exit(1);
107
+ });
108
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /** Shared result shape for doctor (and similar) health checks. */
2
+ export type CheckLevel = "ok" | "fail" | "warn";
3
+ export interface CheckResult {
4
+ id: string;
5
+ level: CheckLevel;
6
+ message: string;
7
+ /** Actionable fix hint when level is not `"ok"`. */
8
+ fix?: string;
9
+ }
10
+ export declare function okCheck(id: string, message: string): CheckResult;
11
+ export declare function failCheck(id: string, message: string, fix?: string): CheckResult;
12
+ export declare function warnCheck(id: string, message: string, fix?: string): CheckResult;
13
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAElE,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AAEhD,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,CAEhE;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAOhF;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,WAAW,CAOhF"}
@@ -0,0 +1,21 @@
1
+ /** Shared result shape for doctor (and similar) health checks. */
2
+ export function okCheck(id, message) {
3
+ return { id, level: "ok", message };
4
+ }
5
+ export function failCheck(id, message, fix) {
6
+ return {
7
+ id,
8
+ level: "fail",
9
+ message,
10
+ ...(fix !== undefined ? { fix } : {}),
11
+ };
12
+ }
13
+ export function warnCheck(id, message, fix) {
14
+ return {
15
+ id,
16
+ level: "warn",
17
+ message,
18
+ ...(fix !== undefined ? { fix } : {}),
19
+ };
20
+ }
21
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAYlE,MAAM,UAAU,OAAO,CAAC,EAAU,EAAE,OAAe;IACjD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EAAU,EAAE,OAAe,EAAE,GAAY;IACjE,OAAO;QACL,EAAE;QACF,KAAK,EAAE,MAAM;QACb,OAAO;QACP,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,EAAU,EAAE,OAAe,EAAE,GAAY;IACjE,OAAO;QACL,EAAE;QACF,KAAK,EAAE,MAAM;QACb,OAAO;QACP,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ export interface DoctorOptions {
2
+ cwd?: string;
3
+ homeDir?: string;
4
+ /** Machine-only checks (skip project/link checks). */
5
+ global?: boolean;
6
+ }
7
+ export declare function runDoctor(argv: string[]): Promise<number>;
8
+ export declare function runDoctorWithOptions(options?: DoctorOptions): Promise<number>;
9
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA2OD,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAG/D;AAED,wBAAsB,oBAAoB,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBvF"}