From 27fbf91d484401ad58aa779e20bb379ce0754076 Mon Sep 17 00:00:00 2001 From: Tobi Lutke Date: Sat, 13 Dec 2025 09:41:31 -0500 Subject: [PATCH] Fix context add to support collection root paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Virtual paths like qmd://journals/ were rejected as invalid Changes: - Updated parseVirtualPath() regex to make path optional: /^qmd:\/\/([^\/]+)\/?(.*)$/ - Now supports: qmd://name, qmd://name/, qmd://name/path - Empty path represents collection root context - Improved help message with collection root example - Better output message showing "(collection root)" for clarity - Updated CLAUDE.md documentation Test cases verified: ✓ qmd context add qmd://journals/ "..." (with trailing slash) ✓ qmd context add qmd://journals "..." (without trailing slash) ✓ qmd context add qmd://journals/2024 "..." (with specific path) Fixes issue where users couldn't add context to entire collections 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .beads/issues.jsonl | 1 + CLAUDE.md | 1 + src/qmd.ts | 9 ++++++++- src/store.ts | 7 +++++-- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index bb5481a..0828e9b 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -11,6 +11,7 @@ {"id":"qmd-clr","title":"fix embed","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-12T16:14:55.292114-05:00","updated_at":"2025-12-12T16:31:27.661829-05:00","closed_at":"2025-12-12T16:31:27.661829-05:00"} {"id":"qmd-deh","title":"Refactor database introduce qmd collection *","description":"","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-10T10:56:04.516137-05:00","updated_at":"2025-12-12T16:12:12.349428-05:00","closed_at":"2025-12-12T16:12:12.349428-05:00"} {"id":"qmd-dmi","title":"Implement 'qmd collection' commands","description":"Add explicit collection management:\n- qmd collection add . --name \u003cname\u003e --mask '**/*.md'\n- qmd collection list\n- qmd collection remove \u003cname\u003e\n\nThis gives users control over collection names and patterns.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-12-12T15:29:53.810666-05:00","updated_at":"2025-12-12T16:02:08.079158-05:00","closed_at":"2025-12-12T16:02:08.079158-05:00","dependencies":[{"issue_id":"qmd-dmi","depends_on_id":"qmd-ama","type":"discovered-from","created_at":"2025-12-12T15:29:53.811294-05:00","created_by":"daemon"}]} +{"id":"qmd-dt1","title":"Redesign context add command for better usability","description":"Current issues: \n1. Virtual path qmd://journals/ is rejected as invalid\n2. Syntax is confusing - sometimes path is first arg, sometimes second\n3. Need to support collection root context (qmd://name/)\n4. Should be intuitive: qmd context add \u003cwhere\u003e \u003cwhat\u003e\nDesign goals:\n- Support qmd://collection/ for collection root context\n- Support qmd://collection/path for path-specific context\n- Clear, consistent syntax\n- Good error messages","status":"in_progress","priority":1,"issue_type":"task","created_at":"2025-12-13T09:39:19.764114-05:00","updated_at":"2025-12-13T09:39:26.497481-05:00"} {"id":"qmd-e2c","title":"Implement 'qmd ls' command","description":"Add command to explore virtual file tree:\n- qmd ls → list all collections\n- qmd ls \u003ccollection\u003e → list files in collection\n- qmd ls \u003ccollection\u003e/\u003cpath\u003e → list files under path\nOutput: flat list of qmd:// paths","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-12-12T15:29:53.859804-05:00","updated_at":"2025-12-12T15:55:12.777701-05:00","closed_at":"2025-12-12T15:55:12.777701-05:00","dependencies":[{"issue_id":"qmd-e2c","depends_on_id":"qmd-ama","type":"discovered-from","created_at":"2025-12-12T15:29:53.860535-05:00","created_by":"daemon"}]} {"id":"qmd-i3t","title":"Move context management DB operations to store.ts","description":"Move path_contexts INSERT/DELETE/SELECT operations from addContext(), listContexts(), removeContext() to store.ts. Create methods like insertContext(), deleteContext(), etc.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-12-12T16:36:21.561746-05:00","updated_at":"2025-12-12T16:48:57.271485-05:00","closed_at":"2025-12-12T16:48:57.271485-05:00","dependencies":[{"issue_id":"qmd-i3t","depends_on_id":"qmd-29c","type":"parent-child","created_at":"2025-12-12T16:37:02.866006-05:00","created_by":"daemon"}]} {"id":"qmd-j9z","title":"Add unit tests for content addressable hashes","description":"add same file from multiple places and verify that they both point at same hash. drop one collection and the content stays.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-12-12T15:39:15.459504-05:00","updated_at":"2025-12-12T16:21:35.473776-05:00","closed_at":"2025-12-12T16:21:35.473776-05:00"} diff --git a/CLAUDE.md b/CLAUDE.md index 0678499..99d0ab0 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -62,6 +62,7 @@ qmd context add /subfolder "Description for subfolder" qmd context add / "Always include this context" # Add context using virtual paths +qmd context add qmd://journals/ "Context for entire journals collection" qmd context add qmd://journals/2024 "Journal entries from 2024" # List all contexts diff --git a/src/qmd.ts b/src/qmd.ts index 9fbe6ef..ee910d1 100755 --- a/src/qmd.ts +++ b/src/qmd.ts @@ -689,7 +689,10 @@ async function contextAdd(pathArg: string | undefined, contextText: string): Pro insertContext(db, coll.id, parsed.path, contextText); - console.log(`${c.green}✓${c.reset} Added context for: qmd://${parsed.collectionName}/${parsed.path || ''}`); + const displayPath = parsed.path + ? `qmd://${parsed.collectionName}/${parsed.path}` + : `qmd://${parsed.collectionName}/ (collection root)`; + console.log(`${c.green}✓${c.reset} Added context for: ${displayPath}`); console.log(`${c.dim}Context: ${contextText}${c.reset}`); closeDb(); return; @@ -2456,11 +2459,15 @@ switch (cli.command) { case "add": { if (cli.args.length < 2) { console.error("Usage: qmd context add [path] \"text\""); + console.error(""); console.error("Examples:"); console.error(" qmd context add \"Context for current directory\""); console.error(" qmd context add . \"Context for current directory\""); console.error(" qmd context add /subfolder \"Context for subfolder\""); console.error(" qmd context add / \"Global context for all collections\""); + console.error(""); + console.error(" Using virtual paths:"); + console.error(" qmd context add qmd://journals/ \"Context for entire journals collection\""); console.error(" qmd context add qmd://journals/2024 \"Context for 2024 journals\""); process.exit(1); } diff --git a/src/store.ts b/src/store.ts index 5170f73..67acc82 100644 --- a/src/store.ts +++ b/src/store.ts @@ -102,13 +102,16 @@ export type VirtualPath = { /** * Parse a virtual path like "qmd://collection-name/path/to/file.md" * into its components. + * Also supports collection root: "qmd://collection-name/" or "qmd://collection-name" */ export function parseVirtualPath(virtualPath: string): VirtualPath | null { - const match = virtualPath.match(/^qmd:\/\/([^\/]+)\/(.+)$/); + // Match: qmd://collection-name[/optional-path] + // Allows: qmd://name, qmd://name/, qmd://name/path + const match = virtualPath.match(/^qmd:\/\/([^\/]+)\/?(.*)$/); if (!match) return null; return { collectionName: match[1], - path: match[2], + path: match[2] || '', // Empty string for collection root }; }