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
12 changes: 9 additions & 3 deletions cmd/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

var resumeCmd = &cobra.Command{
Use: "resume [issue-id]",
Short: "Show context and set focus",
Short: "Show an issue's context and focus on it",
GroupID: "session",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
Expand All @@ -31,8 +31,14 @@ var resumeCmd = &cobra.Command{
}

var usageCmd = &cobra.Command{
Use: "usage",
Short: "Generate optimized context block for AI agents",
Use: "usage",
Short: "Print a session-aware context block for AI agents",
Long: `Print a compact summary of your session, focused issue, in-progress work,
and reviewable issues. Designed to be pasted into an AI agent at the start of
a conversation so it knows where to pick up.

Use --new-session at conversation start (or after /clear) to rotate sessions.
Use -q/--quiet for the compact form suited to agent prompts.`,
GroupID: "session",
RunE: func(cmd *cobra.Command, args []string) error {
baseDir := getBaseDir()
Expand Down
13 changes: 9 additions & 4 deletions cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@ import (
var createCmd = &cobra.Command{
Use: "create [title]",
Aliases: []string{"add", "new"},
Short: "Create a new issue",
Long: `Create a new issue with optional flags for type, priority, labels, and more.`,
Short: "Create an issue",
Long: `Create an issue. Title is required; type, priority, labels, parent,
dependencies, and rich-text description/acceptance are all optional.

You can prefix the title with a type (e.g., "epic: Migrate auth") and td will
extract it; explicit --type wins.`,
Example: " td create \"Add user auth\" --type feature --priority P1\n" +
" td create \"Rich markdown issue\" --description-file description.md --acceptance-file acceptance.md\n" +
" cat acceptance.md | td create \"Import from stdin\" --acceptance-file -",
" td create \"epic: Migrate auth\" # type from prefix\n" +
" td create \"Rich issue\" --description-file body.md --acceptance-file accept.md\n" +
" cat accept.md | td create \"From stdin\" --acceptance-file -",
GroupID: "core",
RunE: func(cmd *cobra.Command, args []string) error {
// Route "td new task Title" → td create --type task "Title"
Expand Down
7 changes: 5 additions & 2 deletions cmd/focus.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ import (
)

var focusCmd = &cobra.Command{
Use: "focus [issue-id]",
Short: "Set the current working issue",
Use: "focus [issue-id]",
Short: "Pin an issue as the default for log, handoff, and close",
Long: `Set the focused issue so commands like 'td log' and 'td handoff' can be
run without an ID. Focus is cleared automatically when an issue moves to
review or closed.`,
GroupID: "session",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down
31 changes: 18 additions & 13 deletions cmd/handoff.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,28 @@ import (

var handoffCmd = &cobra.Command{
Use: "handoff <issue-id> [message]",
Short: "Capture structured working state",
Long: `Required before submitting for review. Captures git state automatically.

Accepts YAML-like format via stdin:
Short: "Capture working state so the next session can resume",
Long: `Record what's done, what's left, decisions made, and open questions.
Captures git state automatically. Run this before 'td review' so the reviewer
(or the next session) has full context.

Provide items via flags, stdin (-), file (@path), or a YAML-like block on
stdin with done/remaining/decisions/uncertain sections.

Examples:
td handoff td-abc1 --done "wired up oauth" --remaining "add tests"
td handoff td-abc1 --done @done.txt # one item per line from file
echo "fixed login" | td handoff td-abc1 --done -
td handoff td-abc1 <<EOF
done:
- Item completed
- Wired up oauth flow
remaining:
- Item to do
- Add integration tests
decisions:
- Decision made
- Use PKCE for native clients
uncertain:
- Question/uncertainty

Or use flags with values, stdin (-), or file (@path):
--done "item" Single item
--done @done.txt Items from file (one per line)
echo "item" | td handoff ID --done - Items from stdin`,
- Token refresh strategy
EOF`,
GroupID: "workflow",
Args: cobra.RangeArgs(0, 2),
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down
14 changes: 12 additions & 2 deletions cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,19 @@ import (
)

var listCmd = &cobra.Command{
Use: "list [filters]",
Use: "list [query]",
Aliases: []string{"ls"},
Short: "List issues matching given filters",
Short: "List issues, optionally filtered by flags or a TDQ query",
Long: `List issues. With no arguments, shows open/in-progress/blocked/in-review
issues (use --all to include closed and deferred). Combine flags for quick
filters, or pass a TDQ expression for full query power.

Examples:
td list # default view
td list --mine --status in_progress # your active work
td list --type bug --priority P1 # high-priority bugs
td list "status=open AND label=backend" # TDQ query
td list --epic td-epic1 # all tasks under an epic`,
GroupID: "core",
RunE: func(cmd *cobra.Command, args []string) error {
baseDir := getBaseDir()
Expand Down
26 changes: 11 additions & 15 deletions cmd/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,17 @@ var issueIDPattern = regexp.MustCompile(`^td-[0-9a-f]{6,8}$`)

var logCmd = &cobra.Command{
Use: "log [issue-id] <message>",
Short: "Append a log entry to the current issue",
Long: `Low-friction progress tracking during a session.

Syntax:
td log <message> # Log to focused issue
td log <issue-id> <message> # Log to specific issue
td log --issue <id> <message> # Log to specific issue (flag syntax)

Supports stdin input for multi-line messages or piped input:
echo "message" | td log
td log < notes.txt
td log <<EOF
Multi-line
log message
EOF`,
Short: "Record progress, decisions, or blockers on an issue",
Long: `Append a timestamped log entry. With no issue ID, logs to the focused
issue. Use type flags (--decision, --blocker, --hypothesis, --tried, --result)
to tag entries for later filtering.

Examples:
td log "fixed login redirect" # log to focused issue
td log td-abc1 "investigating timeout" # log to a specific issue
td log --decision "use websocket" # tag as a decision
echo "long note" | td log # read message from stdin
td log < notes.txt # read message from file`,
GroupID: "workflow",
Args: cobra.MaximumNArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down
38 changes: 21 additions & 17 deletions cmd/review.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,19 +190,21 @@ func isRoutineWorkflowLogMessage(message string) bool {
var reviewCmd = &cobra.Command{
Use: "review [issue-id...]",
Aliases: []string{"submit", "finish"},
Short: "Submit one or more issues for review",
Long: `Submits the issue(s) for review. If no handoff exists, a minimal one is
auto-created (consider using 'td handoff' for better documentation).
Short: "Submit issues for independent review",
Long: `Move issues to in_review and record this session as the requester.
If no handoff exists, a minimal one is auto-created — prefer running
'td handoff' first so the reviewer has real context.

The submitting session is recorded as 'review_requested_by_session' on the
issue. Under review_policy_mode=delegated, an active independent approval is
the close gate, so any session may close after a reviewer records approval.
Epics cascade automatically to all open/in_progress descendants, which do not
need individual handoffs.

For epics/parent issues, automatically cascades to all open/in_progress
descendants. Cascaded children don't require individual handoffs.
Under review_policy_mode=delegated, an active independent approval is the
close gate; any session may close once a reviewer records approval.

Supports bulk operations:
td review td-abc1 td-abc2 td-abc3 # Submit multiple issues for review`,
Examples:
td review td-abc1
td review td-abc1 td-abc2 td-abc3 # bulk submit
td review td-epic1 # cascades to all open descendants`,
GroupID: "workflow",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down Expand Up @@ -493,7 +495,7 @@ func rejectFollowupGuidance(issue *models.Issue) string {

var approveCmd = &cobra.Command{
Use: "approve [issue-id...]",
Short: "Approve and close one or more issues, or record a review",
Short: "Approve reviewed work (and close, unless --record-only)",
Long: `Approves the issue(s). You cannot review your own implementation, but you
can close after an independent review has been recorded. 'td approve' operates
in one of three modes:
Expand Down Expand Up @@ -1085,12 +1087,14 @@ To surface issues reviewed by a sub-agent that you can close, use

var rejectCmd = &cobra.Command{
Use: "reject [issue-id...]",
Short: "Reject and return to open",
Long: `Rejects the issue(s) and returns them to open status so they can be
picked up again by td next.
Short: "Reject reviewed work and return it to open",
Long: `Send issues back to open so they can be picked up again. Supersedes any
active approval review and clears the implementer/reviewer/requester stamps so
a fresh review cycle starts clean.

Supports bulk operations:
td reject td-abc1 td-abc2 # Reject multiple issues`,
Examples:
td reject td-abc1 -m "tests are flaky, please rerun"
td reject td-abc1 td-abc2 # bulk reject`,
GroupID: "workflow",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down Expand Up @@ -1227,7 +1231,7 @@ Supports bulk operations:
var closeCmd = &cobra.Command{
Use: "close [issue-id...]",
Aliases: []string{"done", "complete"},
Short: "Admin close: duplicates, won't-fix, cleanup (NOT for reviewed work)",
Short: "Admin close for duplicates, won't-fix, or cleanup",
Long: `Closes the issue(s) directly. Admin-only scope: duplicates, won't-fix,
or cleanup of never-implemented issues.

Expand Down
8 changes: 5 additions & 3 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ func SetVersion(v string) {

var rootCmd = &cobra.Command{
Use: "td",
Short: "Local task and session management CLI",
Long: `td - A minimalist local task and session management CLI designed for AI-assisted development workflows.
Short: "Track tasks and hand off work between AI sessions",
Long: `td is a local-first task tracker built for AI-assisted development.

Optimized for session continuity—capturing working state so new context windows can resume where previous ones stopped.`,
It captures progress, decisions, and git state so a new context window can
pick up exactly where the previous one stopped. Run 'td usage -q' for a
condensed command reference, or 'td next' to see what to work on.`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
cmdStartTime = time.Now()
runGatedSyncStartupHook(cmd)
Expand Down
10 changes: 6 additions & 4 deletions cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ import (
var startCmd = &cobra.Command{
Use: "start [issue-id...]",
Aliases: []string{"begin"},
Short: "Begin work on issue(s)",
Long: `Records current session as implementer and captures git state.
Short: "Begin work on one or more issues",
Long: `Mark issues as in-progress, claim them for this session, and snapshot
git HEAD so diffs at handoff time are accurate.

Examples:
td start td-abc1 # Start single issue
td start td-abc1 td-abc2 td-abc3 # Start multiple issues`,
td start td-abc1 # Start a single issue
td start td-abc1 td-abc2 td-abc3 # Start several at once
td start td-abc1 --force # Override blocked status`,
GroupID: "workflow",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down