clawforge-cli 1.5.4__tar.gz → 1.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/CHANGELOG.md +29 -0
  2. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/Formula/clawforge.rb +3 -1
  3. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/PKG-INFO +1 -1
  4. clawforge_cli-1.6.0/VERSION +1 -0
  5. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/clawforge +2 -0
  6. clawforge_cli-1.6.0/bin/quick-run.sh +204 -0
  7. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/spawn-agent.sh +6 -2
  8. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/package.json +1 -1
  9. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/pyproject.toml +1 -1
  10. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/run-all-tests.sh +1 -1
  11. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-dx.sh +3 -3
  12. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-observability.sh +1 -1
  13. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-power.sh +1 -1
  14. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-practical.sh +1 -1
  15. clawforge_cli-1.6.0/tests/test-quick-run.sh +105 -0
  16. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-reliability.sh +1 -1
  17. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-web.sh +1 -1
  18. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tui/agent.go +3 -0
  19. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tui/dashboard.go +8 -4
  20. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tui/keybindings.go +83 -11
  21. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tui/model.go +2 -1
  22. clawforge_cli-1.5.4/VERSION +0 -1
  23. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/.github/workflows/ci.yml +0 -0
  24. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/.github/workflows/publish-npm.yml +0 -0
  25. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/.github/workflows/publish-pypi.yml +0 -0
  26. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/.github/workflows/update-homebrew.yml +0 -0
  27. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/.github/workflows/version-sync.yml +0 -0
  28. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/.gitignore +0 -0
  29. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/LICENSE +0 -0
  30. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/PRD-v05.md +0 -0
  31. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/PRD-v06.md +0 -0
  32. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/PRD-v07.md +0 -0
  33. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/README.md +0 -0
  34. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/SKILL.md +0 -0
  35. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/attach.sh +0 -0
  36. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/check-agents.sh +0 -0
  37. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/clawforge-web +0 -0
  38. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/clean.sh +0 -0
  39. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/completions.sh +0 -0
  40. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/config.sh +0 -0
  41. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/conflicts.sh +0 -0
  42. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/cost.sh +0 -0
  43. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/dashboard.sh +0 -0
  44. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/deps.sh +0 -0
  45. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/diff.sh +0 -0
  46. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/doctor.sh +0 -0
  47. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/eval.sh +0 -0
  48. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/export.sh +0 -0
  49. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/history.sh +0 -0
  50. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/init.sh +0 -0
  51. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/learn.sh +0 -0
  52. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/logs.sh +0 -0
  53. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/memory.sh +0 -0
  54. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/merge-helper.sh +0 -0
  55. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/multi-review.sh +0 -0
  56. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/notify.sh +0 -0
  57. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/on-complete.sh +0 -0
  58. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/parse-cost.sh +0 -0
  59. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/pr.sh +0 -0
  60. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/profile.sh +0 -0
  61. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/replay.sh +0 -0
  62. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/resume.sh +0 -0
  63. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/review-mode.sh +0 -0
  64. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/review-pr.sh +0 -0
  65. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/routing.sh +0 -0
  66. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/scope-task.sh +0 -0
  67. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/sprint.sh +0 -0
  68. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/steer.sh +0 -0
  69. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/stop.sh +0 -0
  70. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/summary.sh +0 -0
  71. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/swarm.sh +0 -0
  72. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/templates.sh +0 -0
  73. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/bin/web.sh +0 -0
  74. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/clawforge/__init__.py +0 -0
  75. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/clawforge/cli.py +0 -0
  76. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/completions/_clawforge +0 -0
  77. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/completions/clawforge.bash +0 -0
  78. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/completions/clawforge.fish +0 -0
  79. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/config/defaults.json +0 -0
  80. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/config/prompt-templates/default.md +0 -0
  81. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/config/routing-defaults.json +0 -0
  82. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/IMPLEMENTATION-v04.md +0 -0
  83. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/PRD-v04.md +0 -0
  84. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/PUBLISHING-CHECKLIST.md +0 -0
  85. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/README.md +0 -0
  86. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/RELEASE.md +0 -0
  87. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/architecture.md +0 -0
  88. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/command-reference.md +0 -0
  89. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/configuration.md +0 -0
  90. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/dashboard.md +0 -0
  91. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/evaluation.md +0 -0
  92. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/faq.md +0 -0
  93. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/fleet-ops.md +0 -0
  94. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/getting-started.md +0 -0
  95. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/scenarios.md +0 -0
  96. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/troubleshooting.md +0 -0
  97. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/docs/workflow-modes.md +0 -0
  98. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/evals/run-log.example.jsonl +0 -0
  99. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/evals/run-log.schema.json +0 -0
  100. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/evals/scorecard.md +0 -0
  101. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/install.sh +0 -0
  102. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/lib/common.sh +0 -0
  103. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/lib/templates/bugfix.json +0 -0
  104. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/lib/templates/migration.json +0 -0
  105. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/lib/templates/refactor.json +0 -0
  106. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/lib/templates/security-audit.json +0 -0
  107. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/lib/templates/test-coverage.json +0 -0
  108. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/registry/conflicts.jsonl +0 -0
  109. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/registry/costs.jsonl +0 -0
  110. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-ci-loop.sh +0 -0
  111. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-clean.sh +0 -0
  112. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-cli.sh +0 -0
  113. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-conflicts.sh +0 -0
  114. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-cost.sh +0 -0
  115. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-dashboard.sh +0 -0
  116. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-deps.sh +0 -0
  117. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-eval.sh +0 -0
  118. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-foundation.sh +0 -0
  119. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-history.sh +0 -0
  120. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-init.sh +0 -0
  121. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-learn.sh +0 -0
  122. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-management.sh +0 -0
  123. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-memory.sh +0 -0
  124. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-merge.sh +0 -0
  125. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-modes.sh +0 -0
  126. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-multi-repo.sh +0 -0
  127. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-notify.sh +0 -0
  128. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-openclaw.sh +0 -0
  129. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-registry.sh +0 -0
  130. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-review.sh +0 -0
  131. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-routing.sh +0 -0
  132. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-scope.sh +0 -0
  133. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-spawn.sh +0 -0
  134. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-templates.sh +0 -0
  135. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-tui.sh +0 -0
  136. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tests/test-watch.sh +0 -0
  137. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tui/PRD.md +0 -0
  138. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tui/animation.go +0 -0
  139. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tui/filter.go +0 -0
  140. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tui/go.mod +0 -0
  141. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tui/go.sum +0 -0
  142. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tui/main.go +0 -0
  143. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tui/steer.go +0 -0
  144. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/tui/styles.go +0 -0
  145. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/web/go.mod +0 -0
  146. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/web/index.html +0 -0
  147. {clawforge_cli-1.5.4 → clawforge_cli-1.6.0}/web/main.go +0 -0
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.6.0 — quick-run: Zero-Overhead Direct Execution
4
+
5
+ ### Added
6
+ - New `clawforge quick-run "<task>"` command
7
+ - Runs agent directly in current directory (or `--dir <path>`)
8
+ - No worktree, no branch, no tmux — streams output to terminal
9
+ - Flags: `--agent`, `--model`, `--save`, `--budget`, `--no-track`, `--dir`, `--dry-run`
10
+ - Output teed to log file (`~/.clawforge/registry/logs/`) and registered in task history
11
+ - Appears in `clawforge status` unless `--no-track` used
12
+ - 34 test suites (new: `test-quick-run`)
13
+
14
+ ### Use case
15
+ For quick questions, codebase exploration, or small fixes that don't need a branch/PR workflow.
16
+ Use `clawforge sprint` when you need a branch, worktree, CI loop, and PR.
17
+
18
+ ## v1.5.5 — TUI Observability: Logs + Diff Keys
19
+
20
+ ### Added
21
+ - `l` key in TUI dashboard: show last 50 lines of agent log in preview pane (reads log file; falls back to tmux capture for live sessions)
22
+ - `d` key in TUI dashboard: show `git diff --stat HEAD` for selected agent's worktree
23
+ - `Enter` now falls back to showing log file in preview when session is gone (instead of silent no-op)
24
+ - Agent log files auto-captured to `~/.clawforge/registry/logs/<branch>.log` via `tee` on spawn
25
+ - `log_path` stored in registry and surfaced to TUI
26
+ - `Esc` closes preview/log panel
27
+ - Navigation clears stale static preview content
28
+
29
+ ### Fixed
30
+ - `Enter` on finished/dead sessions silently did nothing — now shows log output
31
+
3
32
  ## v1.5.4 — TUI Attach + Agent Session Persistence
4
33
 
5
34
  ### Fixed
@@ -1,7 +1,9 @@
1
1
  class Clawforge < Formula
2
2
  desc "Multi-mode coding workflow CLI for orchestrating AI coding agents"
3
3
  homepage "https://github.com/cyperx84/clawforge"
4
- url "https://github.com/cyperx84/clawforge/archive/refs/tags/v1.5.3.tar.gz"
4
+ url "https://github.com/cyperx84/clawforge/archive/refs/tags/v1.5.5.tar.gz"
5
+ sha256 "b2d483778e83b9007b22bb4c421c90b71e7343cc4f244d116b99eaa2810dc433"
6
+ sha256 "549b3ebf95c953cd4f366b5a251786c994726761c9d4ed6255b996b6458cf695"
5
7
  sha256 "2730fca0066fda9d3c864802c4346ab7c39d0daee39a254cc5cebd2694d4a1db"
6
8
  sha256 "a026cb0df5b7c3efae439a9ca912e728843deb56c70441591c9064f81a1041ae"
7
9
  sha256 "27cca187828366d138dbde81f99f313e065c656be7073452ccc016eb5dba16db"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clawforge-cli
3
- Version: 1.5.4
3
+ Version: 1.6.0
4
4
  Summary: Multi-mode coding workflow CLI for orchestrating AI coding agents
5
5
  Project-URL: Homepage, https://github.com/cyperx84/clawforge
6
6
  Project-URL: Repository, https://github.com/cyperx84/clawforge
@@ -0,0 +1 @@
1
+ 1.6.0
@@ -43,6 +43,7 @@ Multi-mode coding workflow CLI — from quick patches to parallel agent orchestr
43
43
  Usage: clawforge <command> [options]
44
44
 
45
45
  Workflow Modes:
46
+ quick-run Direct agent execution in cwd (no branch/worktree overhead)
46
47
  sprint Single agent, full dev cycle (the workhorse)
47
48
  review Quality gate on an existing PR (analysis only)
48
49
  swarm Parallel multi-agent orchestration
@@ -260,6 +261,7 @@ doctor) exec "${BIN_DIR}/doctor.sh" "$@" ;;
260
261
  spawn) exec "${BIN_DIR}/spawn-agent.sh" "$@" ;;
261
262
  notify) exec "${BIN_DIR}/notify.sh" "$@" ;;
262
263
  merge) exec "${BIN_DIR}/merge-helper.sh" "$@" ;;
264
+ quick-run) exec "${BIN_DIR}/quick-run.sh" "$@" ;;
263
265
  run) run_combined "$@" ;;
264
266
 
265
267
  # Meta
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env bash
2
+ # quick-run.sh — Zero-overhead direct agent execution in current directory.
3
+ # No worktree, no branch, no tmux. Just runs the agent and streams output.
4
+ set -euo pipefail
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
7
+ source "${SCRIPT_DIR}/../lib/common.sh"
8
+
9
+ usage() {
10
+ cat <<EOF
11
+ Usage: clawforge quick-run "<task>" [options]
12
+
13
+ Run an agent directly in the current (or specified) directory.
14
+ No worktree, no branch, no tmux overhead — just streams output to your terminal.
15
+
16
+ Arguments:
17
+ <task> Task description (required)
18
+
19
+ Options:
20
+ --dir <path> Directory to run in (default: current working directory)
21
+ --agent <name> Agent to use: claude or codex (default: auto-detect)
22
+ --model <model> Model override
23
+ --no-track Don't register in task registry
24
+ --save <file> Save output to file (in addition to stdout)
25
+ --budget <usd> Max spend cap (passed to agent if supported)
26
+ --dry-run Show what would run without executing
27
+ --help Show this help
28
+
29
+ Examples:
30
+ clawforge quick-run "Explain what this codebase does"
31
+ clawforge quick-run "Add docstrings to all exported functions" --dir ~/github/mylib
32
+ clawforge quick-run "Fix the failing test" --agent codex --model gpt-5.3-codex
33
+ clawforge quick-run "Summarize recent git changes" --no-track
34
+ clawforge quick-run "Refactor auth.ts" --save /tmp/agent-output.log
35
+
36
+ Notes:
37
+ - Output streams directly to your terminal (and optionally a file).
38
+ - The agent runs in the target directory with full file access.
39
+ - Results are tracked in the registry (use --no-track to skip).
40
+ - For tasks requiring a branch/PR, use: clawforge sprint "<task>"
41
+ EOF
42
+ }
43
+
44
+ # ── Parse args ─────────────────────────────────────────────────────────
45
+ TASK="" DIR="" AGENT="" MODEL="" NO_TRACK=false SAVE_PATH="" BUDGET="" DRY_RUN=false
46
+
47
+ while [[ $# -gt 0 ]]; do
48
+ case "$1" in
49
+ --dir) DIR="$2"; shift 2 ;;
50
+ --agent) AGENT="$2"; shift 2 ;;
51
+ --model) MODEL="$2"; shift 2 ;;
52
+ --no-track) NO_TRACK=true; shift ;;
53
+ --save) SAVE_PATH="$2"; shift 2 ;;
54
+ --budget) BUDGET="$2"; shift 2 ;;
55
+ --dry-run) DRY_RUN=true; shift ;;
56
+ --help|-h) usage; exit 0 ;;
57
+ -*) log_error "Unknown option: $1"; usage; exit 1 ;;
58
+ *)
59
+ if [[ -z "$TASK" ]]; then
60
+ TASK="$1"; shift
61
+ else
62
+ log_error "Unexpected argument: $1"; usage; exit 1
63
+ fi
64
+ ;;
65
+ esac
66
+ done
67
+
68
+ [[ -z "$TASK" ]] && { log_error "Task description is required"; usage; exit 1; }
69
+
70
+ # ── Resolve directory ──────────────────────────────────────────────────
71
+ if [[ -n "$DIR" ]]; then
72
+ [[ -d "$DIR" ]] || { log_error "Directory not found: $DIR"; exit 1; }
73
+ TARGET_DIR="$(cd "$DIR" && pwd)"
74
+ else
75
+ TARGET_DIR="$(pwd)"
76
+ fi
77
+
78
+ # ── Resolve agent ──────────────────────────────────────────────────────
79
+ RESOLVED_AGENT=$(detect_agent "${AGENT:-}")
80
+ [[ -z "$RESOLVED_AGENT" ]] && { log_error "No agent (claude/codex) found in PATH"; exit 1; }
81
+
82
+ # ── Resolve model ──────────────────────────────────────────────────────
83
+ if [[ -z "$MODEL" ]]; then
84
+ if [[ "$RESOLVED_AGENT" == "claude" ]]; then
85
+ MODEL=$(config_get default_model_claude "claude-sonnet-4-5")
86
+ else
87
+ MODEL=$(config_get default_model_codex "gpt-5.3-codex")
88
+ fi
89
+ fi
90
+
91
+ # ── Build task ID ──────────────────────────────────────────────────────
92
+ SAFE_SLUG=$(slugify_task "$TASK" 32)
93
+ TASK_ID="qr-${SAFE_SLUG}"
94
+ NOW=$(epoch_ms)
95
+
96
+ # ── Dry-run ────────────────────────────────────────────────────────────
97
+ if $DRY_RUN; then
98
+ echo "──────────────────────────────────────────"
99
+ echo " clawforge quick-run [dry-run]"
100
+ echo "──────────────────────────────────────────"
101
+ echo " task: $TASK"
102
+ echo " dir: $TARGET_DIR"
103
+ echo " agent: $RESOLVED_AGENT"
104
+ echo " model: $MODEL"
105
+ echo " track: $( $NO_TRACK && echo no || echo yes)"
106
+ [[ -n "$SAVE_PATH" ]] && echo " Save to: $SAVE_PATH"
107
+ [[ -n "$BUDGET" ]] && echo " Budget: \$$BUDGET"
108
+ echo "──────────────────────────────────────────"
109
+ exit 0
110
+ fi
111
+
112
+ # ── Register task ──────────────────────────────────────────────────────
113
+ SHORT_ID=""
114
+ if ! $NO_TRACK; then
115
+ _ensure_registry
116
+ TASK_JSON=$(jq -n \
117
+ --arg id "$TASK_ID" \
118
+ --arg agent "$RESOLVED_AGENT" \
119
+ --arg model "$MODEL" \
120
+ --arg desc "$TASK" \
121
+ --arg dir "$TARGET_DIR" \
122
+ --argjson started "$NOW" \
123
+ '{
124
+ id: $id,
125
+ agent: $agent,
126
+ model: $model,
127
+ description: $desc,
128
+ repo: $dir,
129
+ worktree: $dir,
130
+ branch: "",
131
+ mode: "quick-run",
132
+ status: "running",
133
+ started_at: $started,
134
+ files_touched: [],
135
+ ci_retries: 0
136
+ }')
137
+ registry_add "$TASK_JSON"
138
+ SHORT_ID=$(registry_get "$TASK_ID" | jq -r '.short_id // empty')
139
+ fi
140
+
141
+ # ── Set up output capture ──────────────────────────────────────────────
142
+ LOG_DIR="${CLAWFORGE_DIR}/registry/logs"
143
+ mkdir -p "$LOG_DIR"
144
+ LOG_FILE="${LOG_DIR}/${TASK_ID}.log"
145
+
146
+ if ! $NO_TRACK; then
147
+ registry_update "$TASK_ID" "log_path" "\"$LOG_FILE\""
148
+ fi
149
+
150
+ # ── Build agent command ────────────────────────────────────────────────
151
+ ESCAPED_TASK=$(printf '%s' "$TASK" | sed "s/'/'\\''/g")
152
+
153
+ if [[ "$RESOLVED_AGENT" == "claude" ]]; then
154
+ BUDGET_FLAG=""
155
+ [[ -n "$BUDGET" ]] && BUDGET_FLAG="--max-budget-usd $BUDGET"
156
+ AGENT_CMD=(claude --model "$MODEL" --dangerously-skip-permissions -p "$TASK" $BUDGET_FLAG)
157
+ elif [[ "$RESOLVED_AGENT" == "codex" ]]; then
158
+ AGENT_CMD=(codex --model "$MODEL" --dangerously-bypass-approvals-and-sandbox "$TASK")
159
+ fi
160
+
161
+ # ── Run ────────────────────────────────────────────────────────────────
162
+ ID_LABEL=""
163
+ [[ -n "$SHORT_ID" ]] && ID_LABEL=" [#${SHORT_ID}]"
164
+
165
+ echo "──────────────────────────────────────────"
166
+ echo " ⚡ clawforge quick-run${ID_LABEL}"
167
+ echo "──────────────────────────────────────────"
168
+ echo " Task: $TASK"
169
+ echo " Dir: $TARGET_DIR"
170
+ echo " Agent: $RESOLVED_AGENT ($MODEL)"
171
+ echo "──────────────────────────────────────────"
172
+ echo ""
173
+
174
+ EXIT_CODE=0
175
+ START_MS=$NOW
176
+
177
+ if [[ -n "$SAVE_PATH" ]]; then
178
+ (cd "$TARGET_DIR" && "${AGENT_CMD[@]}" 2>&1) | tee "$LOG_FILE" "$SAVE_PATH" || EXIT_CODE=$?
179
+ else
180
+ (cd "$TARGET_DIR" && "${AGENT_CMD[@]}" 2>&1) | tee "$LOG_FILE" || EXIT_CODE=$?
181
+ fi
182
+
183
+ END_MS=$(epoch_ms)
184
+ DURATION_S=$(( (END_MS - START_MS) / 1000 ))
185
+
186
+ echo ""
187
+ echo "──────────────────────────────────────────"
188
+ if [[ $EXIT_CODE -eq 0 ]]; then
189
+ echo " ✅ Done in ${DURATION_S}s"
190
+ else
191
+ echo " ❌ Agent exited with code $EXIT_CODE (${DURATION_S}s)"
192
+ fi
193
+ [[ -n "$SAVE_PATH" ]] && echo " 📄 Saved to: $SAVE_PATH"
194
+ echo "──────────────────────────────────────────"
195
+
196
+ # ── Update registry ────────────────────────────────────────────────────
197
+ if ! $NO_TRACK; then
198
+ FINAL_STATUS="done"
199
+ [[ $EXIT_CODE -ne 0 ]] && FINAL_STATUS="failed"
200
+ registry_update "$TASK_ID" "status" "\"$FINAL_STATUS\""
201
+ registry_update "$TASK_ID" "finished_at" "$(epoch_ms)"
202
+ fi
203
+
204
+ exit $EXIT_CODE
@@ -114,6 +114,8 @@ else
114
114
  fi
115
115
 
116
116
  TMUX_SESSION="agent-${SAFE_BRANCH}"
117
+ LOGFILE="${CLAWFORGE_DIR}/registry/logs/${SAFE_BRANCH}.log"
118
+ mkdir -p "$(dirname "$LOGFILE")"
117
119
  MAX_RETRIES=$(config_get max_retries 3)
118
120
 
119
121
  log_info "Spawning agent: $RESOLVED_AGENT ($MODEL)"
@@ -183,6 +185,7 @@ TASK_JSON=$(jq -n \
183
185
  --arg desc "$TASK" \
184
186
  --arg repo "$REPO_ABS" \
185
187
  --arg wt "$WORKTREE_DIR" \
188
+ --arg log "$LOGFILE" \
186
189
  --arg branch "$BRANCH" \
187
190
  --argjson started "$NOW" \
188
191
  --argjson maxRetries "$MAX_RETRIES" \
@@ -194,6 +197,7 @@ TASK_JSON=$(jq -n \
194
197
  description: $desc,
195
198
  repo: $repo,
196
199
  worktree: $wt,
200
+ log_path: $log,
197
201
  branch: $branch,
198
202
  startedAt: $started,
199
203
  status: "spawned",
@@ -223,9 +227,9 @@ tmux kill-session -t "$TMUX_SESSION" 2>/dev/null || true
223
227
  # Build agent command — interactive mode so tmux attach works
224
228
  ESCAPED_PROMPT=$(echo "$FULL_PROMPT" | sed 's/"/\\"/g')
225
229
  if [[ "$RESOLVED_AGENT" == "claude" ]]; then
226
- AGENT_CMD="claude --model ${MODEL} --dangerously-skip-permissions --verbose -p \"${ESCAPED_PROMPT}\"; echo; echo \"[ClawForge] Agent finished. Press Enter to close.\"; read"
230
+ AGENT_CMD="claude --model ${MODEL} --dangerously-skip-permissions --verbose -p \"${ESCAPED_PROMPT}\" 2>&1 | tee \"${LOGFILE}\"; echo; echo \"[ClawForge] Agent finished. Press Enter to close.\"; read"
227
231
  elif [[ "$RESOLVED_AGENT" == "codex" ]]; then
228
- AGENT_CMD="codex --model ${MODEL} --dangerously-bypass-approvals-and-sandbox \"${ESCAPED_PROMPT}\"; echo; echo \"[ClawForge] Agent finished. Press Enter to close.\"; read"
232
+ AGENT_CMD="codex --model ${MODEL} --dangerously-bypass-approvals-and-sandbox \"${ESCAPED_PROMPT}\" 2>&1 | tee \"${LOGFILE}\"; echo; echo \"[ClawForge] Agent finished. Press Enter to close.\"; read"
229
233
  fi
230
234
 
231
235
  # Create tmux session and launch
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyperx/clawforge",
3
- "version": "1.5.4",
3
+ "version": "1.6.0",
4
4
  "description": "Multi-mode coding workflow CLI for orchestrating AI coding agents",
5
5
  "bin": {
6
6
  "@cyperx/clawforge": "./bin/clawforge"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "clawforge-cli"
3
- version = "1.5.4"
3
+ version = "1.6.0"
4
4
  description = "Multi-mode coding workflow CLI for orchestrating AI coding agents"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -11,7 +11,7 @@ echo ""
11
11
 
12
12
  TOTAL_PASS=0
13
13
  TOTAL_FAIL=0
14
- TESTS=(test-cli test-registry test-spawn test-watch test-review test-scope test-notify test-merge test-clean test-learn test-foundation test-modes test-management test-dashboard test-tui test-cost test-templates test-conflicts test-ci-loop test-openclaw test-multi-repo test-routing test-memory test-init test-history test-eval test-reliability test-observability test-practical test-power test-dx test-web test-deps)
14
+ TESTS=(test-cli test-registry test-spawn test-watch test-review test-scope test-notify test-merge test-clean test-learn test-foundation test-modes test-management test-dashboard test-tui test-cost test-templates test-conflicts test-ci-loop test-openclaw test-multi-repo test-routing test-memory test-init test-history test-eval test-reliability test-observability test-practical test-power test-dx test-web test-deps test-quick-run)
15
15
 
16
16
  for test in "${TESTS[@]}"; do
17
17
  echo "────────────────────────────────────────"
@@ -134,10 +134,10 @@ assert_contains "help shows Developer Experience" "Developer Experience" "$cli_h
134
134
  # Test 11: version
135
135
  echo "Test 11: version"
136
136
  version=$(cat "${SCRIPT_DIR}/../VERSION")
137
- if [[ "$version" == "1.5.4" ]]; then
138
- echo " ✅ version is 1.5.4"; PASS=$((PASS+1))
137
+ if [[ "$version" == "1.6.0" ]]; then
138
+ echo " ✅ version is 1.6.0"; PASS=$((PASS+1))
139
139
  else
140
- echo " ❌ version is $version, expected 1.5.4"; FAIL=$((FAIL+1))
140
+ echo " ❌ version is $version, expected 1.6.0"; FAIL=$((FAIL+1))
141
141
  fi
142
142
 
143
143
  echo ""
@@ -77,7 +77,7 @@ assert_contains "dashboard help shows p key" "preview" "$tui_help"
77
77
  # Test 7: version
78
78
  echo "Test 7: version"
79
79
  version=$(cat "${SCRIPT_DIR}/../VERSION")
80
- assert_eq "version is 1.5.4" "1.5.4" "$version"
80
+ assert_eq "version is 1.6.0" "1.6.0" "$version"
81
81
 
82
82
  echo ""
83
83
  echo "Results: $PASS passed, $FAIL failed"
@@ -121,7 +121,7 @@ assert_contains "help shows Power Features" "Power Features" "$cli_help"
121
121
  # Test 13: version
122
122
  echo "Test 13: version"
123
123
  version=$(cat "${SCRIPT_DIR}/../VERSION")
124
- assert_eq "version is 1.5.4" "1.5.4" "$version"
124
+ assert_eq "version is 1.6.0" "1.6.0" "$version"
125
125
 
126
126
  echo ""
127
127
  echo "Results: $PASS passed, $FAIL failed"
@@ -96,7 +96,7 @@ assert_contains "watch checks terminal states" "done|failed|timeout|cancelled" "
96
96
  # Test 9: version
97
97
  echo "Test 9: version"
98
98
  version=$(cat "${SCRIPT_DIR}/../VERSION")
99
- assert_eq "version is 1.5.4" "1.5.4" "$version"
99
+ assert_eq "version is 1.6.0" "1.6.0" "$version"
100
100
 
101
101
  echo ""
102
102
  echo "Results: $PASS passed, $FAIL failed"
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env bash
2
+ # test-quick-run.sh — Tests for clawforge quick-run
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ CLI="${SCRIPT_DIR}/../bin/clawforge"
7
+ QR="${SCRIPT_DIR}/../bin/quick-run.sh"
8
+
9
+ PASS=0 FAIL=0
10
+
11
+ assert_ok() {
12
+ local desc="$1"; shift
13
+ if "$@" >/dev/null 2>&1; then
14
+ echo " ✅ $desc"; ((PASS++)) || true
15
+ else
16
+ echo " ❌ $desc"; ((FAIL++)) || true
17
+ fi
18
+ }
19
+
20
+ assert_fail() {
21
+ local desc="$1"; shift
22
+ if ! "$@" >/dev/null 2>&1; then
23
+ echo " ✅ $desc"; ((PASS++)) || true
24
+ else
25
+ echo " ❌ $desc"; ((FAIL++)) || true
26
+ fi
27
+ }
28
+
29
+ assert_contains() {
30
+ local desc="$1" needle="$2"; shift 2
31
+ local output
32
+ output=$("$@" 2>&1 || true)
33
+ if grep -q "$needle" <<< "$output"; then
34
+ echo " ✅ $desc"; ((PASS++)) || true
35
+ else
36
+ echo " ❌ $desc (expected '$needle' in output)"; ((FAIL++)) || true
37
+ fi
38
+ }
39
+
40
+ echo "=== test-quick-run.sh ==="
41
+
42
+ # Test 1: script exists and is executable
43
+ echo "Test 1: script exists"
44
+ assert_ok "quick-run.sh exists" test -f "$QR"
45
+ assert_ok "quick-run.sh is executable" test -x "$QR"
46
+
47
+ # Test 2: --help
48
+ echo "Test 2: --help"
49
+ assert_ok "help exits 0" "$QR" --help
50
+ assert_contains "help shows usage" "Usage:" "$QR" --help
51
+ assert_contains "help shows --dir" "\-\-dir" "$QR" --help
52
+ assert_contains "help shows --agent" "\-\-agent" "$QR" --help
53
+ assert_contains "help shows --model" "\-\-model" "$QR" --help
54
+ assert_contains "help shows --save" "\-\-save" "$QR" --help
55
+ assert_contains "help shows --budget" "\-\-budget" "$QR" --help
56
+ assert_contains "help shows --no-track" "\-\-no-track" "$QR" --help
57
+ assert_contains "help shows --dry-run" "\-\-dry-run" "$QR" --help
58
+
59
+ # Test 3: missing task fails
60
+ echo "Test 3: missing task"
61
+ assert_fail "no task fails" "$QR"
62
+
63
+ # Test 4: bad dir fails
64
+ echo "Test 4: bad dir"
65
+ assert_fail "nonexistent dir fails" "$QR" "task" --dir /nonexistent/path
66
+
67
+ # Test 5: dry-run
68
+ echo "Test 5: dry-run"
69
+ TMPDIR_TEST=$(mktemp -d)
70
+ assert_contains "dry-run shows task" "task" "$QR" "Explain the code" --dir "$TMPDIR_TEST" --dry-run
71
+ assert_contains "dry-run shows agent" "agent\|claude\|codex" "$QR" "Explain the code" --dir "$TMPDIR_TEST" --dry-run
72
+ assert_contains "dry-run shows dir" "$TMPDIR_TEST" "$QR" "Explain the code" --dir "$TMPDIR_TEST" --dry-run
73
+ assert_contains "dry-run shows model" "model" "$QR" "Explain the code" --dir "$TMPDIR_TEST" --dry-run
74
+ assert_contains "dry-run no-track shows no" "no" "$QR" "Explain the code" --dir "$TMPDIR_TEST" --dry-run --no-track
75
+ rm -rf "$TMPDIR_TEST"
76
+
77
+ # Test 6: CLI routes quick-run
78
+ echo "Test 6: CLI routing"
79
+ assert_contains "CLI help shows quick-run" "quick-run" "$CLI" help
80
+ assert_contains "CLI routes to script" "Usage:" "$CLI" quick-run --help
81
+
82
+ # Test 7: dry-run with options
83
+ echo "Test 7: dry-run with budget + save"
84
+ TMPDIR_TEST=$(mktemp -d)
85
+ assert_contains "dry-run shows budget" "Budget" \
86
+ "$QR" "Fix the bug" --dir "$TMPDIR_TEST" --dry-run --budget 1.50
87
+ assert_contains "dry-run shows save path" "/tmp" \
88
+ "$QR" "Fix the bug" --dir "$TMPDIR_TEST" --dry-run --save /tmp/out.log
89
+ rm -rf "$TMPDIR_TEST"
90
+
91
+ # Test 8: registry + log setup (with --no-track, no agent needed)
92
+ echo "Test 8: source inspection"
93
+ assert_contains "has epoch_ms" "epoch_ms" cat "$QR"
94
+ assert_contains "has registry_add" "registry_add" cat "$QR"
95
+ assert_contains "has log_path" "log_path" cat "$QR"
96
+ assert_contains "has tee" "tee" cat "$QR"
97
+ assert_contains "has quick-run mode" "quick-run" cat "$QR"
98
+ assert_contains "has detect_agent" "detect_agent" cat "$QR"
99
+ assert_contains "has no-track flag" "NO_TRACK" cat "$QR"
100
+ assert_contains "has budget flag" "BUDGET" cat "$QR"
101
+ assert_contains "has save flag" "SAVE_PATH" cat "$QR"
102
+
103
+ echo ""
104
+ echo "Results: $PASS passed, $FAIL failed"
105
+ [[ $FAIL -eq 0 ]] && exit 0 || exit 1
@@ -96,7 +96,7 @@ assert_contains "help shows Reliability" "Reliability" "$cli_help"
96
96
  # Test 11: version bump
97
97
  echo "Test 11: version"
98
98
  version=$(cat "${SCRIPT_DIR}/../VERSION")
99
- assert_eq "version is 1.5.4" "1.5.4" "$version"
99
+ assert_eq "version is 1.6.0" "1.6.0" "$version"
100
100
 
101
101
  # Test 12: doctor --fix runs without errors
102
102
  echo "Test 12: doctor --fix"
@@ -107,7 +107,7 @@ assert_contains "help shows Web Dashboard" "Web Dashboard" "$cli_help"
107
107
  # Test 7: version
108
108
  echo "Test 7: version"
109
109
  version=$(cat "${SCRIPT_DIR}/../VERSION")
110
- assert_eq "version is 1.5.4" "1.5.4" "$version"
110
+ assert_eq "version is 1.6.0" "1.6.0" "$version"
111
111
 
112
112
  echo ""
113
113
  echo "Results: $PASS passed, $FAIL failed"
@@ -25,6 +25,7 @@ type Agent struct {
25
25
  Conflicts int
26
26
  Description string
27
27
  Worktree string
28
+ LogPath string
28
29
  TmuxSession string
29
30
  }
30
31
 
@@ -42,6 +43,7 @@ type registryTask struct {
42
43
  Model string `json:"model"`
43
44
  Repo string `json:"repo"`
44
45
  CIStatus string `json:"ci_status"`
46
+ LogPath string `json:"log_path"`
45
47
  }
46
48
 
47
49
  type registryFile struct {
@@ -122,6 +124,7 @@ func LoadAgents() []Agent {
122
124
  Description: t.Description,
123
125
  Task: t.Description,
124
126
  Worktree: t.Worktree,
127
+ LogPath: t.LogPath,
125
128
  TmuxSession: t.TmuxSession,
126
129
  CI: ciIndicator(t.CIStatus),
127
130
  Cost: costs[t.ID],
@@ -114,11 +114,15 @@ func renderDashboard(m Model) string {
114
114
  fmt.Sprintf("── Preview: %s ──", selAgent.ID))
115
115
  b.WriteString(previewHeader)
116
116
  b.WriteString("\n")
117
- if selAgent.Preview != "" {
118
- b.WriteString(lipgloss.NewStyle().Faint(true).Render(selAgent.Preview))
119
- } else {
120
- b.WriteString(lipgloss.NewStyle().Faint(true).Render("(no output / not running)"))
117
+ // Static content (from l/d keys) takes priority over live tmux preview.
118
+ content := m.previewContent
119
+ if content == "" {
120
+ content = selAgent.Preview
121
121
  }
122
+ if content == "" {
123
+ content = "(no output / not running)"
124
+ }
125
+ b.WriteString(lipgloss.NewStyle().Faint(true).Render(content))
122
126
  b.WriteString("\n")
123
127
  }
124
128
  }