agileflow 2.71.0 → 2.73.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.
@@ -1,355 +0,0 @@
1
- #!/bin/bash
2
- # AgileFlow Status Line for Claude Code
3
- # Displays contextual information from status.json and session data
4
- #
5
- # This script is called by Claude Code and receives JSON via stdin.
6
- # Customize this script to change what's displayed in your status line.
7
- #
8
- # Available data from stdin JSON:
9
- # .model.display_name - Model name (Opus, Sonnet, etc.)
10
- # .cost.total_cost_usd - Session cost in USD
11
- # .context_window.context_window_size - Total context window size
12
- # .context_window.current_usage.input_tokens - Current input tokens
13
- # .workspace.current_dir - Current working directory
14
-
15
- # ============================================================================
16
- # ANSI Color Codes
17
- # ============================================================================
18
- RESET="\033[0m"
19
- BOLD="\033[1m"
20
- DIM="\033[2m"
21
-
22
- # Foreground colors
23
- BLACK="\033[30m"
24
- RED="\033[31m"
25
- GREEN="\033[32m"
26
- YELLOW="\033[33m"
27
- BLUE="\033[34m"
28
- MAGENTA="\033[35m"
29
- CYAN="\033[36m"
30
- WHITE="\033[37m"
31
-
32
- # Bright foreground colors
33
- BRIGHT_RED="\033[91m"
34
- BRIGHT_GREEN="\033[92m"
35
- BRIGHT_YELLOW="\033[93m"
36
- BRIGHT_BLUE="\033[94m"
37
- BRIGHT_MAGENTA="\033[95m"
38
- BRIGHT_CYAN="\033[96m"
39
-
40
- # Brand color (burnt orange #e8683a = RGB 232,104,58)
41
- BRAND="\033[38;2;232;104;58m"
42
-
43
- # ============================================================================
44
- # Read Component Configuration
45
- # ============================================================================
46
- # Default: all components enabled
47
- SHOW_AGILEFLOW=true
48
- SHOW_MODEL=true
49
- SHOW_STORY=true
50
- SHOW_EPIC=true
51
- SHOW_WIP=true
52
- SHOW_CONTEXT=true
53
- SHOW_COST=true
54
- SHOW_GIT=true
55
-
56
- # Check agileflow-metadata.json for component settings
57
- if [ -f "docs/00-meta/agileflow-metadata.json" ]; then
58
- COMPONENTS=$(jq '.features.statusline.components // null' docs/00-meta/agileflow-metadata.json 2>/dev/null)
59
- if [ "$COMPONENTS" != "null" ] && [ -n "$COMPONENTS" ]; then
60
- # Use 'if . == null then true else . end' to properly handle false values
61
- # (jq's // operator treats false as falsy and applies the fallback)
62
- SHOW_AGILEFLOW=$(echo "$COMPONENTS" | jq -r '.agileflow | if . == null then true else . end')
63
- SHOW_MODEL=$(echo "$COMPONENTS" | jq -r '.model | if . == null then true else . end')
64
- SHOW_STORY=$(echo "$COMPONENTS" | jq -r '.story | if . == null then true else . end')
65
- SHOW_EPIC=$(echo "$COMPONENTS" | jq -r '.epic | if . == null then true else . end')
66
- SHOW_WIP=$(echo "$COMPONENTS" | jq -r '.wip | if . == null then true else . end')
67
- SHOW_CONTEXT=$(echo "$COMPONENTS" | jq -r '.context | if . == null then true else . end')
68
- SHOW_COST=$(echo "$COMPONENTS" | jq -r '.cost | if . == null then true else . end')
69
- SHOW_GIT=$(echo "$COMPONENTS" | jq -r '.git | if . == null then true else . end')
70
- fi
71
- fi
72
-
73
- # ============================================================================
74
- # AgileFlow Version & Update Check
75
- # ============================================================================
76
- AGILEFLOW_DISPLAY=""
77
- if [ "$SHOW_AGILEFLOW" = "true" ]; then
78
- # Get local version from package.json or metadata
79
- LOCAL_VERSION=""
80
- if [ -f ".agileflow/package.json" ]; then
81
- LOCAL_VERSION=$(jq -r '.version // ""' .agileflow/package.json 2>/dev/null)
82
- elif [ -f "docs/00-meta/agileflow-metadata.json" ]; then
83
- LOCAL_VERSION=$(jq -r '.version // ""' docs/00-meta/agileflow-metadata.json 2>/dev/null)
84
- fi
85
-
86
- if [ -n "$LOCAL_VERSION" ] && [ "$LOCAL_VERSION" != "null" ]; then
87
- # Check for updates (cached for 1 hour to avoid rate limiting)
88
- UPDATE_CACHE="/tmp/agileflow-update-check"
89
- UPDATE_AVAILABLE=""
90
- LATEST_VERSION=""
91
-
92
- # Only check npm if cache is stale (older than 1 hour)
93
- if [ ! -f "$UPDATE_CACHE" ] || [ "$(find "$UPDATE_CACHE" -mmin +60 2>/dev/null)" ]; then
94
- # Quick npm check (timeout after 2 seconds)
95
- LATEST_VERSION=$(timeout 2 npm view agileflow version 2>/dev/null || echo "")
96
- if [ -n "$LATEST_VERSION" ]; then
97
- echo "$LATEST_VERSION" > "$UPDATE_CACHE"
98
- fi
99
- else
100
- LATEST_VERSION=$(cat "$UPDATE_CACHE" 2>/dev/null)
101
- fi
102
-
103
- # Compare versions
104
- if [ -n "$LATEST_VERSION" ] && [ "$LATEST_VERSION" != "$LOCAL_VERSION" ]; then
105
- # Simple version comparison (works for semver)
106
- if [ "$(printf '%s\n' "$LOCAL_VERSION" "$LATEST_VERSION" | sort -V | tail -n1)" = "$LATEST_VERSION" ] && [ "$LOCAL_VERSION" != "$LATEST_VERSION" ]; then
107
- UPDATE_AVAILABLE="$LATEST_VERSION"
108
- fi
109
- fi
110
-
111
- # Build display
112
- if [ -n "$UPDATE_AVAILABLE" ]; then
113
- AGILEFLOW_DISPLAY="${BRAND}agileflow${RESET} ${DIM}v${LOCAL_VERSION}${RESET} ${YELLOW}↑${UPDATE_AVAILABLE}${RESET}"
114
- else
115
- AGILEFLOW_DISPLAY="${BRAND}agileflow${RESET} ${DIM}v${LOCAL_VERSION}${RESET}"
116
- fi
117
- else
118
- AGILEFLOW_DISPLAY="${BRAND}agileflow${RESET}"
119
- fi
120
- fi
121
-
122
- # ============================================================================
123
- # Parse Input JSON
124
- # ============================================================================
125
- input=$(cat)
126
-
127
- # Parse model info
128
- MODEL_DISPLAY=$(echo "$input" | jq -r '.model.display_name // "Claude"')
129
-
130
- # Parse context usage
131
- CONTEXT_SIZE=$(echo "$input" | jq -r '.context_window.context_window_size // 200000')
132
- USAGE=$(echo "$input" | jq '.context_window.current_usage // null')
133
-
134
- CTX_DISPLAY=""
135
- CTX_COLOR="$GREEN"
136
- if [ "$USAGE" != "null" ]; then
137
- CURRENT_TOKENS=$(echo "$USAGE" | jq '.input_tokens + (.cache_creation_input_tokens // 0) + (.cache_read_input_tokens // 0)')
138
- if [ "$CURRENT_TOKENS" != "null" ] && [ "$CURRENT_TOKENS" -gt 0 ] 2>/dev/null; then
139
- PERCENT_USED=$((CURRENT_TOKENS * 100 / CONTEXT_SIZE))
140
-
141
- # Color based on usage level
142
- if [ "$PERCENT_USED" -ge 80 ]; then
143
- CTX_COLOR="$BRIGHT_RED"
144
- elif [ "$PERCENT_USED" -ge 60 ]; then
145
- CTX_COLOR="$YELLOW"
146
- elif [ "$PERCENT_USED" -ge 40 ]; then
147
- CTX_COLOR="$BRIGHT_YELLOW"
148
- else
149
- CTX_COLOR="$GREEN"
150
- fi
151
-
152
- CTX_DISPLAY="${CTX_COLOR}${PERCENT_USED}%${RESET}"
153
- fi
154
- fi
155
-
156
- # Parse cost
157
- TOTAL_COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')
158
- COST_DISPLAY=""
159
- if [ "$TOTAL_COST" != "0" ] && [ "$TOTAL_COST" != "null" ]; then
160
- COST_CENTS=$(echo "$TOTAL_COST * 100" | bc 2>/dev/null | cut -d. -f1)
161
- if [ -n "$COST_CENTS" ] && [ "$COST_CENTS" -gt 100 ]; then
162
- # Over $1 - show in yellow
163
- COST_DISPLAY="${YELLOW}$(printf '$%.2f' "$TOTAL_COST")${RESET}"
164
- else
165
- COST_DISPLAY="${DIM}$(printf '$%.2f' "$TOTAL_COST")${RESET}"
166
- fi
167
- fi
168
-
169
- # ============================================================================
170
- # AgileFlow Status - Read from status.json
171
- # ============================================================================
172
- STORY_DISPLAY=""
173
- EPIC_DISPLAY=""
174
- NEXT_STORY=""
175
- WIP_DISPLAY=""
176
-
177
- if [ -f "docs/09-agents/status.json" ]; then
178
- STATUS_JSON=$(cat docs/09-agents/status.json 2>/dev/null)
179
-
180
- # Find first in-progress story and its epic
181
- STORY_ID=$(echo "$STATUS_JSON" | jq -r '.stories | to_entries | map(select(.value.status == "in-progress")) | .[0].key // empty')
182
-
183
- if [ -n "$STORY_ID" ] && [ "$STORY_ID" != "null" ]; then
184
- STORY_TITLE=$(echo "$STATUS_JSON" | jq -r ".stories[\"$STORY_ID\"].title // \"\"")
185
- EPIC_ID=$(echo "$STATUS_JSON" | jq -r ".stories[\"$STORY_ID\"].epic // \"\"")
186
-
187
- if [ -n "$STORY_TITLE" ] && [ "$STORY_TITLE" != "null" ]; then
188
- # Truncate title if too long (max 25 chars)
189
- if [ ${#STORY_TITLE} -gt 25 ]; then
190
- STORY_TITLE="${STORY_TITLE:0:22}..."
191
- fi
192
- STORY_DISPLAY="${CYAN}${STORY_ID}${RESET}${DIM}:${RESET} ${STORY_TITLE}"
193
- fi
194
-
195
- # Get epic progress if we have an epic
196
- if [ -n "$EPIC_ID" ] && [ "$EPIC_ID" != "null" ]; then
197
- # Count total stories in this epic
198
- TOTAL_IN_EPIC=$(echo "$STATUS_JSON" | jq "[.stories | to_entries[] | select(.value.epic == \"$EPIC_ID\")] | length")
199
- # Count done stories in this epic
200
- DONE_IN_EPIC=$(echo "$STATUS_JSON" | jq "[.stories | to_entries[] | select(.value.epic == \"$EPIC_ID\" and .value.status == \"done\")] | length")
201
-
202
- if [ "$TOTAL_IN_EPIC" -gt 0 ] 2>/dev/null; then
203
- EPIC_PCT=$((DONE_IN_EPIC * 100 / TOTAL_IN_EPIC))
204
-
205
- # Color epic progress based on completion
206
- if [ "$EPIC_PCT" -ge 80 ]; then
207
- EPIC_COLOR="$GREEN"
208
- elif [ "$EPIC_PCT" -ge 50 ]; then
209
- EPIC_COLOR="$YELLOW"
210
- else
211
- EPIC_COLOR="$DIM"
212
- fi
213
- EPIC_DISPLAY="${MAGENTA}${EPIC_ID}${RESET} ${EPIC_COLOR}${DONE_IN_EPIC}/${TOTAL_IN_EPIC}${RESET}"
214
- fi
215
- fi
216
- else
217
- # No story in-progress - find next READY story (priority: high > medium > low)
218
- NEXT_ID=$(echo "$STATUS_JSON" | jq -r '
219
- .stories | to_entries
220
- | map(select(.value.status == "ready" or .value.status == "backlog" or .value.status == "draft"))
221
- | sort_by(
222
- if .value.priority == "high" then 0
223
- elif .value.priority == "medium" then 1
224
- else 2
225
- end
226
- )
227
- | .[0].key // empty
228
- ')
229
-
230
- if [ -n "$NEXT_ID" ] && [ "$NEXT_ID" != "null" ]; then
231
- NEXT_PRIORITY=$(echo "$STATUS_JSON" | jq -r ".stories[\"$NEXT_ID\"].priority // \"\"")
232
- # Color based on priority
233
- case "$NEXT_PRIORITY" in
234
- high) PRIORITY_COLOR="$RED" ;;
235
- medium) PRIORITY_COLOR="$YELLOW" ;;
236
- *) PRIORITY_COLOR="$GREEN" ;;
237
- esac
238
- NEXT_STORY="${DIM}Next:${RESET} ${PRIORITY_COLOR}${NEXT_ID}${RESET}"
239
- fi
240
- fi
241
-
242
- # Calculate WIP count
243
- WIP_COUNT=$(echo "$STATUS_JSON" | jq '[.stories | to_entries[] | select(.value.status == "in-progress" or .value.status == "in-review")] | length')
244
- WIP_LIMIT=3 # Default WIP limit
245
- if [ -n "$WIP_COUNT" ] && [ "$WIP_COUNT" != "null" ] && [ "$WIP_COUNT" -gt 0 ] 2>/dev/null; then
246
- # Color WIP based on limit
247
- if [ "$WIP_COUNT" -gt "$WIP_LIMIT" ]; then
248
- WIP_COLOR="$RED"
249
- elif [ "$WIP_COUNT" -eq "$WIP_LIMIT" ]; then
250
- WIP_COLOR="$YELLOW"
251
- else
252
- WIP_COLOR="$GREEN"
253
- fi
254
- WIP_DISPLAY="${DIM}WIP${RESET} ${WIP_COLOR}${WIP_COUNT}${RESET}"
255
- fi
256
- fi
257
-
258
- # ============================================================================
259
- # Git Branch with Colors
260
- # ============================================================================
261
- GIT_DISPLAY=""
262
- if git rev-parse --git-dir > /dev/null 2>&1; then
263
- BRANCH=$(git branch --show-current 2>/dev/null)
264
- if [ -n "$BRANCH" ]; then
265
- # Color based on branch type
266
- case "$BRANCH" in
267
- main|master)
268
- GIT_COLOR="$GREEN"
269
- ;;
270
- develop|dev)
271
- GIT_COLOR="$BLUE"
272
- ;;
273
- feature/*|feat/*)
274
- GIT_COLOR="$CYAN"
275
- ;;
276
- fix/*|bugfix/*|hotfix/*)
277
- GIT_COLOR="$RED"
278
- ;;
279
- release/*)
280
- GIT_COLOR="$MAGENTA"
281
- ;;
282
- *)
283
- GIT_COLOR="$DIM"
284
- ;;
285
- esac
286
-
287
- # Truncate long branch names
288
- if [ ${#BRANCH} -gt 20 ]; then
289
- BRANCH="${BRANCH:0:17}..."
290
- fi
291
- GIT_DISPLAY="${GIT_COLOR}${BRANCH}${RESET}"
292
- fi
293
- fi
294
-
295
- # ============================================================================
296
- # Build Status Line
297
- # ============================================================================
298
- OUTPUT=""
299
-
300
- # Separator
301
- SEP=" ${DIM}│${RESET} "
302
-
303
- # AgileFlow branding (if enabled)
304
- if [ "$SHOW_AGILEFLOW" = "true" ] && [ -n "$AGILEFLOW_DISPLAY" ]; then
305
- OUTPUT="${AGILEFLOW_DISPLAY}"
306
- fi
307
-
308
- # Model with subtle styling (if enabled)
309
- if [ "$SHOW_MODEL" = "true" ]; then
310
- [ -n "$OUTPUT" ] && OUTPUT="${OUTPUT}${SEP}"
311
- OUTPUT="${OUTPUT}${DIM}[${RESET}${BOLD}${MODEL_DISPLAY}${RESET}${DIM}]${RESET}"
312
- fi
313
-
314
- # Add current story OR next story suggestion (if enabled)
315
- if [ "$SHOW_STORY" = "true" ]; then
316
- if [ -n "$STORY_DISPLAY" ]; then
317
- [ -n "$OUTPUT" ] && OUTPUT="${OUTPUT}${SEP}"
318
- OUTPUT="${OUTPUT}${STORY_DISPLAY}"
319
- elif [ -n "$NEXT_STORY" ]; then
320
- [ -n "$OUTPUT" ] && OUTPUT="${OUTPUT}${SEP}"
321
- OUTPUT="${OUTPUT}${NEXT_STORY}"
322
- fi
323
- fi
324
-
325
- # Add epic progress (if enabled and working on a story in an epic)
326
- if [ "$SHOW_EPIC" = "true" ] && [ -n "$EPIC_DISPLAY" ]; then
327
- [ -n "$OUTPUT" ] && OUTPUT="${OUTPUT}${SEP}"
328
- OUTPUT="${OUTPUT}${EPIC_DISPLAY}"
329
- fi
330
-
331
- # Add WIP count (if enabled)
332
- if [ "$SHOW_WIP" = "true" ] && [ -n "$WIP_DISPLAY" ]; then
333
- [ -n "$OUTPUT" ] && OUTPUT="${OUTPUT}${SEP}"
334
- OUTPUT="${OUTPUT}${WIP_DISPLAY}"
335
- fi
336
-
337
- # Add context usage (if enabled)
338
- if [ "$SHOW_CONTEXT" = "true" ] && [ -n "$CTX_DISPLAY" ]; then
339
- [ -n "$OUTPUT" ] && OUTPUT="${OUTPUT}${SEP}"
340
- OUTPUT="${OUTPUT}${CTX_DISPLAY}"
341
- fi
342
-
343
- # Add cost (if enabled)
344
- if [ "$SHOW_COST" = "true" ] && [ -n "$COST_DISPLAY" ]; then
345
- [ -n "$OUTPUT" ] && OUTPUT="${OUTPUT}${SEP}"
346
- OUTPUT="${OUTPUT}${COST_DISPLAY}"
347
- fi
348
-
349
- # Add git branch (if enabled)
350
- if [ "$SHOW_GIT" = "true" ] && [ -n "$GIT_DISPLAY" ]; then
351
- [ -n "$OUTPUT" ] && OUTPUT="${OUTPUT}${SEP}"
352
- OUTPUT="${OUTPUT}${GIT_DISPLAY}"
353
- fi
354
-
355
- echo -e "$OUTPUT"