Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.local
*.local.*
.DS_Store
node_modules/
dummy-demo-vault/
.idea
.vscode
Expand Down
214 changes: 95 additions & 119 deletions docs/tasks-todo/task-x-claude-cowork-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <install-url> | 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)
Expand All @@ -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).
34 changes: 34 additions & 0 deletions tdn-claude-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,52 @@ 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
│ └── templates.md
└── 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.
Expand Down
16 changes: 13 additions & 3 deletions tdn-claude-plugin/commands/prime.md
Original file line number Diff line number Diff line change
@@ -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... <x> areas, <y> 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... <x> areas, <y> active projects... 🚀" (where x & y are based on the output of step 4)
1 change: 1 addition & 0 deletions tdn-claude-plugin/skills/task-management/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading
Loading