docs: add v0.2 spec

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-06 10:05:27 -04:00
parent 69c487cf79
commit f967064331
5 changed files with 3603 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
{
"permissions": {
"allow": [
"Bash(go version:*)",
"Bash(cmd.exe:*)",
"Bash(export PATH=\"$PATH:/c/Program Files/Go/bin:/c/Users/Warren/go/bin\")",
"Read(//c/Program Files/Go/**)",
"Read(//c/Users/Warren/go/**)",
"Bash(rustc --version)",
"Bash(powershell.exe:*)",
"Bash(export PATH=\"$PATH:/c/Program Files/Go/bin\")",
"Bash(go mod:*)",
"Bash(go test:*)",
"Bash(go get:*)",
"Bash(go build:*)",
"Bash(./ctask.exe --version)",
"Bash(./ctask.exe --help)",
"Bash(git init:*)",
"Bash(git add:*)",
"Bash(git commit -m ':*)",
"Bash(./ctask.exe new:*)",
"Bash(./ctask.exe list:*)",
"Bash(./ctask.exe resume:*)",
"Bash(./ctask.exe open:*)",
"Bash(./ctask.exe info:*)",
"Read(//tmp/**)",
"Bash(export CTASK_ROOT)",
"Bash(./ctask.exe archive:*)",
"Bash(echo \"exit: $?\")",
"Bash(CTASK_ROOT=$\\(ls -d /tmp/tmp.SbUlBO0N9l\\) ./ctask.exe resume --agent \"nonexistent_agent_12345\" task-183813)",
"Bash(CTASK_ROOT=$\\(ls -d /tmp/tmp.SbUlBO0N9l\\) ./ctask.exe resume --agent \"bad_agent\" task-183813)",
"Bash(go env:*)",
"Bash(go install:*)",
"Bash(mkdir -p /c/Users/Warren/go/bin)",
"Bash(cp /c/Users/Warren/claude_tasks/ctask_v0.1/scripts/ctask-statusline.ps1 /c/Users/Warren/go/bin/ctask-statusline.ps1)",
"Bash(cp /c/Users/Warren/claude_tasks/ctask_v0.1/scripts/ctask-statusline.sh /c/Users/Warren/go/bin/ctask-statusline.sh)",
"Bash(ls -la /c/Users/Warren/go/bin/ctask-statusline.*)",
"Bash(export CTASK_TASK=\"manual-test\")",
"Bash(export CTASK_MODE=\"local\")",
"Bash(export CTASK_WORKSPACE=\"C:\\\\\\\\Users\\\\\\\\Warren\\\\\\\\ai-workspaces\\\\\\\\general\\\\\\\\2026-04-05_manual-test\")",
"Bash(unset CTASK_TASK CTASK_MODE CTASK_WORKSPACE)",
"Skill(update-config)",
"Bash(command -v powershell)",
"Bash(command -v powershell.exe)",
"Bash(pwsh -NoProfile -Command '$PSVersionTable.PSVersion')",
"Bash(export CTASK_TASK=\"manual-test-2\")",
"Bash(export CTASK_WORKSPACE=\"C:\\\\\\\\Users\\\\\\\\Warren\\\\\\\\ai-workspaces\\\\\\\\general\\\\\\\\2026-04-05_manual-test-2\")",
"Bash(bash -c 'C:\\\\WINDOWS\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe -NoProfile -File C:\\\\Users\\\\Warren\\\\go\\\\bin\\\\ctask-statusline.ps1')",
"Bash(bash -c 'powershell -NoProfile -File C:\\\\Users\\\\Warren\\\\go\\\\bin\\\\ctask-statusline.ps1')",
"Bash(bash -c 'powershell -NoProfile -File /c/Users/Warren/go/bin/ctask-statusline.ps1')",
"Bash(CTASK_TASK=\"manual-test-2\" CTASK_MODE=\"local\" CTASK_WORKSPACE=\"C:\\\\\\\\Users\\\\\\\\Warren\\\\\\\\ai-workspaces\\\\\\\\general\\\\\\\\2026-04-05_manual-test-2\" bash /c/Users/Warren/go/bin/ctask-statusline.sh)",
"Bash(bash /c/Users/Warren/go/bin/ctask-statusline.sh)",
"Bash(ls /c/Users/Warren/claude_tasks/ctask_v0.1/*v0.2* /c/Users/Warren/claude_tasks/ctask_v0.1/*spec*)",
"Bash(./ctask.exe doctor:*)",
"Bash(./ctask.exe last:*)",
"Bash(./ctask.exe delete:*)",
"Bash(export PATH=\"$PATH:/c/Users/Warren/go/bin\")",
"Bash(mktemp -d)",
"Bash(export CTASK_ROOT=$\\(mktemp -d\\))",
"Bash(ctask --version)",
"Bash(ctask --help)",
"Bash(ctask new:*)",
"Bash(ctask list:*)",
"Bash(ctask info:*)",
"Bash(ctask archive:*)",
"Bash(ctask resume:*)",
"Bash(echo \"missing arg exit: $?\")",
"Bash(ctask last:*)",
"Bash(ctask doctor:*)",
"Bash(ctask delete:*)"
]
}
}
+404
View File
@@ -0,0 +1,404 @@
# ctask CLI Specification (v0.1)
## Global Options
```
ctask [command] [options] [arguments]
ctask -h | --help
ctask --version
```
## Commands
---
### `ctask new [title]`
Create a new task workspace and launch the agent.
```
ctask new [title] [options]
```
**Arguments:**
- `title` — Human-readable task name (optional). If omitted, generates `task-HHMMSS`.
**Options:**
| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--category` | `-c` | `general` | Workspace category subdirectory |
| `--container` | | off | Launch in container sandbox (v0.2 — prints notice in v0.1) |
| `--shell` | | off | Open interactive shell instead of agent |
| `--agent` | `-a` | `claude` | Command to exec as the agent |
| `--no-launch` | | off | Create workspace only, do not launch |
**Behavior:**
- `new` always creates a fresh workspace. If a workspace with the same date+slug exists, append `-2`, `-3`, etc.
- Slugs are derived from the title: lowercase, non-alphanumeric replaced with hyphens, trimmed
- Workspace created at `$CTASK_ROOT/<category>/<YYYY-MM-DD>_<slug>/`
- Seed files written only if they do not already exist
**Examples:**
```bash
# Basic — creates workspace, launches claude
ctask new "arch notes"
# With category
ctask new -c scripts "backup helper"
# Container mode
ctask new --container -c risky "unknown installer"
# Shell instead of agent
ctask new --shell "test env"
# Create workspace but don't launch anything
ctask new --no-launch "json cleanup"
# Use aider instead of claude
ctask new --agent aider "refactor api"
# Auto-generated name
ctask new
```
**Output:**
```
[ctask] created general/2026-04-05_arch-notes
[ctask] local :: arch-notes
[ctask] ~/ai-workspaces/general/2026-04-05_arch-notes
```
---
### `ctask list`
Show recent workspaces in reverse-chronological order.
```
ctask list [options]
```
**Options:**
| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--all` | `-a` | off | Include archived workspaces |
| `--category` | `-c` | all | Filter by category |
| `--limit` | `-n` | 20 | Maximum entries to show |
**Output format:**
```
active local general 2026-04-05 arch-notes
active container risky 2026-04-04 unknown-installer
active local scripts 2026-04-03 backup-helper
```
Columns: status, mode, category, date, slug.
**Examples:**
```bash
# Recent workspaces
ctask list
# Only scripts category
ctask list -c scripts
# Include archived
ctask list --all
# Last 5
ctask list -n 5
```
---
### `ctask resume <query>`
Reopen an existing workspace and launch the agent.
```
ctask resume <query> [options]
```
**Arguments:**
- `query` — Workspace slug, partial name, or full directory name (required)
**Options:**
| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--container` | | off | Resume in container mode (v0.2 — prints notice in v0.1) |
| `--shell` | | off | Open shell instead of agent |
| `--agent` | `-a` | from task.yaml | Override agent command |
**Resolution:**
1. Exact directory name match under `$CTASK_ROOT/*/*` → use it
2. Exact slug match (portion after date prefix) → use it
3. Case-insensitive substring match against slug → use if unique
4. Multiple matches → print all matches and exit 1
5. No matches → error and exit 1
Archived workspaces are excluded from matching by default.
**Behavior:**
- Updates `updated_at` in `task.yaml`
- Sets environment variables
- Prints launch banner
- Execs agent or shell
**Examples:**
```bash
# Resume by slug
ctask resume arch-notes
# Resume by partial match
ctask resume backup
# Resume by full directory name
ctask resume 2026-04-05_arch-notes
# Resume in container mode (even if originally local)
ctask resume --container arch-notes
# Resume with shell
ctask resume --shell arch-notes
```
**On multiple matches:**
```
Multiple workspaces match "notes":
general/2026-04-05_arch-notes
research/2026-04-03_migration-notes
Specify a more precise query.
```
---
### `ctask open <query>`
Open a workspace directory without launching the agent.
```
ctask open <query> [options]
```
**Options:**
| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--all` | `-a` | off | Include archived workspaces in query resolution |
**Behavior:**
- Resolves workspace (same rules as `resume`)
- Updates `updated_at`
- Sets environment variables
- Spawns a new interactive subshell in the workspace directory with ctask prompt prefix
- Does NOT launch the agent
- Does NOT mutate the caller's existing shell session — this is a subshell, not a `cd`
This is equivalent to `ctask resume --shell <query>` but reads more naturally for "I just want to look at the files."
**Examples:**
```bash
# Open workspace in shell
ctask open arch-notes
```
---
### `ctask info <query>`
Display metadata and path for a workspace without entering it.
```
ctask info <query> [options]
```
**Options:**
| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--all` | `-a` | off | Include archived workspaces in query resolution |
**Output:**
```
Task: arch-notes
Title: arch notes
Category: general
Status: active
Mode: local
Agent: claude
Created: 2026-04-05 14:30:22
Updated: 2026-04-05 15:12:00
Path: ~/ai-workspaces/general/2026-04-05_arch-notes
Contents:
task.yaml
CLAUDE.md
notes.md
context/
output/
logs/
```
**Examples:**
```bash
ctask info arch-notes
ctask info backup
```
---
### `ctask archive <query>`
Mark a workspace as archived.
```
ctask archive <query>
```
**Behavior:**
- Resolves workspace (same rules as `resume`)
- Sets `status: archived` and `archived_at` timestamp in `task.yaml`
- Workspace stays in place (not moved or deleted)
- Archived workspaces are hidden from `ctask list` unless `--all` is passed
**Examples:**
```bash
ctask archive arch-notes
ctask archive 2026-04-03_backup-helper
```
**Output:**
```
[ctask] archived: general/2026-04-05_arch-notes
```
---
## Environment Variables
### Set by ctask (exported into every child session)
| Variable | Example | Description |
|----------|---------|-------------|
| `CTASK_TASK` | `arch-notes` | Task slug |
| `CTASK_MODE` | `local` | Execution mode |
| `CTASK_ROOT` | `/home/warren/ai-workspaces` | Resolved workspace root (absolute path) |
| `CTASK_WORKSPACE` | `/home/warren/ai-workspaces/general/2026-04-05_arch-notes` | Full workspace path |
| `CTASK_CATEGORY` | `general` | Category |
### Read by ctask (user-configurable input)
| Variable | Default | Description |
|----------|---------|-------------|
| `CTASK_ROOT` | `~/ai-workspaces` (Unix) or `%USERPROFILE%\ai-workspaces` (Windows) | Workspace root directory |
| `CTASK_AGENT` | `claude` | Default agent command |
**Implementation note on `CTASK_ROOT`:** ctask reads the caller's `CTASK_ROOT` as config input (may contain `~` or relative path), resolves it to an absolute path, then exports the resolved value into the child process environment. The child session always sees a fully resolved absolute path.
---
## Exit Codes
| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | General error (multiple matches, not found, invalid args) |
| 2 | Missing required argument |
| 127 | Agent command not found |
---
## Shell Prompt Behavior
### In `--shell` mode
Ephemeral `PS1` prefix, no permanent config changes:
```
(ctask:arch-notes|local) warren@host:~/ai-workspaces/general/2026-04-05_arch-notes$
```
### In agent mode
Banner printed before exec:
```
[ctask] local :: arch-notes
[ctask] ~/ai-workspaces/general/2026-04-05_arch-notes
```
---
## Container Mode (Deferred to v0.2)
The `--container` flag is accepted but prints a notice that container mode is not yet available in v0.1. This keeps the CLI interface stable so users and scripts don't need to change when container support lands.
```
[ctask] container mode is not available in v0.1. Use local mode or see docs for manual container setup.
```
Design intent for v0.2: persistent named container, Podman-first (Docker fallback), Claude Code only inside container. See MVP contract for details.
---
## Status Line Integration
### Claude Code status line
ctask ships a small helper script for Claude Code's status line feature. When ctask environment variables are set, it renders session context at the bottom of the Claude Code UI.
**Setup** (add to `~/.claude/settings.json`):
```json
{
"statusLine": {
"type": "command",
"command": "bash /path/to/ctask-statusline.sh"
}
}
```
On Windows, use the PowerShell variant:
```json
{
"statusLine": {
"type": "command",
"command": "powershell -NoProfile -File C:\\path\\to\\ctask-statusline.ps1"
}
}
```
**Output when in a ctask session:**
```
(ctask:arch-notes|local) ~/ai-workspaces/general/2026-04-05_arch-notes
```
**Output when NOT in a ctask session:** empty (no output, falls through gracefully).
### Fallback for non-Claude agents
The ephemeral shell prompt prefix (`PS1` on Unix, `PROMPT` on Windows) in `--shell` mode provides session context for any tool that doesn't support a dedicated status line.
File diff suppressed because it is too large Load Diff
+201
View File
@@ -0,0 +1,201 @@
# ctask — MVP Contract (v0.1)
## 1. Purpose
ctask is a local CLI that creates and manages named AI-agent task workspaces so developers can start, resume, and organize work more safely and predictably. It provides dedicated task directories with consistent structure, visible session identity, environment context injection, and optional container isolation. It is agent-agnostic — the default agent is Claude Code, but any command-line agent or shell can be launched.
## 2. Must-Have Commands
| Command | Description |
|---------|-------------|
| `ctask new [title]` | Create a new task workspace and launch the agent in it |
| `ctask list` | Show recent workspaces, reverse-chronological |
| `ctask resume <query>` | Reopen an existing workspace by name/slug match |
| `ctask open <query>` | Open a workspace directory without launching the agent |
| `ctask info <query>` | Display metadata and path for a workspace |
| `ctask archive <query>` | Mark a workspace as archived (status flag, workspace stays in place) |
### Flags (apply across commands where relevant)
| Flag | Description |
|------|-------------|
| `-c, --category <name>` | Workspace category (default: `general`) |
| `--container` | Request container mode (deferred to v0.2 — prints notice in v0.1) |
| `--shell` | Open an interactive shell instead of the agent |
| `--agent <command>` | Override the default agent command |
| `-h, --help` | Show help |
### Resolution rules for `<query>`
1. Exact directory name match under `<root>/*/*` → use it
2. Exact slug match (portion after date prefix) → use it
3. Case-insensitive substring match against slug → use if unique
4. Multiple matches → print all and exit non-zero
5. No matches → error
Archived workspaces are excluded from matching unless `--all` is passed (where supported).
## 3. Workspace Layout
Every task workspace contains:
```
~/ai-workspaces/<category>/<YYYY-MM-DD>_<slug>/
├── task.yaml # Task metadata (machine-managed)
├── CLAUDE.md # Advisory workspace scope guidelines (not security enforcement)
├── notes.md # Freeform task log (human/agent-managed)
├── context/ # Additional reference docs (user-managed, not seeded)
├── output/ # Task deliverables and artifacts
└── logs/ # Session logs (future use, empty in v0.1)
```
### Seed files
On `ctask new`:
- `task.yaml` — populated with initial metadata (see §4)
- `notes.md` — skeleton with Purpose / Constraints / Actions / Results headings
- `CLAUDE.md` — advisory workspace scope guidelines (placed in root so Claude Code finds it automatically)
Seed files are only created if they do not already exist (safe for resume/reopen).
### Workspace root
Default: `~/ai-workspaces`
Override via: `CTASK_ROOT` environment variable
### Categories
Predefined suggestions: `general`, `scripts`, `research`, `risky`
Any string is accepted. Categories are just subdirectories — no registry.
## 4. Task Metadata
`task.yaml` contains only:
```yaml
id: "20260405-143022" # YYYYMMDD-HHMMSS, unique enough
slug: "arch-notes"
title: "arch notes"
created_at: "2026-04-05T14:30:22Z"
updated_at: "2026-04-05T15:12:00Z"
status: "active" # active | archived
category: "general"
mode: "local" # local | container
agent: "claude" # command used to launch
workspace_path: "/home/warren/ai-workspaces/general/20260405_arch-notes"
archived_at: null # set by ctask archive, null while active
```
`updated_at` is refreshed on every `resume` or `open`.
No additional fields in v0.1. Schema grows only when a real need appears.
## 5. Launch Behavior
### On `ctask new`
1. Compute slug from title (lowercase, alphanumeric + hyphens)
2. If workspace with same date+slug already exists, append `-2`, `-3`, etc.
3. Create workspace directory under `<root>/<category>/<date>_<slug>`
4. Write seed files (`task.yaml`, `notes.md`, `CLAUDE.md`)
5. Export environment variables (see below)
6. Print launch banner
7. `cd` into workspace and exec the agent (or shell if `--shell`)
### On `ctask resume`
1. Resolve workspace by query (see §2 resolution rules)
2. Update `updated_at` in `task.yaml`
3. Export environment variables
4. Print launch banner
5. `cd` into workspace and exec the agent (or shell)
### Environment variables (set for every session)
| Variable | Value |
|----------|-------|
| `CTASK_TASK` | Slug (e.g., `arch-notes`) |
| `CTASK_MODE` | `local` or `container` |
| `CTASK_ROOT` | Workspace root path |
| `CTASK_WORKSPACE` | Full path to current workspace |
| `CTASK_CATEGORY` | Category name |
These are available to the agent, status line scripts, and shell prompts.
### Launch banner (printed before exec)
```
[ctask] local :: arch-notes
[ctask] ~/ai-workspaces/general/2026-04-05_arch-notes
```
### Shell prompt prefix (for `--shell` mode only)
```
(ctask:arch-notes|local) warren@host:~$
```
Set via ephemeral `PS1` override. No permanent shell config changes.
### Container mode (v0.2 — deferred from initial release)
Container mode uses a persistent named container (`ctask-sandbox`). It is deferred from the initial v0.1 release to keep scope focused on the workspace lifecycle, which is the core value. The `--container` flag will be accepted but will print a message that container mode is not yet available.
Design intent for v0.2: Linux-only, Podman-first (Docker fallback), Claude Code only inside the container. Mount `$CTASK_ROOT` at `/workspaces`. No other host directories mounted. Agent auth done once manually after first container creation.
## 6. Explicit Non-Goals for v0.1
- **No plugin system.** Agent is a command string, not an interface.
- **No elevated helper / privilege adapter.** Sudo policy is separate from ctask.
- **No task templates.** Every workspace gets the same seed files.
- **No built-in session logging.** `logs/` directory exists but ctask does not populate it.
- **No agent abstraction layer.** Swap agents via `--agent <cmd>` flag, not adapters.
- **No container orchestration.** Container mode is one persistent sandbox, not per-task containers.
- **No GUI, no TUI beyond the CLI.**
- **No cloud sync, no remote sharing.**
## 7. Platform Target
Cross-platform from the start: Windows, Linux, macOS. Primary development and testing on Windows.
Go's standard library handles the main platform differences (path separators via `filepath`, environment via `os`). The only platform-specific concerns are:
- **Shell spawning:** Use `cmd.exe` or PowerShell on Windows, user's `$SHELL` or `bash` on Unix
- **Default workspace root:** `%USERPROFILE%\ai-workspaces` on Windows, `~/ai-workspaces` on Unix
- **Status line helper:** Provide both a bash script and a PowerShell script
Keep platform-specific code isolated behind small helper functions. Do not introduce build tags or platform abstraction layers unless a concrete need appears.
## 8. Status Line Support
The status line is an MVP deliverable, not a future enhancement. It provides persistent visible session context inside Claude Code's UI.
### Deliverables
- A small status line helper script (bash + PowerShell variants) that reads ctask environment variables and prints a formatted context string
- Brief setup instructions for wiring it into Claude Code's `statusLine` configuration in `~/.claude/settings.json`
- A note explaining the fallback approach for non-Claude agents (ephemeral shell prompt prefix)
### Output format
```
(ctask:arch-notes|local) ~/ai-workspaces/general/2026-04-05_arch-notes
```
When `CTASK_TASK` is not set (normal non-ctask Claude session), the script should output nothing or fall through to other status line content.
### Source of truth
The script reads only from environment variables — no file parsing, no subprocess calls:
- `CTASK_TASK` — task slug
- `CTASK_MODE` — execution mode
- `CTASK_WORKSPACE` — full workspace path
- `CTASK_CATEGORY` — category (optional, include if concise)
### Fallback for non-Claude agents
For `open` and `resume --shell`, the ephemeral `PS1` / `PROMPT` prefix remains the generic fallback for tools that do not support a dedicated status line hook.
+302
View File
@@ -0,0 +1,302 @@
# ctask v0.2 Feature Spec — Session Traceability & Resumability
## Theme
v0.1 = create and resume workspaces
v0.2 = understand and continue workspaces later
## Scope
Five deliverables:
1. Automatic session snapshot logging
2. Improved seeded CLAUDE.md with handoff instructions
3. `ctask doctor`
4. `ctask last`
5. `ctask delete`
## 1. Automatic Session Snapshot Logging
### Purpose
When a developer returns to a workspace after hours or days, they need to immediately understand what happened last time — without relying on memory or manual note-taking.
### How it works
ctask wraps the agent/shell launch so it can run logic before and after the session.
**On session start:**
1. Create `.ctask/` directory in workspace if it doesn't exist
2. Capture a file manifest: relative path, size in bytes, and modification timestamp for every file in the workspace (excluding `.ctask/` itself)
3. Write manifest to `.ctask/manifest-start.json`
4. Append a session-start entry to `logs/sessions.log`
**On session end (agent/shell process exits):**
1. Capture a second manifest using the same format
2. Diff against the start manifest to produce: files added, files modified (size or mtime changed), files deleted
3. Append a session-end entry to `logs/sessions.log` with the diff summary
4. Clean up `.ctask/manifest-start.json` (or keep for debugging — implementer's choice)
5. Exit with the child process's exit code
### Implementation change
v0.1 uses `exec` to replace the ctask process with the agent. v0.2 must change this to spawn a child process and wait for it, so ctask can run post-session logic. This applies to `new`, `resume`, and `open`.
Session snapshot logging runs for any command that launches an agent or shell session:
- `ctask new` (when it launches into agent or shell)
- `ctask resume`
- `ctask open`
- `ctask last` (delegates to `resume`)
Session snapshot logging does **not** run for:
- `ctask new --no-launch` (no session to capture)
- `ctask list`, `ctask info`, `ctask archive`, `ctask doctor`, `ctask delete`
On Unix: run the agent as a child process with stdin/stdout/stderr inherited, wait for exit.
On Windows: same pattern using `os/exec` with `Cmd.Run()`.
Do not use `exec` (process replacement) in v0.2.
### Session log format
`logs/sessions.log` is a human-readable, append-only text file.
```
── Session 2026-04-05 14:30:22 ──
Agent: claude
Mode: local
Start: 2026-04-05 14:30:22
End: 2026-04-05 15:45:10
Duration: 1h 14m 48s
Added:
output/migration-plan.md
output/schema.sql
context/reference.md
Modified:
notes.md
CLAUDE.md
Deleted:
(none)
Notes updated: yes
────────────────────────────────
```
### Rules
- The manifest captures only regular files, not directories
- Ignore `.ctask/` contents when diffing
- Ignore `task.yaml` changes (ctask updates this itself, not the agent)
- Ignore `logs/sessions.log` changes (ctask's own logging would otherwise show as a modification every session)
- "Modified" means: file present in both start and end manifests with a different size or mtime. This is a lightweight heuristic, not content hashing.
- If the session is very short (< 5 seconds) and no files changed, still log it but with a note like "No changes detected"
- If manifest capture fails for any reason, log the error and continue — never block the user from exiting
- "Notes updated" is a simple boolean: did `notes.md` change between start and end?
- `.ctask/manifest-start.json` is deleted after successful session-end logging. If post-session logging fails, keep it and log the error.
### Manifest format
`.ctask/manifest-start.json`:
```json
{
"captured_at": "2026-04-05T14:30:22Z",
"files": [
{"path": "notes.md", "size": 245, "mtime": "2026-04-05T14:30:20Z"},
{"path": "CLAUDE.md", "size": 512, "mtime": "2026-04-05T14:30:20Z"},
{"path": "task.yaml", "size": 310, "mtime": "2026-04-05T14:30:22Z"}
]
}
```
## 2. Improved Seeded CLAUDE.md
### Purpose
Nudge the agent to leave a human-readable handoff in `notes.md` so the developer (or a future agent session) can understand what was accomplished and what remains.
### Change
Update the seeded `CLAUDE.md` template to include the following instruction (in addition to existing workspace scope guidance):
```markdown
## Session Handoff
Before ending a session, append a brief summary to notes.md with:
- What was accomplished
- Key decisions made
- Open follow-ups or unfinished work
- How to continue from here
Keep it concise — a few bullet points is enough. This helps the developer (or a future session) resume without losing context.
```
### Rules
- This is advisory, not enforced. The agent may or may not follow it.
- The automatic session snapshot (§1) provides the structural safety net regardless.
- Do not add complex formatting requirements — the simpler the instruction, the more likely the agent complies.
## 3. `ctask doctor`
### Purpose
Verify that ctask is correctly set up and help users diagnose common configuration problems.
### Command
```
ctask doctor
```
No arguments, no flags.
### Checks
| Check | Pass condition | Fail message |
|-------|---------------|--------------|
| Workspace root exists | `CTASK_ROOT` directory exists and is writable | `Workspace root not found: <path>. Create it with: mkdir <path>` |
| Default agent on PATH | Configured agent command is found | `Agent command not found: <cmd>. Install it or set CTASK_AGENT.` |
| Status line helper exists | Status line script file exists at expected location | `Status line helper not found. Run ctask setup instructions at <doc link>.` |
| Claude Code status line configured | `~/.claude/settings.json` exists, contains a `statusLine` key with `type: "command"`, and the `command` value references a file that exists on disk | `Claude Code status line not configured or misconfigured. Add to ~/.claude/settings.json: <example>` |
| Workspace root has workspaces | At least one workspace directory exists | `No workspaces found. Create one with: ctask new "my first task"` |
### Output format
```
ctask doctor
✓ Workspace root exists: ~/ai-workspaces
✓ Default agent found: claude
✗ Status line helper not found
→ Install it to: ~/.local/bin/ctask-statusline.sh
✓ Claude Code status line configured
✓ Workspaces found: 12 tasks (3 archived)
3 checks passed, 1 failed
```
Use ✓ and ✗ (or platform-safe equivalents if Unicode is unreliable on Windows cmd.exe). Provide actionable fix instructions for every failure.
### Rules
- doctor never modifies anything — read-only
- doctor should work even if ctask has never been used (no workspaces yet)
- exit 0 if all checks pass, exit 1 if any fail
- check paths using platform-appropriate logic (Windows vs Unix)
## 4. `ctask last`
### Purpose
Instantly resume the most recently updated workspace without remembering its name.
### Command
```
ctask last [options]
```
### Options
| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--shell` | | off | Open shell instead of agent |
| `--agent` | `-a` | from task.yaml | Override agent command |
### Behavior
1. Scan all non-archived workspaces
2. Find the one with the most recent `updated_at` in `task.yaml`
3. Behave exactly like `ctask resume <that-workspace>`
If no workspaces exist, print an error and exit 1.
### Examples
```bash
# Resume most recent workspace
ctask last
# Open most recent workspace in shell
ctask last --shell
```
### Output
Same as `resume` — launch banner, then agent or shell.
## 5. `ctask delete`
### Purpose
Permanently remove a workspace directory when it's no longer needed.
### Command
```
ctask delete <query> [options]
```
### Options
| Flag | Short | Default | Description |
|------|-------|---------|-------------|
| `--force` | `-f` | off | Skip confirmation prompt |
| `--all` | `-a` | off | Include archived workspaces in query resolution |
### Behavior
1. Resolve workspace (same query rules as `resume`)
2. Print workspace path and contents summary (file count, total size)
3. Prompt for confirmation: `Delete <path>? This cannot be undone. [y/N]`
4. If confirmed (or `--force`), remove the entire workspace directory
5. Print confirmation message
### Output
```
ctask delete arch-notes
Workspace: ~/ai-workspaces/general/2026-04-05_arch-notes
Files: 8 (24 KB)
Delete this workspace? This cannot be undone. [y/N] y
[ctask] deleted: general/2026-04-05_arch-notes
```
### Rules
- Confirmation is required by default. `--force` skips it.
- Delete removes the entire directory tree, not just ctask metadata.
- Archived workspaces are excluded from query resolution unless `--all` is passed (consistent with other commands).
- If the workspace is the most recently updated one, print a note: "This was your most recent workspace."
- If `CTASK_WORKSPACE` is set and matches the resolved target (i.e., the user is inside an active ctask session targeting this workspace), refuse to delete and print: "Cannot delete the active workspace. Exit the session first." This check applies even with `--force`.
## Non-Goals for v0.2
- No terminal output recording or command history capture
- No automatic agent-generated summaries (the CLAUDE.md nudge is advisory only)
- No container mode (still deferred)
- No `ctask summarize` command (the automatic snapshot replaces the need)
- No manifest history / multiple snapshots per workspace (one start manifest is enough)
## Build Order
1. Change launch model from `exec` to child-process-and-wait (touches `new`, `resume`, `open`)
2. Manifest capture (start snapshot)
3. Session log writer (end snapshot + diff + append to `logs/sessions.log`)
4. Updated CLAUDE.md template
5. `ctask doctor`
6. `ctask last`
7. `ctask delete`
8. Testing and validation