# Commands ## ctask new Create a new task or project workspace and launch the agent. ``` ctask new [title] [flags] ``` If title is omitted, generates `task-HHMMSS`. **Flags:** | Flag | Short | Default | Description | |------|-------|---------|-------------| | `--category` | `-c` | `general` (task) / `projects` (project) | Workspace category subdirectory | | `--project` | | off | Create a long-lived project workspace (uses `CTASK_PROJECT_ROOT` if set, runs `git init`, project CLAUDE.md) | | `--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 | | `--container` | | off | Deferred to a future release | **Examples:** ```powershell ctask new "fix auth bug" ctask new -c scripts "backup helper" ctask new --no-launch "json cleanup" ctask new --shell "test env" ctask new --agent aider "refactor api" ctask new ctask new --project "billing service" ctask new --project -c backend "billing service" ``` When `--no-launch` is used, no session is started and no session log is written. ### Project mode (`--project`) `--project` is a thin variation on the normal task workflow for longer-lived work. It changes: - `task.yaml` records `type: project` - Default category becomes `projects` - Workspace root falls back to `CTASK_PROJECT_ROOT` if set; otherwise `CTASK_ROOT` - Built-in CLAUDE.md is the project-oriented template (overridable via seed directories) - Seed order: built-in defaults -> general seed (`CTASK_SEED_DIR`) -> project seed (`CTASK_SEED_PROJECT_DIR`) - `git init` runs if `git` is on PATH; a minimal `.gitignore` (`.ctask/` + `logs/sessions.log`) is created **only if no `.gitignore` was already provided by a seed** - If `git` is not available, ctask prints `[ctask] git not found; skipped repository initialization` and continues **Project root semantics:** - `CTASK_PROJECT_ROOT` not set: workspace goes under `$CTASK_ROOT/projects/_` (default category `projects` is appended) - `CTASK_PROJECT_ROOT` set, no `-c`: workspace goes directly under `$CTASK_PROJECT_ROOT/_` (no `projects/` subdirectory is appended) - `CTASK_PROJECT_ROOT` set, explicit `-c `: workspace goes under `$CTASK_PROJECT_ROOT//_` **Single git repo rule:** Project workspaces use a single git repository initialized at the workspace root. Do not create nested git repositories inside the workspace. If your project code lives in a subdirectory, it is tracked by the root repo. ### Seed directories On `ctask new`, after writing the built-in defaults, ctask copies the contents of an optional user seed directory into the workspace. Files in the seed directory overwrite the built-in defaults; subdirectories are preserved recursively. `task.yaml` and `.ctask/` at the seed root are always skipped. | Variable | Default (Unix) | Default (Windows) | |----------|---------------|-------------------| | `CTASK_SEED_DIR` | `~/.config/ctask/seed/` | `%APPDATA%\ctask\seed\` | | `CTASK_SEED_PROJECT_DIR` | `~/.config/ctask/seed-project/` | `%APPDATA%\ctask\seed-project\` | The general seed is applied to every workspace. The project seed is applied **only** when `--project` is set, on top of the general seed (project seed wins). Both directories are optional; missing directories are silently ignored. --- ## ctask list List workspaces in reverse-chronological order. ``` ctask list [flags] ``` By default, `ctask list` shows **all active workspaces** -- both tasks and projects. Use `--task` or `--projects` to narrow by type, and `--all` to include archived workspaces. **Flags:** | Flag | Short | Default | Description | |------|-------|---------|-------------| | `--all` | `-a` | off | Include archived workspaces | | `--task` | | off | Show task workspaces only | | `--projects` | | off | Show project workspaces only | | `--category` | `-c` | all | Filter by category | | `--limit` | `-n` | 20 | Maximum entries to show | `--task` and `--projects` are mutually exclusive; passing both returns a usage error. **Examples:** ```powershell ctask list # active tasks AND projects ctask list --all # everything (incl. archived) ctask list --task # active tasks only ctask list --task --all # all tasks (incl. archived) ctask list --projects # active projects only ctask list --projects --all # all projects (incl. archived) ctask list -c scripts -n 5 ``` Output columns: status, type, mode, category, date, slug. Workspaces created before v0.3 (which have no `type` field in `task.yaml`) are treated as tasks. --- ## ctask resume Reopen an existing workspace and launch the agent. ``` ctask resume [flags] ``` Resolves the workspace by query (exact directory name, exact slug, or case-insensitive substring). Archived workspaces are excluded by default. **Flags:** | Flag | Short | Default | Description | |------|-------|---------|-------------| | `--shell` | | off | Open shell instead of agent | | `--agent` | `-a` | from task.yaml | Override agent command | | `--force` | | off | Skip active-session and stale-workspace warnings | | `--container` | | off | Deferred to a future release | **Examples:** ```powershell ctask resume auth-bug ctask resume backup ctask resume --shell auth-bug ctask resume --agent aider auth-bug ctask resume --force auth-bug ``` If multiple workspaces match, prints all matches and exits. If none match, prints an error. Session logging runs automatically: file changes during the session are recorded in `logs/sessions.log`. --- ## ctask open Open a workspace directory in an interactive shell without launching the agent. ``` ctask open [flags] ``` Spawns a new subshell in the workspace directory. Does not modify the caller's shell session. **Flags:** | Flag | Short | Default | Description | |------|-------|---------|-------------| | `--all` | `-a` | off | Include archived workspaces in query resolution | | `--force` | | off | Skip active-session and stale-workspace warnings | **Examples:** ```powershell ctask open auth-bug ``` --- ## ctask info Display metadata and path for a workspace without entering it. ``` ctask info [flags] ``` **Flags:** | Flag | Short | Default | Description | |------|-------|---------|-------------| | `--all` | `-a` | off | Include archived workspaces in query resolution | **Examples:** ```powershell ctask info auth-bug ctask info backup ``` Shows: slug, title, category, status, mode, agent, created/updated timestamps, path, and directory contents. --- ## ctask archive Mark a workspace as archived. The workspace stays in place but is hidden from default listings and query resolution. ``` ctask archive ``` **Examples:** ```powershell ctask archive auth-bug ``` To see archived workspaces, use `ctask list --all`. To resolve archived workspaces in other commands, use the `--all` flag where available. --- ## ctask last Resume the most recently updated workspace, considering **both tasks and projects**. Equivalent to `ctask resume` on whichever active workspace has the latest `updated_at` timestamp. Archived workspaces are excluded. ``` ctask last [flags] ``` **Flags:** | Flag | Short | Default | Description | |------|-------|---------|-------------| | `--shell` | | off | Open shell instead of agent | | `--agent` | `-a` | from task.yaml | Override agent command | | `--force` | | off | Skip active-session and stale-workspace warnings | **Examples:** ```powershell ctask last ctask last --shell ``` If no active workspaces exist, prints an error and exits. --- ## ctask doctor Verify that ctask is correctly set up. Read-only -- never modifies anything. ``` ctask doctor ``` Checks: 1. Workspace root exists and is writable 2. Default agent command is found on PATH 3. Status-line helper script exists at the expected location 4. Claude Code `statusLine` is configured in `~/.claude/settings.json` 5. At least one workspace exists Exits 0 if all checks pass, 1 if any fail. Each failure includes a concrete fix instruction. `ctask doctor` also reports seed directory status: `[INFO]` if the `CTASK_SEED_DIR` / `CTASK_SEED_PROJECT_DIR` variable is unset (built-in defaults will be used), `[PASS]` if the variable is set and the path exists, `[FAIL]` if the variable is set but the path is missing. Only the configured-but-missing state counts as a failure. **Example output:** ``` [PASS] Workspace root exists: C:\Users\Warren\ai-workspaces [PASS] Default agent found: claude [PASS] Status line helper found: C:\Users\Warren\AppData\Local\ctask\bin\ctask-statusline.sh [PASS] Claude Code status line configured [PASS] Workspaces found: 5 tasks (2 archived) [INFO] General seed directory: not configured (using built-in defaults) [INFO] Project seed directory: not configured (using built-in defaults) 5 checks passed, 0 failed ``` --- ## ctask delete Permanently remove a workspace directory. ``` ctask delete [flags] ``` **Flags:** | Flag | Short | Default | Description | |------|-------|---------|-------------| | `--force` | `-f` | off | Skip confirmation prompt | | `--all` | `-a` | off | Include archived workspaces in query resolution | **Examples:** ```powershell ctask delete old-task ctask delete --force old-task ctask delete --all --force archived-task ``` **Safety:** - Confirmation is required by default. `--force` skips it. - If the workspace has an active session (running in another terminal), deletion is refused even with `--force`. Exit the session first. - If the workspace is the most recently updated one, a note is printed before confirmation. --- ## Query Resolution Commands that take a `` argument (`resume`, `open`, `info`, `archive`, `delete`) resolve workspaces in this order: 1. Exact directory name match (e.g. `2026-04-06_auth-bug`) 2. Exact slug match (e.g. `auth-bug`) 3. Case-insensitive substring match (e.g. `auth`) If multiple workspaces match, all matches are printed and the command exits. If none match, an error is printed. Archived workspaces are excluded from matching by default. Use `--all` where supported to include them. --- ## Environment Variables ctask exports these into every child session: | Variable | Description | |----------|-------------| | `CTASK_TASK` | Task slug | | `CTASK_MODE` | Execution mode (`local`) | | `CTASK_ROOT` | Resolved workspace root path | | `CTASK_WORKSPACE` | Full workspace path | | `CTASK_CATEGORY` | Category name | | `CTASK_TYPE` | `task` or `project` | Configure ctask behavior with: | Variable | Default | Description | |----------|---------|-------------| | `CTASK_ROOT` | `%USERPROFILE%\ai-workspaces` (Windows) / `~/ai-workspaces` (Unix) | Workspace root directory | | `CTASK_AGENT` | `claude` | Default agent command | | `CTASK_PROJECT_ROOT` | (none) | Workspace root for projects. When set, project workspaces are created directly under this path (no doubled `projects/` segment unless `-c` is passed). | | `CTASK_SEED_DIR` | `%APPDATA%\ctask\seed\` (Windows) / `~/.config/ctask/seed/` (Unix) | General user seed directory copied into every new workspace. | | `CTASK_SEED_PROJECT_DIR` | `%APPDATA%\ctask\seed-project\` (Windows) / `~/.config/ctask/seed-project/` (Unix) | Project seed directory copied only for `--project` workspaces (overlay on top of the general seed). | --- ## Concurrency and safety ctask v0.4 protects workspaces from conflicts when multiple sessions (or manual file edits) touch the same workspace. ### Session lease Each active `ctask resume`, `open`, `last`, or `new` writes a lease file at `/.ctask/session.json` identifying the ctask process, hostname, user, agent, mode, and a heartbeat timestamp. A background goroutine updates the heartbeat every 30 seconds. On session start, if a fresh lease already exists (heartbeat within 60 seconds), ctask warns: ``` [ctask] This workspace has an active session: Session: Host: Agent: Started: ( ago) Last seen: ago Opening a second session may cause conflicts. Continue anyway? [y/N] ``` If the user answers `y`, the second session proceeds **without writing its own lease** (see "Known limitation: coexisting sessions" below). If the lease is older than 60 seconds (crash, lost connection), ctask cleans it up silently and proceeds. ### Metadata write lock All ctask-owned file writes (`task.yaml`, `logs/sessions.log`, `.ctask/session.json`, `.ctask/manifest-start.json`, `.ctask/last-session-summary.json`) are serialized through `/.ctask/write.lock`. The lock is held for the duration of one write only. If the lock cannot be acquired within 2 seconds, the write is skipped with a warning rather than blocking. ### Stale-workspace detection On session start, ctask compares the current workspace state against the end-state recorded by the previous session's summary. If anything changed outside a ctask session (another machine, manual edits), ctask warns: ``` [ctask] Workspace modified since last session ended: Last session: (, ) Modified since then: notes.md (modified) output/report.md (new file) These changes were not made during a ctask session. Review before continuing? [Y/n] ``` Press Enter (or `y`) to proceed. Press `n` to exit without launching. This check is skipped silently for workspaces that have never completed a v0.4 session (no `last-session-summary.json`). ### Session handoff summary At end of session, ctask writes `/.ctask/last-session-summary.json` containing: - `session_id`, `hostname`, `agent`, `mode` - `started_at`, `ended_at`, `duration_seconds` - `files_added`, `files_modified`, `files_deleted` - `notes_updated` - `end_manifest` (snapshot of workspace file list at session end -- used by the stale-workspace detector) The next session prints a short orientation banner from this file: ``` [ctask] local :: api-cleanup [ctask] ~/ai-workspaces/general/2026-04-21_api-cleanup [ctask] Last session: 2026-04-21 14:30-15:45 (warren-desktop, claude) [ctask] Changed: notes.md, output/plan.md ``` ### `--force` `--force` on `resume`, `open`, and `last` suppresses both the active-session warning and the stale-workspace warning. It does **not** disable the metadata write lock or the session summary -- those are always active. Use `--force` only for automation where the human has already decided to proceed. ### Known limitation: coexisting sessions When the user confirms "Continue anyway?" on an active-session warning (or passes `--force`), the second session runs **without writing its own lease**. This keeps the lease model simple (one lease file per workspace), but has two consequences: 1. A third session attempt will only see the original lease. The second (coexisting) session is invisible to lease-based detection. 2. If the original session exits and removes its lease before the coexisting session finishes, the coexisting session is unprotected for its remaining lifetime. The metadata write lock still serializes all ctask-owned file writes regardless of session count, so no state corruption can occur. If you need stronger guarantees, exit the existing session before starting another one. --- ## Exit Codes | Code | Meaning | |------|---------| | 0 | Success | | 1 | General error (multiple matches, not found, invalid args, doctor failure) | | 2 | Missing required argument | | 127 | Agent command not found |