agileflow 2.43.0 → 2.45.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/package.json +2 -1
- package/scripts/README.md +267 -0
- package/scripts/agileflow-configure.js +927 -0
- package/scripts/agileflow-statusline.sh +355 -0
- package/scripts/agileflow-stop.sh +13 -0
- package/scripts/agileflow-welcome.js +427 -0
- package/scripts/archive-completed-stories.sh +162 -0
- package/scripts/clear-active-command.js +48 -0
- package/scripts/compress-status.sh +116 -0
- package/scripts/expertise-metrics.sh +264 -0
- package/scripts/generate-all.sh +77 -0
- package/scripts/generators/agent-registry.js +167 -0
- package/scripts/generators/command-registry.js +135 -0
- package/scripts/generators/index.js +87 -0
- package/scripts/generators/inject-babysit.js +167 -0
- package/scripts/generators/inject-help.js +109 -0
- package/scripts/generators/inject-readme.js +156 -0
- package/scripts/generators/skill-registry.js +144 -0
- package/scripts/get-env.js +209 -0
- package/scripts/obtain-context.js +293 -0
- package/scripts/precompact-context.sh +123 -0
- package/scripts/validate-expertise.sh +259 -0
- package/src/core/commands/context.md +141 -5
- package/tools/cli/installers/core/installer.js +97 -4
|
@@ -0,0 +1,355 @@
|
|
|
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"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# agileflow-stop.sh - Session wrap-up hook
|
|
3
|
+
|
|
4
|
+
# Only run if we're in a git repo
|
|
5
|
+
git rev-parse --git-dir > /dev/null 2>&1 || exit 0
|
|
6
|
+
|
|
7
|
+
# Check for uncommitted changes
|
|
8
|
+
CHANGES=$(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')
|
|
9
|
+
|
|
10
|
+
if [ "$CHANGES" -gt 0 ]; then
|
|
11
|
+
echo ""
|
|
12
|
+
echo -e "\033[0;33m$CHANGES uncommitted change(s)\033[0m"
|
|
13
|
+
fi
|