From ae5987775cdc913d26476483ea07148c8129ef87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jarkko=20Syrja=CC=88la=CC=88?= Date: Fri, 10 Jul 2026 20:29:58 +0300 Subject: [PATCH 1/3] Fix terminal UI/UX consistency audit (#7) Address all findings from the terminal output audit: High - H1: unify error rendering. Commander parse errors now route through formatCliError ([Error] + prelude) via exitOverride/configureOutput instead of a lowercase `error:` + usage dump; worker errors gain the [Error] label. - H2: wide-character-safe `list` table. New src/util/textWidth.ts measures display width (east-asian-width aware), truncates by code point so surrogate-pair emoji aren't split, and sanitizes control chars/newlines so a task stays on one row. - H3: `list --verbose` now includes the Due in countdown. Medium - M1: consistent empty-state labeling ([Info] No pending jobs. / No jobs.). - M2: dry-run lists commands under `Commands:` (not `Tasks:`) and --dry-run --json now includes a `commands` array. - M3: parallel cancel states share one phrasing ("already ; nothing to cancel."). - M4: near-miss subcommands (e.g. `lst`) suggest the real command. - M5: reconcile help vs README copy/punctuation; restore "local" in the program description. Low - L1: `[Dry-run]` single-token label. - L2: sentence-case table headers, aligned with verbose labels. - L3: add a task/job/agent glossary to the README. - L4: group large second-counts with separators (toLocaleString). - L5: imminent schedules render "to run now" instead of "0 seconds (0 seconds)". - L6: message preview keeps a first-task floor so a huge task count can't collapse it to a bare ellipsis. --- README.md | 42 ++++++++++---- src/cli.ts | 94 ++++++++++++++++++++++++------ src/commands/cancel.ts | 46 +++++---------- src/commands/list.ts | 61 +++++++++++--------- src/commands/schedule.ts | 33 +++++++---- src/errors.ts | 5 +- src/util/textWidth.ts | 82 ++++++++++++++++++++++++++ tests/errors.test.ts | 4 +- tests/integration.test.ts | 36 ++++++++++++ tests/list.test.ts | 118 ++++++++++++++++++++++++++++++++++++++ tests/reconcile.test.ts | 2 +- tests/schedule.test.ts | 47 ++++++++++++++- 12 files changed, 466 insertions(+), 104 deletions(-) create mode 100644 src/util/textWidth.ts diff --git a/README.md b/README.md index f7c0434..f4d3818 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,14 @@ cc-timer "2h10m" "Explore if this is this the real life? " - Keep pending jobs in a JSON state file so they can be listed or canceled later. - Work the same way on macOS, Linux, and Windows without shell-specific tricks. +## Glossary + +`cc-timer` uses three related terms consistently: + +- **Task** — one unit of work you provide (a positional argument, a `--task`, or a line from `--file`). Each task becomes a single `claude --bg ` invocation. +- **Job** — the scheduled record that groups one or more tasks under a single dispatch time. Jobs are what you `list` and `cancel`; each has an id like `ct_9f2aXY`. +- **Agent** — the Claude Code background agent a task turns into once the job is dispatched. After dispatch, agents appear in `claude agents` and are managed there, not by `cc-timer`. + ## Install Install globally from npm: @@ -53,7 +61,7 @@ cc-timer "45m" "Investigate this landslide, why no escape from reality" ``` ```text -[Success] Scheduled 1 task to run in 45 minutes (2700 seconds). +[Success] Scheduled 1 task to run in 45 minutes (2,700 seconds). Dispatch time: 2026-05-18 15:42:00 local time Tasks: - Investigate this landslide, why no escape from reality @@ -174,6 +182,18 @@ cc-timer "2h" \ --dry-run ``` +```text +[Dry-run] Would schedule 2 tasks to run in 2 hours (7,200 seconds). +Dispatch time: 2026-05-18 17:42:00 local time +Commands: +- claude --bg "Ping mama, ooh (any way the wind blows)" +- claude --bg "Respawn I don't wanna die" + +No job was created. +``` + +The dry run prints the exact shell-quoted `claude` invocations under `Commands:`. Add `--json` to get the same preview as a `commands` array. + ## Listing pending jobs ```bash @@ -214,16 +234,16 @@ Cancellation marks the job state before terminating the worker, so a wake-up tha `cc-timer [delay] [tasks...]` — schedule new agents. -| Option | Description | -| ----------------------------- | ---------------------------------------------------------------- | -| `--task ` | Add one task. Repeatable. | -| `--file ` | Read tasks from a text file, one per line. | -| `--at