@cyperx/clawforge 1.2.0
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.
- package/LICENSE +21 -0
- package/README.md +312 -0
- package/VERSION +1 -0
- package/bin/attach.sh +98 -0
- package/bin/check-agents.sh +343 -0
- package/bin/clawforge +257 -0
- package/bin/clawforge-dashboard +0 -0
- package/bin/clean.sh +257 -0
- package/bin/config.sh +111 -0
- package/bin/conflicts.sh +224 -0
- package/bin/cost.sh +273 -0
- package/bin/dashboard.sh +557 -0
- package/bin/diff.sh +109 -0
- package/bin/doctor.sh +196 -0
- package/bin/eval.sh +217 -0
- package/bin/history.sh +91 -0
- package/bin/init.sh +182 -0
- package/bin/learn.sh +230 -0
- package/bin/logs.sh +126 -0
- package/bin/memory.sh +207 -0
- package/bin/merge-helper.sh +174 -0
- package/bin/multi-review.sh +215 -0
- package/bin/notify.sh +93 -0
- package/bin/on-complete.sh +149 -0
- package/bin/parse-cost.sh +205 -0
- package/bin/pr.sh +167 -0
- package/bin/resume.sh +183 -0
- package/bin/review-mode.sh +163 -0
- package/bin/review-pr.sh +145 -0
- package/bin/routing.sh +88 -0
- package/bin/scope-task.sh +169 -0
- package/bin/spawn-agent.sh +190 -0
- package/bin/sprint.sh +320 -0
- package/bin/steer.sh +107 -0
- package/bin/stop.sh +136 -0
- package/bin/summary.sh +182 -0
- package/bin/swarm.sh +525 -0
- package/bin/templates.sh +244 -0
- package/lib/common.sh +302 -0
- package/lib/templates/bugfix.json +6 -0
- package/lib/templates/migration.json +7 -0
- package/lib/templates/refactor.json +6 -0
- package/lib/templates/security-audit.json +5 -0
- package/lib/templates/test-coverage.json +6 -0
- package/package.json +31 -0
- package/registry/conflicts.jsonl +0 -0
- package/registry/costs.jsonl +0 -0
- package/tui/PRD.md +106 -0
- package/tui/agent.go +266 -0
- package/tui/animation.go +192 -0
- package/tui/dashboard.go +219 -0
- package/tui/filter.go +68 -0
- package/tui/go.mod +25 -0
- package/tui/go.sum +46 -0
- package/tui/keybindings.go +229 -0
- package/tui/main.go +61 -0
- package/tui/model.go +166 -0
- package/tui/steer.go +69 -0
- package/tui/styles.go +69 -0
package/bin/stop.sh
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# stop.sh — Stop a running agent
|
|
3
|
+
# Usage: clawforge stop <id> [--yes] [--clean]
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
7
|
+
source "${SCRIPT_DIR}/../lib/common.sh"
|
|
8
|
+
|
|
9
|
+
# ── Help ───────────────────────────────────────────────────────────────
|
|
10
|
+
usage() {
|
|
11
|
+
cat <<EOF
|
|
12
|
+
Usage: clawforge stop <id> [flags]
|
|
13
|
+
|
|
14
|
+
Stop a running agent. Kills the tmux session and marks task as stopped.
|
|
15
|
+
|
|
16
|
+
Arguments:
|
|
17
|
+
<id> Task short ID (#1), full ID, or sub-agent ID (3.2)
|
|
18
|
+
|
|
19
|
+
Flags:
|
|
20
|
+
--yes Skip confirmation prompt
|
|
21
|
+
--clean Also remove the worktree
|
|
22
|
+
--help Show this help
|
|
23
|
+
|
|
24
|
+
Examples:
|
|
25
|
+
clawforge stop 1
|
|
26
|
+
clawforge stop 3 --yes --clean
|
|
27
|
+
EOF
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# ── Parse args ────────────────────────────────────────────────────────
|
|
31
|
+
TASK_REF="" YES=false CLEAN=false
|
|
32
|
+
|
|
33
|
+
while [[ $# -gt 0 ]]; do
|
|
34
|
+
case "$1" in
|
|
35
|
+
--yes) YES=true; shift ;;
|
|
36
|
+
--clean) CLEAN=true; shift ;;
|
|
37
|
+
--help|-h) usage; exit 0 ;;
|
|
38
|
+
--*) log_error "Unknown option: $1"; usage; exit 1 ;;
|
|
39
|
+
*)
|
|
40
|
+
if [[ -z "$TASK_REF" ]]; then
|
|
41
|
+
TASK_REF="$1"
|
|
42
|
+
else
|
|
43
|
+
log_error "Unexpected argument: $1"
|
|
44
|
+
usage
|
|
45
|
+
exit 1
|
|
46
|
+
fi
|
|
47
|
+
shift
|
|
48
|
+
;;
|
|
49
|
+
esac
|
|
50
|
+
done
|
|
51
|
+
|
|
52
|
+
if [[ -z "$TASK_REF" ]]; then
|
|
53
|
+
log_error "Task ID is required"
|
|
54
|
+
usage
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# ── Resolve task ──────────────────────────────────────────────────────
|
|
59
|
+
TASK_ID=$(resolve_task_id "$TASK_REF")
|
|
60
|
+
if [[ -z "$TASK_ID" ]]; then
|
|
61
|
+
log_error "Could not resolve task: $TASK_REF"
|
|
62
|
+
exit 1
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
TASK=$(registry_get "$TASK_ID")
|
|
66
|
+
if [[ -z "$TASK" ]]; then
|
|
67
|
+
log_error "Task not found: $TASK_ID"
|
|
68
|
+
exit 1
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
STATUS=$(echo "$TASK" | jq -r '.status')
|
|
72
|
+
TMUX_SESSION=$(echo "$TASK" | jq -r '.tmuxSession')
|
|
73
|
+
WORKTREE=$(echo "$TASK" | jq -r '.worktree')
|
|
74
|
+
DESCRIPTION=$(echo "$TASK" | jq -r '.description' | head -c 50)
|
|
75
|
+
|
|
76
|
+
# ── Already stopped? ──────────────────────────────────────────────────
|
|
77
|
+
if [[ "$STATUS" == "stopped" || "$STATUS" == "archived" ]]; then
|
|
78
|
+
echo "Task $TASK_REF is already $STATUS."
|
|
79
|
+
exit 0
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
# ── Confirm ───────────────────────────────────────────────────────────
|
|
83
|
+
if ! $YES; then
|
|
84
|
+
echo "Stop task $TASK_REF? [$STATUS] \"$DESCRIPTION\""
|
|
85
|
+
$CLEAN && echo " (will also remove worktree: $WORKTREE)"
|
|
86
|
+
echo -n " Confirm [y/N]: "
|
|
87
|
+
read -r confirm
|
|
88
|
+
if [[ ! "$confirm" =~ ^[yY] ]]; then
|
|
89
|
+
echo "Cancelled."
|
|
90
|
+
exit 0
|
|
91
|
+
fi
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# ── Kill tmux session ─────────────────────────────────────────────────
|
|
95
|
+
if [[ -n "$TMUX_SESSION" ]]; then
|
|
96
|
+
tmux kill-session -t "$TMUX_SESSION" 2>/dev/null || true
|
|
97
|
+
log_info "Killed tmux session: $TMUX_SESSION"
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# ── Update registry ───────────────────────────────────────────────────
|
|
101
|
+
NOW=$(epoch_ms)
|
|
102
|
+
registry_update "$TASK_ID" "status" '"stopped"'
|
|
103
|
+
registry_update "$TASK_ID" "completedAt" "$NOW"
|
|
104
|
+
|
|
105
|
+
# ── Clean worktree if requested ───────────────────────────────────────
|
|
106
|
+
if $CLEAN && [[ -n "$WORKTREE" ]] && [[ -d "$WORKTREE" ]]; then
|
|
107
|
+
REPO=$(echo "$TASK" | jq -r '.repo')
|
|
108
|
+
git -C "$REPO" worktree remove "$WORKTREE" --force 2>/dev/null || rm -rf "$WORKTREE"
|
|
109
|
+
log_info "Removed worktree: $WORKTREE"
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
# ── Also stop sub-agents if this is a swarm parent ────────────────────
|
|
113
|
+
MODE=$(echo "$TASK" | jq -r '.mode // ""')
|
|
114
|
+
if [[ "$MODE" == "swarm" ]]; then
|
|
115
|
+
SUB_IDS=$(jq -r --arg pid "$TASK_ID" '.tasks[] | select(.parent_id == $pid) | .id' "$REGISTRY_FILE" 2>/dev/null || true)
|
|
116
|
+
if [[ -n "$SUB_IDS" ]]; then
|
|
117
|
+
while IFS= read -r sub_id; do
|
|
118
|
+
SUB_TMUX=$(registry_get "$sub_id" | jq -r '.tmuxSession')
|
|
119
|
+
if [[ -n "$SUB_TMUX" ]]; then
|
|
120
|
+
tmux kill-session -t "$SUB_TMUX" 2>/dev/null || true
|
|
121
|
+
fi
|
|
122
|
+
registry_update "$sub_id" "status" '"stopped"'
|
|
123
|
+
registry_update "$sub_id" "completedAt" "$NOW"
|
|
124
|
+
if $CLEAN; then
|
|
125
|
+
SUB_WT=$(registry_get "$sub_id" | jq -r '.worktree')
|
|
126
|
+
SUB_REPO=$(registry_get "$sub_id" | jq -r '.repo')
|
|
127
|
+
if [[ -n "$SUB_WT" ]] && [[ -d "$SUB_WT" ]]; then
|
|
128
|
+
git -C "$SUB_REPO" worktree remove "$SUB_WT" --force 2>/dev/null || rm -rf "$SUB_WT"
|
|
129
|
+
fi
|
|
130
|
+
fi
|
|
131
|
+
log_info "Stopped sub-agent: $sub_id"
|
|
132
|
+
done <<< "$SUB_IDS"
|
|
133
|
+
fi
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
echo "Stopped: $TASK_REF ($DESCRIPTION)"
|
package/bin/summary.sh
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# summary.sh — AI-generated summary of what an agent did
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
+
source "${SCRIPT_DIR}/../lib/common.sh"
|
|
7
|
+
|
|
8
|
+
usage() {
|
|
9
|
+
cat <<EOF
|
|
10
|
+
Usage: clawforge summary <id> [options]
|
|
11
|
+
|
|
12
|
+
Generate an AI summary of what an agent did based on git diff and logs.
|
|
13
|
+
|
|
14
|
+
Arguments:
|
|
15
|
+
<id> Task ID or short ID
|
|
16
|
+
|
|
17
|
+
Options:
|
|
18
|
+
--model <model> Model to use for summary (default: from config)
|
|
19
|
+
--format <fmt> Output format: text, markdown, json (default: markdown)
|
|
20
|
+
--include-diff Include full diff in output (default: summary only)
|
|
21
|
+
--save <path> Save summary to file
|
|
22
|
+
--help Show this help
|
|
23
|
+
|
|
24
|
+
Examples:
|
|
25
|
+
clawforge summary 1
|
|
26
|
+
clawforge summary 1 --format json
|
|
27
|
+
clawforge summary sprint-jwt --save /tmp/summary.md
|
|
28
|
+
EOF
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
TASK_REF="" MODEL="" FORMAT="markdown" INCLUDE_DIFF=false SAVE_PATH=""
|
|
32
|
+
|
|
33
|
+
while [[ $# -gt 0 ]]; do
|
|
34
|
+
case "$1" in
|
|
35
|
+
--model) MODEL="$2"; shift 2 ;;
|
|
36
|
+
--format) FORMAT="$2"; shift 2 ;;
|
|
37
|
+
--include-diff) INCLUDE_DIFF=true; shift ;;
|
|
38
|
+
--save) SAVE_PATH="$2"; shift 2 ;;
|
|
39
|
+
--help|-h) usage; exit 0 ;;
|
|
40
|
+
--*) log_error "Unknown option: $1"; usage; exit 1 ;;
|
|
41
|
+
*) TASK_REF="$1"; shift ;;
|
|
42
|
+
esac
|
|
43
|
+
done
|
|
44
|
+
|
|
45
|
+
[[ -z "$TASK_REF" ]] && { log_error "Task ID required"; usage; exit 1; }
|
|
46
|
+
|
|
47
|
+
_ensure_registry
|
|
48
|
+
|
|
49
|
+
# Resolve task
|
|
50
|
+
TASK_DATA=""
|
|
51
|
+
if [[ "$TASK_REF" =~ ^[0-9]+$ ]]; then
|
|
52
|
+
TASK_DATA=$(jq -r --argjson sid "$TASK_REF" '.tasks[] | select(.short_id == $sid)' "$REGISTRY_FILE" 2>/dev/null || true)
|
|
53
|
+
fi
|
|
54
|
+
if [[ -z "$TASK_DATA" ]]; then
|
|
55
|
+
TASK_DATA=$(registry_get "$TASK_REF" 2>/dev/null || true)
|
|
56
|
+
fi
|
|
57
|
+
if [[ -z "$TASK_DATA" ]]; then
|
|
58
|
+
log_error "Task '$TASK_REF' not found"
|
|
59
|
+
exit 1
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
TASK_ID=$(echo "$TASK_DATA" | jq -r '.id')
|
|
63
|
+
DESC=$(echo "$TASK_DATA" | jq -r '.description // "—"')
|
|
64
|
+
WORKTREE=$(echo "$TASK_DATA" | jq -r '.worktree // empty')
|
|
65
|
+
BRANCH=$(echo "$TASK_DATA" | jq -r '.branch // empty')
|
|
66
|
+
REPO=$(echo "$TASK_DATA" | jq -r '.repo // empty')
|
|
67
|
+
MODE=$(echo "$TASK_DATA" | jq -r '.mode // "sprint"')
|
|
68
|
+
STATUS=$(echo "$TASK_DATA" | jq -r '.status // "unknown"')
|
|
69
|
+
AGENT=$(echo "$TASK_DATA" | jq -r '.agent // "claude"')
|
|
70
|
+
SHORT_ID=$(echo "$TASK_DATA" | jq -r '.short_id // 0')
|
|
71
|
+
TMUX_SESSION=$(echo "$TASK_DATA" | jq -r '.tmuxSession // empty')
|
|
72
|
+
|
|
73
|
+
# Resolve model
|
|
74
|
+
if [[ -z "$MODEL" ]]; then
|
|
75
|
+
MODEL=$(config_get default_model_claude "claude-sonnet-4-5")
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# Gather context: git diff
|
|
79
|
+
GIT_DIR=""
|
|
80
|
+
if [[ -n "$WORKTREE" && -d "$WORKTREE" ]]; then
|
|
81
|
+
GIT_DIR="$WORKTREE"
|
|
82
|
+
elif [[ -n "$REPO" && -d "$REPO" ]]; then
|
|
83
|
+
GIT_DIR="$REPO"
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
DIFF_TEXT=""
|
|
87
|
+
DIFF_STAT=""
|
|
88
|
+
if [[ -n "$GIT_DIR" ]]; then
|
|
89
|
+
DEFAULT_BRANCH=$(git -C "$GIT_DIR" symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||' || echo "main")
|
|
90
|
+
DIFF_STAT=$(git -C "$GIT_DIR" diff --stat "${DEFAULT_BRANCH}...HEAD" 2>/dev/null || git -C "$GIT_DIR" diff --stat 2>/dev/null || true)
|
|
91
|
+
DIFF_TEXT=$(git -C "$GIT_DIR" diff "${DEFAULT_BRANCH}...HEAD" 2>/dev/null | head -300 || git -C "$GIT_DIR" diff 2>/dev/null | head -300 || true)
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# Gather context: recent tmux output
|
|
95
|
+
TMUX_OUTPUT=""
|
|
96
|
+
if [[ -n "$TMUX_SESSION" ]] && tmux has-session -t "$TMUX_SESSION" 2>/dev/null; then
|
|
97
|
+
TMUX_OUTPUT=$(tmux capture-pane -t "$TMUX_SESSION" -p -S -30 2>/dev/null || true)
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# Build summary prompt
|
|
101
|
+
SUMMARY_PROMPT="Summarize what this coding agent accomplished. Be concise and specific.
|
|
102
|
+
|
|
103
|
+
Task: ${DESC}
|
|
104
|
+
Mode: ${MODE}
|
|
105
|
+
Status: ${STATUS}
|
|
106
|
+
Agent: ${AGENT}
|
|
107
|
+
Branch: ${BRANCH}
|
|
108
|
+
|
|
109
|
+
${DIFF_STAT:+Files changed:
|
|
110
|
+
${DIFF_STAT}
|
|
111
|
+
}
|
|
112
|
+
${DIFF_TEXT:+Diff (first 300 lines):
|
|
113
|
+
\`\`\`diff
|
|
114
|
+
${DIFF_TEXT}
|
|
115
|
+
\`\`\`
|
|
116
|
+
}
|
|
117
|
+
${TMUX_OUTPUT:+Recent agent output:
|
|
118
|
+
\`\`\`
|
|
119
|
+
${TMUX_OUTPUT}
|
|
120
|
+
\`\`\`
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
Provide:
|
|
124
|
+
1. One-line summary (what was done)
|
|
125
|
+
2. Key changes (bullet points)
|
|
126
|
+
3. Status assessment (complete/partial/blocked)
|
|
127
|
+
4. Any notable decisions or trade-offs"
|
|
128
|
+
|
|
129
|
+
if [[ "$FORMAT" == "json" ]]; then
|
|
130
|
+
SUMMARY_PROMPT+="
|
|
131
|
+
|
|
132
|
+
Output as JSON: {\"oneLiner\": \"...\", \"changes\": [\"...\"], \"status\": \"...\", \"notes\": \"...\"}"
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
# Generate summary
|
|
136
|
+
if ! command -v claude &>/dev/null; then
|
|
137
|
+
log_error "claude CLI not found — needed for summary generation"
|
|
138
|
+
exit 1
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
log_info "Generating summary for #${SHORT_ID} with $MODEL..."
|
|
142
|
+
|
|
143
|
+
SUMMARY=$(claude --model "$MODEL" -p "$SUMMARY_PROMPT" 2>/dev/null || true)
|
|
144
|
+
|
|
145
|
+
if [[ -z "$SUMMARY" ]]; then
|
|
146
|
+
log_error "Summary generation failed"
|
|
147
|
+
exit 1
|
|
148
|
+
fi
|
|
149
|
+
|
|
150
|
+
# Output
|
|
151
|
+
OUTPUT=""
|
|
152
|
+
if [[ "$FORMAT" == "markdown" ]]; then
|
|
153
|
+
OUTPUT="# Summary: #${SHORT_ID} — ${DESC}
|
|
154
|
+
**Mode:** ${MODE} | **Status:** ${STATUS} | **Agent:** ${AGENT}
|
|
155
|
+
**Branch:** ${BRANCH}
|
|
156
|
+
|
|
157
|
+
${SUMMARY}
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
*Generated by ClawForge summary (${MODEL})*"
|
|
161
|
+
elif [[ "$FORMAT" == "json" ]]; then
|
|
162
|
+
OUTPUT="$SUMMARY"
|
|
163
|
+
else
|
|
164
|
+
OUTPUT="Summary #${SHORT_ID}: ${DESC}
|
|
165
|
+
${SUMMARY}"
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
if $INCLUDE_DIFF && [[ -n "$DIFF_STAT" ]]; then
|
|
169
|
+
OUTPUT+="
|
|
170
|
+
|
|
171
|
+
## Diff Stats
|
|
172
|
+
\`\`\`
|
|
173
|
+
${DIFF_STAT}
|
|
174
|
+
\`\`\`"
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
if [[ -n "$SAVE_PATH" ]]; then
|
|
178
|
+
echo "$OUTPUT" > "$SAVE_PATH"
|
|
179
|
+
echo "Summary saved to $SAVE_PATH"
|
|
180
|
+
else
|
|
181
|
+
echo "$OUTPUT"
|
|
182
|
+
fi
|