From 997e64b3d80834258cdc0e6be8089783b7614e49 Mon Sep 17 00:00:00 2001 From: Danny Smith Date: Sun, 15 Mar 2026 01:18:04 +0000 Subject: [PATCH 1/5] Add Cowork environment support to tdn plugin Update the Claude Code plugin to detect and handle Cowork sandboxed environments: auto-install tdn from GitHub Releases, discover mounted vault directories, and create local config. Also suppress spurious "outside home directory" warnings for /sessions/ and /mnt/ paths. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../task-x-claude-cowork-integration.md | 214 ++++++++---------- tdn-claude-plugin/README.md | 34 +++ tdn-claude-plugin/commands/prime.md | 16 +- .../skills/task-management/SKILL.md | 1 + .../skills/task-management/cowork.md | 96 ++++++++ tdn-cli/src/config/index.ts | 5 +- tdn-cli/tests/unit/config-security.test.ts | 12 + 7 files changed, 254 insertions(+), 124 deletions(-) create mode 100644 tdn-claude-plugin/skills/task-management/cowork.md diff --git a/docs/tasks-todo/task-x-claude-cowork-integration.md b/docs/tasks-todo/task-x-claude-cowork-integration.md index 2fcfecc2..9a7493b8 100644 --- a/docs/tasks-todo/task-x-claude-cowork-integration.md +++ b/docs/tasks-todo/task-x-claude-cowork-integration.md @@ -2,166 +2,137 @@ ## Background -Anthropic released [Claude Cowork](https://claude.com/blog/cowork-research-preview) in January 2026 - a research preview that brings Claude Code's agentic capabilities to Claude Desktop for non-developers. It runs tasks in an isolated Linux VM using Apple's Virtualization Framework (VZVirtualMachine). +Anthropic released [Claude Cowork](https://claude.com/blog/cowork-research-preview) in January 2026 — a research preview that brings Claude Code's agentic capabilities to Claude Desktop for non-developers. It runs tasks in an isolated Linux VM. **Key technical details:** -- Runs a lightweight Linux VM on macOS (Apple Silicon only currently) -- Uses VZVirtualMachine with a custom Linux rootfs -- Pre-installed tools: Python, git, grep (no Node.js/Bun) -- User folders mounted at paths like `/sessions/[session-id]/mnt/[folder-name]` -- Hard isolation: Claude can only access explicitly mounted directories +- Runs a lightweight Linux VM (Apple Silicon Macs and Windows) +- Hard isolation: Claude can only access explicitly mounted/shared folders - No `~/.taskdn.json` or global `tdn` binary available +- No access to host `~/.claude/` — plugins/skills are managed via the Desktop app UI +- Pre-installed tools include Python, git, grep, curl (no Node.js/Bun) **Goal:** Make the existing Claude Code plugin (`tdn-claude-plugin/`) work in both: 1. Claude Code (local machine, `tdn` globally installed) -2. Cowork sandbox (bundled binary, mounted directories) +2. Cowork sandbox (binary installed at session start, mounted directories) -## Research Sources +## Research (March 2026 Update) -- [Cowork announcement](https://claude.com/blog/cowork-research-preview) -- [Simon Willison's analysis](https://simonwillison.net/2026/Jan/12/claude-cowork/) -- [Cowork Architecture Deep Dive](https://claudecn.com/en/blog/claude-cowork-architecture/) -- [Getting Started with Cowork](https://support.claude.com/en/articles/13345190-getting-started-with-cowork) -- [HN discussion](https://news.ycombinator.com/item?id=46613304) +The original version of this doc (January 2026) proposed bundling a pre-compiled binary with the plugin. That approach doesn't work: -## Proposed Approach +1. **Plugins can't bundle binaries** — the Claude Code plugin system supports markdown skills, scripts, hooks, and MCP configs, but not pre-compiled executables. +2. **Binary is 102MB** — the standalone `tdn` binary (built with `bun build --compile`) is far larger than the 15-25MB originally estimated. +3. **Cowork VM can't see `~/.claude/`** — plugin directories on the host aren't accessible from inside the VM. -Bundle a pre-compiled Linux ARM64 `tdn` binary with the skill. When Claude detects it's in a sandboxed Cowork environment (no global `tdn`, mounted paths), use the bundled binary with a dynamically created config file. +### What Does Work (Verified) -### Why This Approach +Proof of concept tested on Linux ARM64 (2026-03-14): -1. **Binary compilation works**: `bun build --compile` creates self-contained executables -2. **Config already flexible**: CLI supports env vars > local `.taskdn.json` > user config > defaults -3. **Cross-compilation ready**: Already builds for `linux-arm64-gnu` and `linux-arm64-musl` +- `bun build --compile --minify src/index.ts --outfile dist/tdn-linux-arm64` produces a working standalone binary +- The binary runs with zero dependencies beyond glibc +- A local `.taskdn.json` in the working directory correctly overrides defaults +- `tdn context --ai` successfully reads a vault and produces structured output +- The existing `install.sh` script handles Linux ARM64 detection and installation -## Implementation Checklist - -### Phase 1: Build & Verify Binary +### Revised Approach: Install at Session Start -- [ ] Build Linux ARM64 standalone binary - ```bash - # Build for glibc (standard Linux) - napi build --release --target aarch64-unknown-linux-gnu -o bindings - bun build --compile --minify src/index.ts --outfile dist/tdn-linux-arm64 - ``` -- [ ] Verify binary size (expect 15-25MB) - check if acceptable for skill bundling -- [ ] Test binary in Cowork VM manually (mount folder containing binary, run it) -- [ ] Determine if Cowork uses glibc or musl +Instead of bundling, have Claude install `tdn` from GitHub Releases at the start of each Cowork session. The user mounts their vault folders, and the skill guides Claude through setup. -### Phase 2: Environment Detection +**Why this works:** +- `curl` and `tar` are available in the Cowork VM +- The install script already supports `linux-arm64` +- Local `.taskdn.json` in the working directory takes precedence over global config +- No changes needed to the binary or release pipeline -- [ ] Add detection logic to SKILL.md: - - Check if `which tdn` returns a path (Claude Code) - - Check for `/sessions/*/mnt/*` paths (Cowork) - - Check for bundled binary in known location -- [ ] Document detection signals: - -| Signal | Claude Code | Cowork | -|--------|-------------|--------| -| `which tdn` | Returns path | Empty/error | -| `/sessions/*/mnt/` | No | Yes | -| `~/.taskdn.json` | Usually exists | No | +## Implementation Checklist -### Phase 3: Update Plugin Structure +### Phase 1: Cowork Setup Documentation [✅ DONE] -- [ ] Add binary to plugin: - ``` - tdn-claude-plugin/ - ├── bin/ - │ └── tdn-linux-arm64 # Bundled binary - ├── skills/ - │ └── task-management/ - │ ├── SKILL.md # Updated with env detection - │ ├── setup-cowork.md # NEW: Cowork setup docs - │ └── ... - └── commands/ - ├── prime.md # Updated to handle both envs - └── setup.md # NEW: /tdn:setup command - ``` +- [x] Create `skills/task-management/cowork.md` with: + - How Cowork environment differs from Claude Code + - Step-by-step setup instructions for Claude to follow + - How to discover mounted vault directories + - How to create a local `.taskdn.json` + - Troubleshooting (no internet, wrong paths, etc.) -### Phase 4: Create Setup Flow +### Phase 2: Update `/tdn:prime` for Environment Detection [✅ DONE] -- [ ] Create `/tdn:setup` command that: - 1. Detects environment (Claude Code vs Cowork) - 2. In Cowork: discovers mounted directories - 3. Creates local `.taskdn.json` with mounted paths: - ```json - { - "tasksDir": "/sessions/xxx/mnt/tasks", - "projectsDir": "/sessions/xxx/mnt/projects", - "areasDir": "/sessions/xxx/mnt/areas" - } - ``` - 4. Verifies binary works: `./tdn-linux-arm64 config --ai` -- [ ] Update `/tdn:prime` to run setup if needed +- [x] Update `commands/prime.md` to detect the environment before running commands: + 1. Check if `tdn` is already available (`which tdn`) + 2. If not: check for Cowork signals (mounted paths, no home dir config) + 3. If Cowork detected: run install script, discover mounted dirs, create `.taskdn.json` + 4. Then proceed with normal priming (`tdn config --ai && tdn context --ai`) +- [x] Add `cowork.md` to the skill's detailed documentation list in SKILL.md -### Phase 5: Update SKILL.md +### Phase 3: Handle the "No Internet" Fallback [✅ DONE] -- [ ] Add "Environment Detection" section -- [ ] Add "Cowork Setup" section -- [ ] Update command patterns to use appropriate binary path -- [ ] Document that users must mount tasks/projects/areas folders +- [x] Document a fallback for when `curl` can't reach GitHub (e.g. no internet in VM): + - User can pre-download the binary and include it in a mounted folder + - Skill docs explain: "place `tdn` binary in your mounted folder, Claude will find it" + - Claude searches mounted directories for a `tdn` or `tdn-linux-arm64` executable +- [x] Add fallback instructions to `cowork.md` -### Phase 6: Documentation & Distribution +### Phase 4: Update Plugin README [✅ DONE] -- [ ] Update plugin README with Cowork instructions -- [ ] Document user requirements: - - Must grant folder access to tasks, projects, and areas directories - - May need to include binary in a mounted folder (if plugins aren't accessible in VM) -- [ ] Consider a "Cowork starter kit" with binary included +- [x] Add "Using with Claude Cowork" section to README +- [x] Document user requirements: + - Must share/mount their tasks, projects, and areas folders + - Binary is downloaded automatically on first use (or placed in a mounted folder) +- [x] Note that setup runs once per session (not persistent across sessions) -## Key Unknowns to Resolve +### Phase 5: Suppress Warnings for Cowork Paths [✅ DONE] -1. **Plugin accessibility in Cowork**: Are `~/.claude/plugins/` files accessible from inside the Cowork VM? May need binary distributed separately. +- [x] The CLI warned when dirs are "outside your home directory" — this always triggers in Cowork where paths look like `/sessions/xxx/mnt/tasks` +- [x] Added `/sessions/` and `/mnt/` to the exemption list alongside `/tmp/` and `/var/folders/` +- [x] Added tests for the new exemptions +- [x] This was a CLI change in `tdn-cli/src/config/index.ts` -2. **Skill size limits**: Is there a maximum size for skill bundles? Binary is 15-25MB. +## Environment Detection Signals -3. **libc variant**: Does Cowork's Linux use glibc or musl? (Likely glibc) +| Signal | Claude Code | Cowork | +|--------|-------------|--------| +| `which tdn` | Returns path | Empty/error | +| `~/.taskdn.json` | Usually exists | No | +| Mounted paths (`/sessions/*/mnt/*` or similar) | No | Yes | +| `uname -s` | Darwin (usually) | Linux | +| Internet access | Yes | Usually yes | -4. **Session persistence**: Each session gets new ID - config needs regeneration each time. +## Setup Flow (What Claude Does) -5. **Path discovery**: Need reliable way to find mounted directories (glob `/sessions/*/mnt/*`). +``` +1. User says /tdn:prime (or asks about tasks) +2. Claude checks: which tdn + ├─ Found → normal flow (Claude Code) + └─ Not found → Cowork setup: + a. Install: curl -fsSL | bash + ├─ Success → continue + └─ Failure → look for binary in mounted dirs + b. Discover vault dirs in mounted paths + c. Create .taskdn.json with discovered paths + d. Verify: tdn config --ai + e. Continue with normal priming +``` ## Path Mapping Reference | User's Mac | Cowork VM | |------------|-----------| -| `~/notes/tasks` | `/sessions/xxx/mnt/tasks` | +| `~/notes/tasks` | `/sessions/xxx/mnt/tasks` (or similar) | | `~/notes/projects` | `/sessions/xxx/mnt/projects` | | `~/notes/areas` | `/sessions/xxx/mnt/areas` | -## Modified Command Pattern - -```markdown -# In SKILL.md - -## Running Commands - -Determine the tdn binary path at session start: - -**Claude Code (global)**: -```bash -TDN_BIN="tdn" -``` - -**Cowork (bundled)**: -```bash -TDN_BIN="/path/to/mounted/bin/tdn-linux-arm64" -``` - -Then use consistently: -```bash -$TDN_BIN list --ai -$TDN_BIN new "Task title" --ai -``` -``` +The exact mount paths depend on what the user shares and the session ID. Claude should discover these dynamically rather than assuming a structure. ## Alternative Approaches Considered +### Binary Bundling in Plugin (Original Plan — Rejected) +Bundle a pre-compiled `tdn` binary inside the plugin directory. Rejected because: +- Plugin system doesn't support binary bundling +- Binary is 102MB (too large) +- Cowork VM can't access host plugin directories + ### MCP Server (Rejected) Create an MCP server wrapping tdn CLI that runs on host. Rejected because: - User explicitly doesn't want MCP -- Unclear if Cowork VM can access host MCP servers - Adds complexity ### Python-based Skill (Rejected) @@ -170,8 +141,13 @@ Reimplement CLI logic in Python (pre-installed in Cowork). Rejected because: - Maintenance burden of two implementations - Loses Rust performance benefits -### Direct File Access Only (Partial) -Just mount directories and work with files directly. Acceptable as fallback but: +### Direct File Access Only (Fallback) +Just mount directories and work with files directly. Acceptable as degraded fallback but: - Loses CLI benefits (validation, querying, formatted output) - More error-prone for mutations -- Could be used as degraded mode if binary doesn't work +- The skill's `templates.md` and `specification.md` already document the file format for this case + +## Open Questions + +1. **Internet in Cowork VM** — Can the VM always reach GitHub to download releases? If not, the "pre-download binary" fallback becomes the primary path. +2. **Install location persistence** — Does `~/.local/bin/` persist across Cowork sessions or is it wiped? If wiped, install runs every session (acceptable — takes seconds). diff --git a/tdn-claude-plugin/README.md b/tdn-claude-plugin/README.md index ce6cb8f9..dc3e552e 100644 --- a/tdn-claude-plugin/README.md +++ b/tdn-claude-plugin/README.md @@ -85,11 +85,13 @@ tdn-claude-plugin/ ├── .claude-plugin/ │ └── plugin.json # Plugin manifest ├── commands/ +│ ├── prime.md # /tdn:prime slash command │ └── today.md # /tdn:today slash command ├── skills/ │ └── task-management/ │ ├── SKILL.md # Main skill (overview) │ ├── command-reference.md +│ ├── cowork.md # Cowork environment setup │ ├── decision-guide.md │ ├── examples.md │ ├── specification.md @@ -97,6 +99,38 @@ tdn-claude-plugin/ └── README.md ``` +## Using with Claude Cowork + +This plugin works in [Claude Cowork](https://claude.com/blog/cowork-research-preview) (Anthropic's sandboxed desktop VM environment) with automatic setup. + +### Requirements + +You must **share/mount your vault folders** with the Cowork session: +- Your `tasks` directory +- Your `projects` directory +- Your `areas` directory + +### How It Works + +When you run `/tdn:prime` (or ask about your tasks), Claude will: + +1. Detect that `tdn` isn't installed +2. Download and install it automatically from GitHub Releases +3. Discover your mounted vault directories +4. Create a local config file pointing to them +5. Proceed normally + +If the download fails (e.g. no internet), Claude will look for a `tdn` binary you've placed in one of your mounted folders. If no binary is available at all, Claude falls back to working with your task files directly. + +### Pre-downloading the Binary (Optional) + +If your Cowork sessions don't have internet access, download the Linux ARM64 binary from [GitHub Releases](https://github.com/taskdn/taskdn/releases) and place it in one of the folders you share with Cowork. + +### Notes + +- Setup runs once per session (not persistent across sessions) +- The CLI may warn about paths being "outside your home directory" — this is expected and harmless in Cowork + ## Contributing This plugin is part of the [Taskdn](../) monorepo. See the main repository for contribution guidelines. diff --git a/tdn-claude-plugin/commands/prime.md b/tdn-claude-plugin/commands/prime.md index 86131f6d..c128e000 100644 --- a/tdn-claude-plugin/commands/prime.md +++ b/tdn-claude-plugin/commands/prime.md @@ -1,10 +1,20 @@ --- description: Prime the current session with general context from taskdn and load the task-management skill -allowed-tools: Bash(tdn:*), Skill(tdn:task-management) +allowed-tools: Bash(tdn:*), Bash(which:*), Bash(curl:*), Bash(export:*), Bash(find:*), Bash(ls:*), Bash(cat:*), Bash(echo:*), Skill(tdn:task-management) --- This session is being primed with context on the user's personal task management system: tasks, projects and life areas. Do this: 1. Load the `task-management` skill now. -2. Run `tdn config --ai && tdn context --ai` (so output -> your context) -3. Report only: "Got it... areas, active projects... 🚀" (where x & y are based on the output of (2)) +2. Check if `tdn` is available: run `which tdn` + - **If found** → skip to step 4. + - **If not found** → continue to step 3. +3. Set up tdn for this environment (likely Claude Cowork). See [cowork.md](../skills/task-management/cowork.md) for full details. In short: + a. Install: `curl -fsSL https://github.com/taskdn/taskdn/releases/latest/download/install.sh | bash && export PATH="$PATH:$HOME/.local/bin"` + b. If install fails, search mounted dirs for a `tdn` binary: `find /sessions/*/mnt/ /mnt/ -name 'tdn' -o -name 'tdn-linux-arm64' 2>/dev/null` + c. Discover vault directories in mounted paths (look for `tasks`, `projects`, `areas` folders) + d. Create a `.taskdn.json` in the current directory with the discovered paths + e. Verify with `tdn config --ai` + f. If none of this works, tell the user and fall back to direct file access using the skill's specification and templates docs. +4. Run `tdn config --ai && tdn context --ai` (so output → your context) +5. Report only: "Got it... areas, active projects... 🚀" (where x & y are based on the output of step 4) diff --git a/tdn-claude-plugin/skills/task-management/SKILL.md b/tdn-claude-plugin/skills/task-management/SKILL.md index 231e81d6..a0a71dca 100644 --- a/tdn-claude-plugin/skills/task-management/SKILL.md +++ b/tdn-claude-plugin/skills/task-management/SKILL.md @@ -202,6 +202,7 @@ If a tdn command fails: ## Detailed Documentation - [command-reference.md](command-reference.md) — Complete command documentation +- [cowork.md](cowork.md) — Setup and usage in Claude Cowork (sandboxed VM) - [decision-guide.md](decision-guide.md) — When to use what approach - [examples.md](examples.md) — Common workflow examples - [obsidian.md](obsidian.md) — Obsidian-specific guidance (if vault is in Obsidian) diff --git a/tdn-claude-plugin/skills/task-management/cowork.md b/tdn-claude-plugin/skills/task-management/cowork.md new file mode 100644 index 00000000..41b7a222 --- /dev/null +++ b/tdn-claude-plugin/skills/task-management/cowork.md @@ -0,0 +1,96 @@ +# Cowork Environment Guide + +This document covers using tdn inside **Claude Cowork** — Anthropic's sandboxed Linux VM environment for Claude Desktop. + +--- + +## How Cowork Differs from Claude Code + +| Aspect | Claude Code | Cowork | +|--------|-------------|--------| +| `tdn` binary | Globally installed | Not installed — must be set up | +| Config file | `~/.taskdn.json` | None — must be created locally | +| Vault paths | User's home directory | Mounted paths (e.g. `/sessions/xxx/mnt/tasks`) | +| Platform | macOS/Linux/Windows | Linux ARM64 (always) | +| Internet | Always available | Usually available | + +--- + +## Setup Flow + +When you detect you're in a Cowork environment (no `tdn` in PATH, Linux platform), follow these steps: + +### Step 1: Install the tdn Binary + +**Primary method — download from GitHub Releases:** + +```bash +curl -fsSL https://github.com/taskdn/taskdn/releases/latest/download/install.sh | bash +export PATH="$PATH:$HOME/.local/bin" +``` + +**Fallback — if download fails (no internet, etc.):** + +Search mounted directories for a pre-placed binary: + +```bash +# Look for a tdn binary the user may have included in their mounted folders +find /sessions/*/mnt/ -name 'tdn' -o -name 'tdn-linux-arm64' 2>/dev/null +``` + +If found, use it directly by its full path. + +If neither method works, fall back to direct file access mode (see "Degraded Mode" below). + +### Step 2: Discover Mounted Vault Directories + +The user must have shared/mounted their tasks, projects, and areas folders. Find them: + +```bash +# List all mounted directories to identify vault paths +ls /sessions/*/mnt/ 2>/dev/null || ls /mnt/ 2>/dev/null +``` + +Look for directories named `tasks`, `projects`, and `areas` (or similar). If unsure, ask the user which mounted directories correspond to their vault. + +### Step 3: Create Local Configuration + +Create a `.taskdn.json` in the current working directory with the discovered paths: + +```json +{ + "tasksDir": "/sessions/xxx/mnt/tasks", + "projectsDir": "/sessions/xxx/mnt/projects", + "areasDir": "/sessions/xxx/mnt/areas" +} +``` + +Replace the paths with the actual mounted paths from Step 2. + +### Step 4: Verify + +```bash +tdn config --ai +``` + +This should show the resolved paths pointing to the mounted directories. If it shows default paths instead, the local config wasn't picked up — check the working directory. + +--- + +## Degraded Mode (No Binary) + +If `tdn` can't be installed or found, you can still work with the vault using direct file access: + +- **Read tasks:** Use `Read` and `Glob` tools to read markdown files from the mounted vault directories +- **Search:** Use `Grep` to search across task files +- **Create/edit:** Use `Write` and `Edit` tools, following the templates in [templates.md](templates.md) and the spec in [specification.md](specification.md) + +This loses CLI benefits (validation, querying, status management), but is functional for basic task management. + +--- + +## Important Notes + +- **Setup runs each session.** Cowork sessions don't persist installed binaries or config files. The setup flow runs once at the start of each conversation. +- **Warnings are expected.** The CLI warns when vault paths are "outside your home directory" — this is normal in Cowork where paths look like `/sessions/xxx/mnt/tasks`. Ignore these warnings. +- **Ask about paths.** If you can't find the vault directories automatically, ask the user which folders they shared and what they contain. diff --git a/tdn-cli/src/config/index.ts b/tdn-cli/src/config/index.ts index 235304da..729c2baf 100644 --- a/tdn-cli/src/config/index.ts +++ b/tdn-cli/src/config/index.ts @@ -68,10 +68,11 @@ export function validateVaultPath(path: string, pathType: string = 'vault path') } // Warn if outside home directory (informational, not blocking) - // Exceptions: temp directories on macOS (/var/folders) and Linux (/tmp) + // Exceptions: temp directories, and sandboxed environments (e.g. Cowork VM mount paths) const home = homedir(); const isTempDir = absolutePath.startsWith('/var/folders/') || absolutePath.startsWith('/tmp/'); - if (!absolutePath.startsWith(home) && !isTempDir) { + const isSandboxedMount = absolutePath.startsWith('/sessions/') || absolutePath.startsWith('/mnt/'); + if (!absolutePath.startsWith(home) && !isTempDir && !isSandboxedMount) { console.warn( `Warning: ${pathType} is outside your home directory: ${absolutePath}\n` + `This may cause permission issues or affect system files.` diff --git a/tdn-cli/tests/unit/config-security.test.ts b/tdn-cli/tests/unit/config-security.test.ts index c0a4b157..a3ea05b3 100644 --- a/tdn-cli/tests/unit/config-security.test.ts +++ b/tdn-cli/tests/unit/config-security.test.ts @@ -144,6 +144,18 @@ describe('config security', () => { expect(warnCalls.length).toBeGreaterThan(0); expect(warnCalls[0]).toContain('outside your home directory'); }); + + test('accepts /sessions/ paths without warning (Cowork VM mount)', () => { + const result = validateVaultPath('/sessions/abc123/mnt/tasks', 'tasksDir'); + expect(result).toBe('/sessions/abc123/mnt/tasks'); + expect(warnCalls).toHaveLength(0); + }); + + test('accepts /mnt/ paths without warning (generic mount point)', () => { + const result = validateVaultPath('/mnt/shared/tasks', 'tasksDir'); + expect(result).toBe('/mnt/shared/tasks'); + expect(warnCalls).toHaveLength(0); + }); }); test('resolves relative paths to absolute', () => { From 01cdc510283ae989669fd1086604a47109c1fa10 Mon Sep 17 00:00:00 2001 From: Danny Smith Date: Sun, 15 Mar 2026 01:20:36 +0000 Subject: [PATCH 2/5] Fix flaky home directory test in config-security Use homedir() + join() instead of literal '~/tasks' which doesn't expand the tilde via path.resolve(), causing false warnings when cwd is outside $HOME. Co-Authored-By: Claude Opus 4.6 (1M context) --- tdn-cli/tests/unit/config-security.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tdn-cli/tests/unit/config-security.test.ts b/tdn-cli/tests/unit/config-security.test.ts index a3ea05b3..484aa5b8 100644 --- a/tdn-cli/tests/unit/config-security.test.ts +++ b/tdn-cli/tests/unit/config-security.test.ts @@ -22,8 +22,8 @@ describe('config security', () => { }); test('accepts paths in user home directory', () => { - // Use a path that's definitely in the home directory - const result = validateVaultPath('~/tasks', 'tasksDir'); + const home = homedir(); + const result = validateVaultPath(join(home, 'tasks'), 'tasksDir'); expect(result).toContain('tasks'); expect(warnCalls).toHaveLength(0); }); From 6a4f333ba22aefef4b9fdd5ac2c1a6db9381aa21 Mon Sep 17 00:00:00 2001 From: Danny Smith Date: Sun, 15 Mar 2026 01:47:45 +0000 Subject: [PATCH 3/5] Add node_modules to root .gitignore Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 23f8217c..012d0fd4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .local *.local.* .DS_Store +node_modules/ dummy-demo-vault/ .idea .vscode From 42ef8c8beea1b76b4e76f27d935efe4d701c489c Mon Sep 17 00:00:00 2001 From: Danny Smith Date: Sun, 15 Mar 2026 02:05:49 +0000 Subject: [PATCH 4/5] Fix home directory check to use proper path boundary Use path.sep to prevent false matches where /home/alice2 would incorrectly be treated as inside /home/alice. Also fix formatting to satisfy Prettier. Co-Authored-By: Claude Opus 4.6 (1M context) --- tdn-cli/src/config/index.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tdn-cli/src/config/index.ts b/tdn-cli/src/config/index.ts index 729c2baf..70d0ea89 100644 --- a/tdn-cli/src/config/index.ts +++ b/tdn-cli/src/config/index.ts @@ -1,4 +1,4 @@ -import { resolve } from 'path'; +import { resolve, sep } from 'path'; import { existsSync, readFileSync } from 'fs'; import { homedir, platform } from 'os'; @@ -71,8 +71,10 @@ export function validateVaultPath(path: string, pathType: string = 'vault path') // Exceptions: temp directories, and sandboxed environments (e.g. Cowork VM mount paths) const home = homedir(); const isTempDir = absolutePath.startsWith('/var/folders/') || absolutePath.startsWith('/tmp/'); - const isSandboxedMount = absolutePath.startsWith('/sessions/') || absolutePath.startsWith('/mnt/'); - if (!absolutePath.startsWith(home) && !isTempDir && !isSandboxedMount) { + const isSandboxedMount = + absolutePath.startsWith('/sessions/') || absolutePath.startsWith('/mnt/'); + const isInsideHome = absolutePath === home || absolutePath.startsWith(home + sep); + if (!isInsideHome && !isTempDir && !isSandboxedMount) { console.warn( `Warning: ${pathType} is outside your home directory: ${absolutePath}\n` + `This may cause permission issues or affect system files.` From 1c1abf52ec1fb707461050c73e703aa1bf02ac9e Mon Sep 17 00:00:00 2001 From: Danny Smith Date: Sun, 22 Mar 2026 02:48:04 +0000 Subject: [PATCH 5/5] Bump tdn-claude-plugin to v0.1.1 Co-Authored-By: Claude Opus 4.6 (1M context) --- tdn-claude-plugin/.claude-plugin/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tdn-claude-plugin/.claude-plugin/plugin.json b/tdn-claude-plugin/.claude-plugin/plugin.json index fd600d76..abda6d59 100644 --- a/tdn-claude-plugin/.claude-plugin/plugin.json +++ b/tdn-claude-plugin/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "tdn", - "version": "0.1.0", + "version": "0.1.1", "description": "Task and project management with the tdn CLI. Helps Claude work as a productivity assistant, managing tasks, projects, and areas stored as markdown files on disk.", "author": { "name": "Danny Smith"