summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-11 22:20:57 +0300
committerPaul Buetow <paul@buetow.org>2026-04-11 22:20:57 +0300
commit69d3ec004b8de3b9f7cfeb34686b9c344c787db4 (patch)
tree857101184293efa61f9d1caba4c3b80b31e89a37
parent5bc434d71fb5057131f1e5c0b2371db42d3b4ed4 (diff)
Rename task CLI binary from do back to ask
- Move cmd/do to cmd/ask; mage builds and installs ask; Fish completions to ask.fish - Update askcli help text, errors, executor default label, and Fish script (__ask_*) - Task alias cache subdirectory under XDG cache: hexai/ask/ - Rename integration test files and helpers; refresh README and docs - Rename plan-do-uuid-wrapper.md to plan-ask-uuid-wrapper.md Made-with: Cursor
-rw-r--r--.gitignore4
-rw-r--r--Magefile.go20
-rw-r--r--README.md12
-rw-r--r--cmd/ask/main.go (renamed from cmd/do/main.go)0
-rw-r--r--cmd/ask/main_test.go (renamed from cmd/do/main_test.go)0
-rw-r--r--docs/buildandinstall.md8
-rw-r--r--docs/fish-completion.md26
-rw-r--r--docs/plan-ask-uuid-wrapper.md154
-rw-r--r--docs/plan-do-uuid-wrapper.md154
-rw-r--r--docs/usage.md94
-rw-r--r--integrationtests/ask_scope_test.go (renamed from integrationtests/do_scope_test.go)54
-rw-r--r--integrationtests/ask_test.go (renamed from integrationtests/do_test.go)160
-rw-r--r--internal/askcli/command_add.go8
-rw-r--r--internal/askcli/command_delete.go2
-rw-r--r--internal/askcli/command_dep.go8
-rw-r--r--internal/askcli/command_fish.go4
-rw-r--r--internal/askcli/command_info_add_test.go2
-rw-r--r--internal/askcli/command_write.go16
-rw-r--r--internal/askcli/completion.go132
-rw-r--r--internal/askcli/completion_test.go44
-rw-r--r--internal/askcli/dispatch.go52
-rw-r--r--internal/askcli/dispatch_test.go18
-rw-r--r--internal/askcli/formatter.go2
-rw-r--r--internal/askcli/task_alias_cache.go2
-rw-r--r--internal/askcli/taskexec.go6
-rw-r--r--internal/askcli/taskexec_test.go26
-rw-r--r--internal/taskproxy/run_test.go12
27 files changed, 522 insertions, 498 deletions
diff --git a/.gitignore b/.gitignore
index 49978b8..3b8714e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
+/ask
/do
-/cmd/do/do
-/cmd/do/ask
+/cmd/ask/ask
/hexai
/hexai-lsp-server
/hexai-mcp-server
diff --git a/Magefile.go b/Magefile.go
index e5d744d..4cea341 100644
--- a/Magefile.go
+++ b/Magefile.go
@@ -26,15 +26,15 @@ var (
// Build builds binaries.
func Build() error {
- mg.Deps(BuildDo, BuildHexaiLSP, BuildHexaiCLI, BuildHexaiTmuxAction, BuildHexaiTmuxEdit, BuildHexaiMCPServer)
+ mg.Deps(BuildAsk, BuildHexaiLSP, BuildHexaiCLI, BuildHexaiTmuxAction, BuildHexaiTmuxEdit, BuildHexaiMCPServer)
printCoverage()
return nil
}
-// BuildDo builds the Taskwarrior proxy wrapper.
-func BuildDo() error {
+// BuildAsk builds the Taskwarrior proxy wrapper.
+func BuildAsk() error {
printCoverage()
- return sh.RunV("go", "build", "-o", "do", "./cmd/do")
+ return sh.RunV("go", "build", "-o", "ask", "./cmd/ask")
}
// BuildHexaiLSP builds the LSP server binary.
@@ -71,7 +71,7 @@ func BuildHexaiMCPServer() error {
func Dev() error {
printCoverage()
mg.Deps(Test, Vet, Lint)
- if err := sh.RunV("go", "build", "-race", "-o", "do", "./cmd/do"); err != nil {
+ if err := sh.RunV("go", "build", "-race", "-o", "ask", "./cmd/ask"); err != nil {
return err
}
if err := sh.RunV("go", "build", "-race", "-o", "hexai-lsp-server", "./cmd/hexai-lsp-server"); err != nil {
@@ -121,7 +121,7 @@ func Install() error {
return err
}
for _, name := range []string{
- "do",
+ "ask",
"hexai-lsp-server",
"hexai",
"hexai-tmux-action",
@@ -132,10 +132,10 @@ func Install() error {
return err
}
}
- return installFishCompletion(filepath.Join(bin, "do"))
+ return installFishCompletion(filepath.Join(bin, "ask"))
}
-func installFishCompletion(doBin string) error {
+func installFishCompletion(askBin string) error {
fishConfigDir, err := resolveFishConfigDir()
if err != nil {
return err
@@ -144,11 +144,11 @@ func installFishCompletion(doBin string) error {
if err := os.MkdirAll(completionsDir, 0o755); err != nil {
return err
}
- out, err := exec.Command(doBin, "fish").Output()
+ out, err := exec.Command(askBin, "fish").Output()
if err != nil {
return fmt.Errorf("generate fish completion: %w", err)
}
- dst := filepath.Join(completionsDir, "do.fish")
+ dst := filepath.Join(completionsDir, "ask.fish")
if err := os.WriteFile(dst, out, 0o644); err != nil {
return err
}
diff --git a/README.md b/README.md
index e323c8b..ad80817 100644
--- a/README.md
+++ b/README.md
@@ -14,15 +14,15 @@ It has got improved capabilities for Go code understanding (for example, create
* Stand-alone command line tool for LLM interaction
- Includes `--tps-simulation` to preview how fast a model would feel by streaming placeholder text or piped stdin at a chosen token-per-second rate
* Task management CLI for agent-managed project work
- - Entrypoint: `do` (the binary was formerly named `ask`; use `do` in scripts and documentation)
+ - Entrypoint: `ask` (the binary was briefly named `do`; use `ask` in scripts and documentation)
- Auto-scopes to `project:<repo> +agent` (derived from git repo root)
- - Override the project explicitly with `do proj:<name> <subcommand...>`
- - Prefixes can be combined, for example `do proj:<name> na <subcommand...>`
+ - Override the project explicitly with `ask proj:<name> <subcommand...>`
+ - Prefixes can be combined, for example `ask proj:<name> na <subcommand...>`
- Never exposes numeric task IDs; human-facing output uses stable alias IDs
- - `do info` hides raw UUIDs unless `HEXAI_DEBUG` is set
+ - `ask info` hides raw UUIDs unless `HEXAI_DEBUG` is set
- Machine-friendly output with suppressed decorative text
- - Subcommands: `do add`, `do list`, `do info`, `do annotate`, `do start`, `do stop`, `do done`, `do priority`, `do tag`, `do dep`, `do urgency`, `do modify`, `do denotate`, `do delete`, `do fish`, `do help`
- - Fish completion generator: `do fish`
+ - Subcommands: `ask add`, `ask list`, `ask info`, `ask annotate`, `ask start`, `ask stop`, `ask done`, `ask priority`, `ask tag`, `ask dep`, `ask urgency`, `ask modify`, `ask denotate`, `ask delete`, `ask fish`, `ask help`
+ - Fish completion generator: `ask fish`
* Parallel completions and CLI responses from multiple providers/models for side-by-side comparison
* **MCP server for prompt/runbook management** (`hexai-mcp-server`) - **⚠️ DEPRECATED/EXPERIMENTAL**
- Create, update, delete, and retrieve prompts via MCP protocol
diff --git a/cmd/do/main.go b/cmd/ask/main.go
index afab992..afab992 100644
--- a/cmd/do/main.go
+++ b/cmd/ask/main.go
diff --git a/cmd/do/main_test.go b/cmd/ask/main_test.go
index db6b436..db6b436 100644
--- a/cmd/do/main_test.go
+++ b/cmd/ask/main_test.go
diff --git a/docs/buildandinstall.md b/docs/buildandinstall.md
index 7d29c71..4a3ccd7 100644
--- a/docs/buildandinstall.md
+++ b/docs/buildandinstall.md
@@ -3,7 +3,7 @@
Hexai uses Mage for developer tasks. Install Mage, then run targets like build, dev, test, and install.
- Install Mage: `go install github.com/magefile/mage@latest`
-- Build binaries: `mage build` (produces `do`, `hexai`, `hexai-lsp-server`, `hexai-tmux-action`, and `hexai-tmux-edit`)
+- Build binaries: `mage build` (produces `ask`, `hexai`, `hexai-lsp-server`, `hexai-tmux-action`, and `hexai-tmux-edit`)
- Dev build (+ tests, vet, lint): `mage dev`
- Run tests: `mage test`
- Run tests with coverage: `go test ./... -cover`
@@ -11,8 +11,8 @@ Hexai uses Mage for developer tasks. Install Mage, then run targets like build,
- In restricted sandboxes/CI (no sockets), skip network-based tests:
- `HEXAI_TEST_SKIP_NET=1 go test ./... -cover`
- Install binaries to `GOPATH/bin`: `mage install`
-- `mage install` also writes Fish completion to `~/.config/fish/completions/do.fish` (or `$XDG_CONFIG_HOME/fish/completions/do.fish`)
-- Load Fish completions in the current shell immediately after install: `~/go/bin/do fish | source`
+- `mage install` also writes Fish completion to `~/.config/fish/completions/ask.fish` (or `$XDG_CONFIG_HOME/fish/completions/ask.fish`)
+- Load Fish completions in the current shell immediately after install: `~/go/bin/ask fish | source`
Note: `mage lint` uses `golangci-lint`. Install via `mage devinstall` if needed.
@@ -20,7 +20,7 @@ Note: `mage lint` uses `golangci-lint`. Install via `mage devinstall` if needed.
Either use the Mage method as mentioned above, or install directly with:
-- Task CLI (`do`, agent-scoped Taskwarrior wrapper): `go install codeberg.org/snonux/hexai/cmd/do@latest`
+- Task CLI (`ask`, agent-scoped Taskwarrior wrapper): `go install codeberg.org/snonux/hexai/cmd/ask@latest`
- CLI: `go install codeberg.org/snonux/hexai/cmd/hexai@latest`
- LSP: `go install codeberg.org/snonux/hexai/cmd/hexai-lsp-server@latest`
- Action runner: `go install codeberg.org/snonux/hexai/cmd/hexai-tmux-action@latest`
diff --git a/docs/fish-completion.md b/docs/fish-completion.md
index 19a90be..f8a4373 100644
--- a/docs/fish-completion.md
+++ b/docs/fish-completion.md
@@ -1,37 +1,37 @@
# Fish Completion
-The `do` task-management CLI embeds its Fish completion script in the binary and prints it with `do fish`.
+The `ask` task-management CLI embeds its Fish completion script in the binary and prints it with `ask fish`.
-It completes the top-level `do` subcommands and the nested `do dep` operations.
+It completes the top-level `ask` subcommands and the nested `ask dep` operations.
It also suggests the global task prefixes `na`, `no-agent`, and `proj:`.
-It also completes task selectors for UUID-taking commands by reading pending tasks through `do complete-aliases`, which uses the local alias cache for stable short IDs.
-The `do complete-uuids` command still emits both alias and UUID lines for scripts and tests that need the full selector list.
-Selector suggestions stop once a command has consumed its selector argument, and `do dep add` / `do dep rm` suggest selectors for both task positions.
-When typing `do add depends:...`, Fish also completes the comma-separated dependency selector list inside the `depends:` modifier.
+It also completes task selectors for UUID-taking commands by reading pending tasks through `ask complete-aliases`, which uses the local alias cache for stable short IDs.
+The `ask complete-uuids` command still emits both alias and UUID lines for scripts and tests that need the full selector list.
+Selector suggestions stop once a command has consumed its selector argument, and `ask dep add` / `ask dep rm` suggest selectors for both task positions.
+When typing `ask add depends:...`, Fish also completes the comma-separated dependency selector list inside the `depends:` modifier.
The script preserves the global `--json` flag.
Load it into the current Fish session:
```sh
-do fish | source
+ask fish | source
```
If you installed with `mage install` and `~/go/bin` is not on your `PATH` yet, use:
```sh
-~/go/bin/do fish | source
+~/go/bin/ask fish | source
```
To enable it automatically for new Fish sessions, add this to your Fish config or a file in `~/.config/fish/conf.d/`:
```fish
-set -l do_bin ~/go/bin/do
+set -l ask_bin ~/go/bin/ask
-if test -x $do_bin
- $do_bin fish | source
+if test -x $ask_bin
+ $ask_bin fish | source
end
```
-No external `do.fish` file is required.
+No external `ask.fish` file is required.
-If you installed with `mage install`, the installer also writes an autoloadable completion file to `~/.config/fish/completions/do.fish` (or `$XDG_CONFIG_HOME/fish/completions/do.fish`), so new Fish sessions should pick it up automatically.
+If you installed with `mage install`, the installer also writes an autoloadable completion file to `~/.config/fish/completions/ask.fish` (or `$XDG_CONFIG_HOME/fish/completions/ask.fish`), so new Fish sessions should pick it up automatically.
diff --git a/docs/plan-ask-uuid-wrapper.md b/docs/plan-ask-uuid-wrapper.md
new file mode 100644
index 0000000..dfc40d4
--- /dev/null
+++ b/docs/plan-ask-uuid-wrapper.md
@@ -0,0 +1,154 @@
+# Plan: `ask` as UUID-only Taskwarrior Wrapper
+
+The user-facing CLI binary is **`ask`** (it was briefly named `do`). This document uses `ask` throughout. The Go implementation package remains `internal/askcli` in the tree below.
+
+## Goal
+
+Rewrite the `ask` command from a thin pass-through proxy into a **subcommand-based CLI** that wraps Taskwarrior. The wrapper never exposes numeric task IDs to the caller — only UUIDs. Output is minimal and machine-friendly for coding agents.
+
+The existing `project:<repo> +agent` auto-injection is preserved.
+
+## Subcommands
+
+| Subcommand | Example | Taskwarrior equivalent |
+|---|---|---|
+| `ask add "Implement X"` | create task | `task project:P +agent add "Implement X"` |
+| `ask add priority:H +cli "Fix bug"` | create with priority & tag | same + `priority:H +cli` |
+| `ask list` | list pending tasks | `task project:P +agent status:pending export` → reformat |
+| `ask info <uuid>` | show one task | `task uuid:<uuid> export` → filtered fields |
+| `ask annotate <uuid> "note"` | add annotation | `task uuid:<uuid> annotate "note"` |
+| `ask start <uuid>` | start work | `task uuid:<uuid> start` |
+| `ask stop <uuid>` | stop work | `task uuid:<uuid> stop` |
+| `ask done <uuid>` | mark complete | `task uuid:<uuid> done` |
+| `ask priority <uuid> H` | set priority | `task uuid:<uuid> modify priority:H` |
+| `ask tag <uuid> +foo` | add tag | `task uuid:<uuid> modify +foo` |
+| `ask tag <uuid> -foo` | remove tag | `task uuid:<uuid> modify -foo` |
+| `ask dep add <uuid> <dep-uuid>` | add dependency | `task uuid:<uuid> modify depends:<dep-uuid>` |
+| `ask dep rm <uuid> <dep-uuid>` | remove dependency | `task uuid:<uuid> modify depends:-<dep-uuid>` |
+| `ask dep list <uuid>` | show dependencies | `task uuid:<uuid> export` → `depends` field |
+| `ask urgency` | list by urgency | `task project:P +agent export` → sort by urgency |
+| `ask modify <uuid> <args...>` | general modify | `task uuid:<uuid> modify <args...>` (priority, tags, depends, /old/new/) |
+| `ask denotate <uuid> "text"` | remove annotation | `task uuid:<uuid> denotate "text"` |
+| `ask delete <uuid>` | delete task | `task uuid:<uuid> delete` |
+| `ask export` | raw JSON dump | `task project:P +agent export` → pass through |
+
+### List filters, sort, and limit
+
+`ask list` accepts optional filters, sort, and limit arguments:
+
+| Example | Taskwarrior equivalent |
+|---|---|
+| `ask list` | `task project:P +agent status:pending export` (default sort: priority-, urgency-) |
+| `ask list +READY` | `task project:P +agent +READY export` |
+| `ask list +BLOCKED` | `task project:P +agent +BLOCKED export` |
+| `ask list +frontend` | `task project:P +agent +frontend export` |
+| `ask list started` | `task project:P +agent start.any: export` |
+| `ask list limit:3` | show only first 3 results |
+| `ask list +READY limit:1` | next ready task |
+
+## Data Retrieval: `task export`
+
+All read operations use `task <filter> export` which returns a JSON array. This avoids fragile text parsing. Write operations (`add`, `done`, `start`, `stop`, `annotate`, `modify`) call Taskwarrior directly and capture stdout to extract the created UUID.
+
+### TaskExport struct
+
+```go
+type TaskExport struct {
+ UUID string `json:"uuid"`
+ Description string `json:"description"`
+ Status string `json:"status"`
+ Priority string `json:"priority"`
+ Tags []string `json:"tags"`
+ Start string `json:"start,omitempty"`
+ Urgency float64 `json:"urgency"`
+ Depends []string `json:"depends"`
+ Annotations []struct {
+ Description string `json:"description"`
+ Entry string `json:"entry"`
+ } `json:"annotations"`
+}
+```
+
+## Output Formatting
+
+- **`list` / `urgency`**: Compact table — `UUID | Priority | Status | Tags | Description | Urgency`. No numeric ID column.
+- **`info`**: UUID, description, status, priority, tags, annotations, dependencies (as UUIDs), urgency.
+- **`add`**: Print only the UUID of the created task (parse from Taskwarrior stdout).
+- **All other write commands**: Print success/failure + UUID. Suppress Taskwarrior decorative output.
+
+## ID Rejection
+
+If an argument looks like a bare numeric ID where a UUID is expected, reject with: `"use UUID, not numeric task ID"`.
+
+## Package Layout
+
+```
+cmd/ask/main.go — parse subcommand, dispatch to internal/askcli
+internal/askcli/ — implementation package (CLI name: ask)
+ ├── dispatch.go — subcommand router (switch args[0])
+ ├── taskexec.go — wraps Taskwarrior execution (binary lookup, repo detection, run)
+ ├── taskexport.go — TaskExport struct + JSON parse helper
+ ├── formatter.go — shared UUID-only table/info formatting
+ ├── command_add.go — add logic + UUID extraction from stdout
+ ├── command_list.go — list via export + reformat
+ ├── command_info.go — info via export + field filter
+ ├── command_annotate.go — annotate
+ ├── command_start.go — start
+ ├── command_stop.go — stop
+ ├── command_done.go — done
+ ├── command_priority.go — set priority
+ ├── command_tag.go — add/remove tags
+ ├── command_dep.go — dep add/rm/list
+ ├── command_urgency.go — urgency-sorted list
+ ├── command_modify.go — general-purpose modify
+ ├── command_denotate.go — remove annotation
+ ├── command_delete.go — delete task
+ └── command_export.go — raw JSON export
+```
+
+Each `command_*.go` file gets a corresponding `command_*_test.go`.
+
+## Changes to Existing Code
+
+- **`cmd/ask/main.go`** — stops calling `taskproxy.Runner.Run` directly; delegates to `askcli.Dispatch()`.
+- **`internal/taskproxy/`** — reused by `askcli/taskexec.go` for binary lookup (`findTaskBinary`) and repo root detection (`detectRepoRoot`). The `Runner.Run` pass-through method becomes unused and can be removed.
+
+## Task Breakdown
+
+1. Scaffold `internal/askcli/` — dispatch, taskexec, taskexport, formatter
+2. Implement `ask add` (UUID extraction from Taskwarrior stdout)
+3. Implement `ask list` (export → UUID-only table)
+4. Implement `ask info <uuid>` (export → filtered fields)
+5. Implement `ask annotate <uuid> "note"`
+6. Implement `ask start <uuid>` / `ask stop <uuid>`
+7. Implement `ask done <uuid>`
+8. Implement `ask priority <uuid> <P>`
+9. Implement `ask tag <uuid> +/-tag`
+10. Implement `ask dep add/rm/list`
+11. Implement `ask urgency`
+12. Implement `ask modify <uuid> <args...>` (general-purpose modify)
+13. Implement `ask denotate <uuid> "text"` (remove annotation)
+14. Implement `ask delete <uuid>`
+15. Implement `ask export` (raw JSON)
+16. Add filter/sort/limit support to `ask list` (+READY, +BLOCKED, +tag, started, limit:N)
+17. Wire `cmd/ask/main.go` to `askcli.Dispatch`, remove old pass-through
+18. Update docs and README
+19. Create `agent-task-management` skill (replacement for `taskwarrior-task-management`) — uses only `ask` subcommands, no Taskwarrior references
+20. Update Pi coding agent: rename `taskwarrior-plan-mode` extension → `agent-plan-mode`, rewrite to use `ask` subcommands only
+21. Audit `agent-task-management` skill and `agent-plan-mode` extension: ensure zero Taskwarrior leakage — agents must see `ask` as the native task system, not a wrapper
+
+## Skill & Extension Migration
+
+After the `ask` CLI is complete and documented, three follow-up tasks abstract away the Taskwarrior implementation detail:
+
+### 19. `agent-task-management` skill
+
+Create a new skill at `~/.agents/skills/agent-task-management/` by copying the structure from `taskwarrior-task-management` (SKILL.md + references/00-context.md through 5-review-overview-tasks.md). Rewrite all content to use `ask` subcommands (`ask add`, `ask list`, `ask info`, `ask start`, `ask stop`, `ask done`, `ask annotate`, `ask denotate`, `ask modify`, `ask priority`, `ask tag`, `ask dep`, `ask urgency`, `ask delete`, `ask export`). Remove all mentions of Taskwarrior, raw `task` command, numeric IDs, and `_uuid` lookups.
+
+### 20. `agent-plan-mode` Pi extension
+
+Rename `~/git/hyperstack/pi/agent/extensions/taskwarrior-plan-mode/` → `agent-plan-mode/`. Update `index.ts`, `utils.ts`, `README.md` to use new `ask` subcommands instead of raw pass-through calls. Rename `TaskwarriorTask` type, update state keys, command names, descriptions, and UI messages.
+
+### 21. Taskwarrior leakage audit
+
+Grep all files in the new skill and extension for `taskwarrior` (any casing), `task warrior`, raw `task ` command patterns, numeric task ID usage, `_uuid` lookups, and any hint that `ask` wraps another tool. **Agents must believe `ask` IS the task management system — not a proxy.** This prevents agents from attempting raw Taskwarrior commands or mentioning Taskwarrior in annotations/descriptions.
diff --git a/docs/plan-do-uuid-wrapper.md b/docs/plan-do-uuid-wrapper.md
deleted file mode 100644
index ed4303b..0000000
--- a/docs/plan-do-uuid-wrapper.md
+++ /dev/null
@@ -1,154 +0,0 @@
-# Plan: `do` as UUID-only Taskwarrior Wrapper
-
-The user-facing CLI binary is **`do`** (it was previously named `ask`). This document uses `do` throughout. The Go implementation package remains `internal/askcli` in the tree below.
-
-## Goal
-
-Rewrite the `do` command from a thin pass-through proxy into a **subcommand-based CLI** that wraps Taskwarrior. The wrapper never exposes numeric task IDs to the caller — only UUIDs. Output is minimal and machine-friendly for coding agents.
-
-The existing `project:<repo> +agent` auto-injection is preserved.
-
-## Subcommands
-
-| Subcommand | Example | Taskwarrior equivalent |
-|---|---|---|
-| `do add "Implement X"` | create task | `task project:P +agent add "Implement X"` |
-| `do add priority:H +cli "Fix bug"` | create with priority & tag | same + `priority:H +cli` |
-| `do list` | list pending tasks | `task project:P +agent status:pending export` → reformat |
-| `do info <uuid>` | show one task | `task uuid:<uuid> export` → filtered fields |
-| `do annotate <uuid> "note"` | add annotation | `task uuid:<uuid> annotate "note"` |
-| `do start <uuid>` | start work | `task uuid:<uuid> start` |
-| `do stop <uuid>` | stop work | `task uuid:<uuid> stop` |
-| `do done <uuid>` | mark complete | `task uuid:<uuid> done` |
-| `do priority <uuid> H` | set priority | `task uuid:<uuid> modify priority:H` |
-| `do tag <uuid> +foo` | add tag | `task uuid:<uuid> modify +foo` |
-| `do tag <uuid> -foo` | remove tag | `task uuid:<uuid> modify -foo` |
-| `do dep add <uuid> <dep-uuid>` | add dependency | `task uuid:<uuid> modify depends:<dep-uuid>` |
-| `do dep rm <uuid> <dep-uuid>` | remove dependency | `task uuid:<uuid> modify depends:-<dep-uuid>` |
-| `do dep list <uuid>` | show dependencies | `task uuid:<uuid> export` → `depends` field |
-| `do urgency` | list by urgency | `task project:P +agent export` → sort by urgency |
-| `do modify <uuid> <args...>` | general modify | `task uuid:<uuid> modify <args...>` (priority, tags, depends, /old/new/) |
-| `do denotate <uuid> "text"` | remove annotation | `task uuid:<uuid> denotate "text"` |
-| `do delete <uuid>` | delete task | `task uuid:<uuid> delete` |
-| `do export` | raw JSON dump | `task project:P +agent export` → pass through |
-
-### List filters, sort, and limit
-
-`do list` accepts optional filters, sort, and limit arguments:
-
-| Example | Taskwarrior equivalent |
-|---|---|
-| `do list` | `task project:P +agent status:pending export` (default sort: priority-, urgency-) |
-| `do list +READY` | `task project:P +agent +READY export` |
-| `do list +BLOCKED` | `task project:P +agent +BLOCKED export` |
-| `do list +frontend` | `task project:P +agent +frontend export` |
-| `do list started` | `task project:P +agent start.any: export` |
-| `do list limit:3` | show only first 3 results |
-| `do list +READY limit:1` | next ready task |
-
-## Data Retrieval: `task export`
-
-All read operations use `task <filter> export` which returns a JSON array. This avoids fragile text parsing. Write operations (`add`, `done`, `start`, `stop`, `annotate`, `modify`) call Taskwarrior directly and capture stdout to extract the created UUID.
-
-### TaskExport struct
-
-```go
-type TaskExport struct {
- UUID string `json:"uuid"`
- Description string `json:"description"`
- Status string `json:"status"`
- Priority string `json:"priority"`
- Tags []string `json:"tags"`
- Start string `json:"start,omitempty"`
- Urgency float64 `json:"urgency"`
- Depends []string `json:"depends"`
- Annotations []struct {
- Description string `json:"description"`
- Entry string `json:"entry"`
- } `json:"annotations"`
-}
-```
-
-## Output Formatting
-
-- **`list` / `urgency`**: Compact table — `UUID | Priority | Status | Tags | Description | Urgency`. No numeric ID column.
-- **`info`**: UUID, description, status, priority, tags, annotations, dependencies (as UUIDs), urgency.
-- **`add`**: Print only the UUID of the created task (parse from Taskwarrior stdout).
-- **All other write commands**: Print success/failure + UUID. Suppress Taskwarrior decorative output.
-
-## ID Rejection
-
-If an argument looks like a bare numeric ID where a UUID is expected, reject with: `"use UUID, not numeric task ID"`.
-
-## Package Layout
-
-```
-cmd/do/main.go — parse subcommand, dispatch to internal/askcli
-internal/askcli/ — implementation package (CLI name: do)
- ├── dispatch.go — subcommand router (switch args[0])
- ├── taskexec.go — wraps Taskwarrior execution (binary lookup, repo detection, run)
- ├── taskexport.go — TaskExport struct + JSON parse helper
- ├── formatter.go — shared UUID-only table/info formatting
- ├── command_add.go — add logic + UUID extraction from stdout
- ├── command_list.go — list via export + reformat
- ├── command_info.go — info via export + field filter
- ├── command_annotate.go — annotate
- ├── command_start.go — start
- ├── command_stop.go — stop
- ├── command_done.go — done
- ├── command_priority.go — set priority
- ├── command_tag.go — add/remove tags
- ├── command_dep.go — dep add/rm/list
- ├── command_urgency.go — urgency-sorted list
- ├── command_modify.go — general-purpose modify
- ├── command_denotate.go — remove annotation
- ├── command_delete.go — delete task
- └── command_export.go — raw JSON export
-```
-
-Each `command_*.go` file gets a corresponding `command_*_test.go`.
-
-## Changes to Existing Code
-
-- **`cmd/do/main.go`** — stops calling `taskproxy.Runner.Run` directly; delegates to `askcli.Dispatch()`.
-- **`internal/taskproxy/`** — reused by `askcli/taskexec.go` for binary lookup (`findTaskBinary`) and repo root detection (`detectRepoRoot`). The `Runner.Run` pass-through method becomes unused and can be removed.
-
-## Task Breakdown
-
-1. Scaffold `internal/askcli/` — dispatch, taskexec, taskexport, formatter
-2. Implement `do add` (UUID extraction from Taskwarrior stdout)
-3. Implement `do list` (export → UUID-only table)
-4. Implement `do info <uuid>` (export → filtered fields)
-5. Implement `do annotate <uuid> "note"`
-6. Implement `do start <uuid>` / `do stop <uuid>`
-7. Implement `do done <uuid>`
-8. Implement `do priority <uuid> <P>`
-9. Implement `do tag <uuid> +/-tag`
-10. Implement `do dep add/rm/list`
-11. Implement `do urgency`
-12. Implement `do modify <uuid> <args...>` (general-purpose modify)
-13. Implement `do denotate <uuid> "text"` (remove annotation)
-14. Implement `do delete <uuid>`
-15. Implement `do export` (raw JSON)
-16. Add filter/sort/limit support to `do list` (+READY, +BLOCKED, +tag, started, limit:N)
-17. Wire `cmd/do/main.go` to `askcli.Dispatch`, remove old pass-through
-18. Update docs and README
-19. Create `agent-task-management` skill (replacement for `taskwarrior-task-management`) — uses only `do` subcommands, no Taskwarrior references
-20. Update Pi coding agent: rename `taskwarrior-plan-mode` extension → `agent-plan-mode`, rewrite to use `do` subcommands only
-21. Audit `agent-task-management` skill and `agent-plan-mode` extension: ensure zero Taskwarrior leakage — agents must see `do` as the native task system, not a wrapper
-
-## Skill & Extension Migration
-
-After the `do` CLI is complete and documented, three follow-up tasks abstract away the Taskwarrior implementation detail:
-
-### 19. `agent-task-management` skill
-
-Create a new skill at `~/.agents/skills/agent-task-management/` by copying the structure from `taskwarrior-task-management` (SKILL.md + references/00-context.md through 5-review-overview-tasks.md). Rewrite all content to use `do` subcommands (`do add`, `do list`, `do info`, `do start`, `do stop`, `do done`, `do annotate`, `do denotate`, `do modify`, `do priority`, `do tag`, `do dep`, `do urgency`, `do delete`, `do export`). Remove all mentions of Taskwarrior, raw `task` command, numeric IDs, and `_uuid` lookups.
-
-### 20. `agent-plan-mode` Pi extension
-
-Rename `~/git/hyperstack/pi/agent/extensions/taskwarrior-plan-mode/` → `agent-plan-mode/`. Update `index.ts`, `utils.ts`, `README.md` to use new `do` subcommands instead of raw pass-through calls. Rename `TaskwarriorTask` type, update state keys, command names, descriptions, and UI messages.
-
-### 21. Taskwarrior leakage audit
-
-Grep all files in the new skill and extension for `taskwarrior` (any casing), `task warrior`, raw `task ` command patterns, numeric task ID usage, `_uuid` lookups, and any hint that `do` wraps another tool. **Agents must believe `do` IS the task management system — not a proxy.** This prevents agents from attempting raw Taskwarrior commands or mentioning Taskwarrior in annotations/descriptions.
diff --git a/docs/usage.md b/docs/usage.md
index 3ebd76e..ce449f4 100644
--- a/docs/usage.md
+++ b/docs/usage.md
@@ -125,92 +125,92 @@ cat SOMEFILE.txt | hexai --tps-simulation 20
## Task management
-`do` is a task management CLI for the current git project. The binary was previously named `ask`; use `do` everywhere (commands, scripts, shell completion).
+`ask` is a task management CLI for the current git project. The binary was briefly named `do`; use `ask` everywhere (commands, scripts, shell completion).
By default it auto-scopes to `project:<repo> +agent` so operations are confined to agent-managed project tasks.
-Use `do proj:<name> <subcommand...>` to override the project explicitly instead of deriving it from the current git repository.
+Use `ask proj:<name> <subcommand...>` to override the project explicitly instead of deriving it from the current git repository.
-Use `do na <subcommand...>` or `do no-agent <subcommand...>` to run the same subcommands against project tasks without the `+agent` tag. Those prefixes keep the project scope but replace the default tag filter with `-agent`.
+Use `ask na <subcommand...>` or `ask no-agent <subcommand...>` to run the same subcommands against project tasks without the `+agent` tag. Those prefixes keep the project scope but replace the default tag filter with `-agent`.
-You can combine the prefixes in either order, for example `do proj:hexai na list` or `do na proj:hexai list`.
+You can combine the prefixes in either order, for example `ask proj:hexai na list` or `ask na proj:hexai list`.
-`do` never exposes Taskwarrior numeric task IDs. Human-facing output uses stable local alias IDs where practical. `do info` hides the raw UUID by default and only prints it when `HEXAI_DEBUG` is set. Commands that accept a task selector still support either the alias ID or the UUID.
+`ask` never exposes Taskwarrior numeric task IDs. Human-facing output uses stable local alias IDs where practical. `ask info` hides the raw UUID by default and only prints it when `HEXAI_DEBUG` is set. Commands that accept a task selector still support either the alias ID or the UUID.
-`do` must be run inside a git repository unless you provide an explicit `proj:<name>` override.
+`ask` must be run inside a git repository unless you provide an explicit `proj:<name>` override.
### Subcommands
| Subcommand | Description |
|---|---|
-| `do add "description"` | Create a new task and print `created task <alias-id>` |
-| `do add depends:<id\|uuid>,<id\|uuid> "description"` | Create task with inline dependencies |
-| `do add priority:H "description"` | Create task with priority |
-| `do add +tag "description"` | Create task with tag |
-| `do na add "description"` | Create a project task without the `+agent` tag |
-| `do list` | List pending tasks only (alias-ID table) |
-| `do na list` | List pending project tasks without the `+agent` tag |
-| `do all` | List all tasks including completed/deleted |
-| `do list +READY` | List only ready tasks |
-| `do list +BLOCKED` | List blocked tasks |
-| `do list +tag` | Filter by tag |
-| `do list started` | List started tasks |
-| `do list limit:N` | Limit results |
-| `do list sort:priority-,urgency-` | Sort by priority then urgency |
-| `do info [id\|uuid]` | Show task details, or the current started task if no selector is provided |
-| `do annotate <id\|uuid> "note"` | Add annotation |
-| `do start <id\|uuid>` | Start working on a task |
-| `do stop <id\|uuid>` | Stop work on a task |
-| `do done <id\|uuid>` | Mark task complete |
-| `do priority <id\|uuid> H\|M\|L` | Set priority |
-| `do tag <id\|uuid> +tag` | Add tag |
-| `do tag <id\|uuid> -tag` | Remove tag |
-| `do dep add <id\|uuid> <dep-id\|dep-uuid>` | Add dependency |
-| `do dep rm <id\|uuid> <dep-id\|dep-uuid>` | Remove dependency |
-| `do dep list <id\|uuid>` | List dependencies |
-| `do urgency` | List tasks by urgency |
-| `do modify <id\|uuid> <args...>` | General-purpose modify |
-| `do denotate <id\|uuid> "text"` | Remove annotation |
-| `do delete <id\|uuid>` | Delete a task |
+| `ask add "description"` | Create a new task and print `created task <alias-id>` |
+| `ask add depends:<id\|uuid>,<id\|uuid> "description"` | Create task with inline dependencies |
+| `ask add priority:H "description"` | Create task with priority |
+| `ask add +tag "description"` | Create task with tag |
+| `ask na add "description"` | Create a project task without the `+agent` tag |
+| `ask list` | List pending tasks only (alias-ID table) |
+| `ask na list` | List pending project tasks without the `+agent` tag |
+| `ask all` |