Conversation
Adds a --json flag to `tsk list` that emits tasks as a JSON array on stdout, making the command scriptable and LLM-friendly without the truncation imposed by the Rich table view. Each task object includes the short numeric display ID (id), the stable UUID, and all frontmatter fields. Dates are ISO 8601. Composes with all existing filters. Empty results return []. Merge-conflict warnings are redirected to stderr in JSON mode so stdout stays valid JSON. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code Review: PR #16 —
|
| Area | Assessment |
|---|---|
| Feature correctness | ✅ Works as described |
| Code style | ✅ Clean, mostly follows conventions |
| Redundant code | display_id if display_id is not None else None |
| Output mechanism | click.echo(json.dumps(...)) over sys.stdout |
| Stale ID edge case | null IDs silently on filtered views without a populated cache |
| Test coverage | ❌ No new tests for the --json flag |
The feature is well-motivated and the implementation is solid. Addressing the click.echo vs sys.stdout point and adding tests for the new flag would bring this to a clean merge. The redundant conditional and the null ID edge case are lower priority but worth fixing before the v0.11.0 tag.
🤖 Reviewed with Claude Code
There was a problem hiding this comment.
Pull request overview
Adds machine-readable JSON output for the tsk list CLI command to support scripting/LLM use cases, and cuts a new minor release.
Changes:
- Add
--jsonflag totsk listto emit tasks as a JSON array to stdout (with conflict warnings redirected to stderr). - Introduce task-to-JSON serialization helper and ensure ID cache rebalance occurs before JSON serialization for unfiltered views.
- Bump version to
0.11.0and document the feature inCHANGELOG.md.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/taskrepo/cli/commands/list.py |
Implements --json output mode, JSON serialization, and stderr conflict warnings in JSON mode. |
src/taskrepo/__version__.py |
Version bump to 0.11.0. |
CHANGELOG.md |
Adds 0.11.0 entry documenting the new JSON output feature. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def _task_to_dict(task) -> dict: | ||
| """Serialize a Task to a JSON-compatible dict. | ||
|
|
||
| The ``id`` field is the short numeric display ID (same as the table view); | ||
| ``uuid`` is the stable underlying identifier. All dates are ISO 8601. | ||
| """ | ||
| display_id = get_display_id_from_uuid(task.id) | ||
| return { | ||
| "id": display_id if display_id is not None else None, |
| if json_output: | ||
| payload = [_task_to_dict(t) for t in sorted_tasks] | ||
| json.dump(payload, sys.stdout, indent=2, default=str) | ||
| sys.stdout.write("\n") |
Addresses review feedback on PR #16: - Load the ID cache once per invocation instead of per-task, eliminating O(N²) scans and N redundant file reads for large task lists. - Switch to click.echo for JSON output so Click's test-capture layer and stdout redirection work correctly. - Emit a stderr hint when the ID cache is empty on a filtered view, so null id values aren't silent. - Drop a redundant conditional on the id field. - Add 8 unit tests covering task-to-dict serialization, cache loading (missing/valid/malformed), and a regression guard against O(N²) reads. Keeps the JSON schema stable (int | null id, uuid always present). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix: --json performance and output correctness (v0.11.1) Addresses review feedback on PR #16: - Load the ID cache once per invocation instead of per-task, eliminating O(N²) scans and N redundant file reads for large task lists. - Switch to click.echo for JSON output so Click's test-capture layer and stdout redirection work correctly. - Emit a stderr hint when the ID cache is empty on a filtered view, so null id values aren't silent. - Drop a redundant conditional on the id field. - Add 8 unit tests covering task-to-dict serialization, cache loading (missing/valid/malformed), and a regression guard against O(N²) reads. Keeps the JSON schema stable (int | null id, uuid always present). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * address review feedback on PR #17 - Harden _load_uuid_to_display_id: reject non-dict top-level, filter entries missing `uuid`, catch OSError/TypeError (Copilot comment). - Add one-line comment clarifying the stderr-hint ordering invariant (claude[bot] suggestion). - Fix inaccurate comment about Task.__post_init__ in the test helper (Copilot comment). - Add CLI integration tests via CliRunner covering the exact regression path this release fixes: --json output end-to-end, empty result → [], and stderr hint on filtered empty-cache runs (claude[bot] suggestion). - Add unit test for non-dict top-level cache files. Deferred as follow-up: the save-then-load round-trip on unfiltered runs (noted by claude[bot], non-blocking). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
--jsonflag ontsk listemits tasks as a JSON array on stdout for scripting and LLM consumption (no Rich-table truncation).id, stableuuid, and all frontmatter fields (title, status, priority, repo, project, assignees, tags, links, due, created, modified, depends, parent, description). Dates are ISO 8601.-s,--priority,-r,-p,-a,-t,--archived). Empty results return[]. Merge-conflict warnings are redirected to stderr in JSON mode so stdout stays valid JSON.Bumps version to
0.11.0(minor — new feature, backwards compatible).Test plan
uv run pytest tests/ -q)uv run ruff checkcleantsk list --json -s pendingreturns valid JSON parseable byjson.load/jqidvalues in JSON match the table view[]v0.11.0→ PyPI publish, thenjust release taskrepoin../homebrew-formulas🤖 Generated with Claude Code