retro
Weekly engineering retrospective. Analyzes commit history, work patterns, and code quality metrics with persistent history and trend tracking. Team-aware: break
Security score
The retro skill was audited on Mar 16, 2026 and we found 19 security issues across 2 threat categories. Review the findings below before installing.
Categories Tested
Security Issues
Command substitution pattern
| 19 | |
| 20 | ```bash |
| 21 | _UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true) |
| 22 | [ -n "$_UPD" ] && echo "$_UPD" || true |
| 23 | mkdir -p ~/.gstack/sessions |
Command substitution pattern
| 23 | mkdir -p ~/.gstack/sessions |
| 24 | touch ~/.gstack/sessions/"$PPID" |
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 26 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 27 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
Command substitution pattern
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 26 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 27 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
| 28 | ``` |
| 29 |
Command substitution pattern
| 342 | ``` |
| 343 | |
| 344 | Determine the next sequence number for today (substitute the actual date for `$(date +%Y-%m-%d)`): |
| 345 | ```bash |
| 346 | # Count existing retros for today to get next sequence number |
Command substitution pattern
| 345 | ```bash |
| 346 | # Count existing retros for today to get next sequence number |
| 347 | today=$(TZ=America/Los_Angeles date +%Y-%m-%d) |
| 348 | existing=$(ls .context/retros/${today}-*.json 2>/dev/null | wc -l | tr -d ' ') |
| 349 | next=$((existing + 1)) |
Command substitution pattern
| 346 | # Count existing retros for today to get next sequence number |
| 347 | today=$(TZ=America/Los_Angeles date +%Y-%m-%d) |
| 348 | existing=$(ls .context/retros/${today}-*.json 2>/dev/null | wc -l | tr -d ' ') |
| 349 | next=$((existing + 1)) |
| 350 | # Save as .context/retros/${today}-${next}.json |
Command substitution pattern
| 347 | today=$(TZ=America/Los_Angeles date +%Y-%m-%d) |
| 348 | existing=$(ls .context/retros/${today}-*.json 2>/dev/null | wc -l | tr -d ' ') |
| 349 | next=$((existing + 1)) |
| 350 | # Save as .context/retros/${today}-${next}.json |
| 351 | ``` |
Access to home directory dotfiles
| 19 | |
| 20 | ```bash |
| 21 | _UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true) |
| 22 | [ -n "$_UPD" ] && echo "$_UPD" || true |
| 23 | mkdir -p ~/.gstack/sessions |
Access to home directory dotfiles
| 21 | _UPD=$(~/.claude/skills/gstack/bin/gstack-update-check 2>/dev/null || .claude/skills/gstack/bin/gstack-update-check 2>/dev/null || true) |
| 22 | [ -n "$_UPD" ] && echo "$_UPD" || true |
| 23 | mkdir -p ~/.gstack/sessions |
| 24 | touch ~/.gstack/sessions/"$PPID" |
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
Access to home directory dotfiles
| 22 | [ -n "$_UPD" ] && echo "$_UPD" || true |
| 23 | mkdir -p ~/.gstack/sessions |
| 24 | touch ~/.gstack/sessions/"$PPID" |
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 26 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
Access to home directory dotfiles
| 23 | mkdir -p ~/.gstack/sessions |
| 24 | touch ~/.gstack/sessions/"$PPID" |
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 26 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 27 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
Access to home directory dotfiles
| 24 | touch ~/.gstack/sessions/"$PPID" |
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 26 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 27 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
| 28 | ``` |
Access to home directory dotfiles
| 25 | _SESSIONS=$(find ~/.gstack/sessions -mmin -120 -type f 2>/dev/null | wc -l | tr -d ' ') |
| 26 | find ~/.gstack/sessions -mmin +120 -type f -delete 2>/dev/null || true |
| 27 | _CONTRIB=$(~/.claude/skills/gstack/bin/gstack-config get gstack_contributor 2>/dev/null || true) |
| 28 | ``` |
| 29 |
Access to home directory dotfiles
| 28 | ``` |
| 29 | |
| 30 | If output shows `UPGRADE_AVAILABLE <old> <new>`: read `~/.claude/skills/gstack/gstack-upgrade/SKILL.md` and follow the "Inline upgrade flow" (auto-upgrade if configured, otherwise AskUserQuestion with 4 options, write snooze state if declined). If `JUST_UPGRADED <from> <to>`: tell user "Running gstack v{to} (just updated!)" and continue. |
| 31 | |
| 32 | ## AskUserQuestion Format |
Access to home directory dotfiles
| 49 | **NOT gstack issues:** user's app bugs, network errors to user's URL, auth failures on user's site. |
| 50 | |
| 51 | **To file:** write `~/.gstack/contributor-logs/{slug}.md` with this structure: |
| 52 | |
| 53 | ``` |
Access to home directory dotfiles
| 69 | ``` |
| 70 | |
| 71 | Then run: `mkdir -p ~/.gstack/contributor-logs && open ~/.gstack/contributor-logs/{slug}.md` |
| 72 | |
| 73 | Slug: lowercase, hyphens, max 60 chars (e.g. `browse-snapshot-ref-gap`). Skip if file already exists. Max 3 reports per session. File inline and continue — don't stop the workflow. Tell user: "Filed gstack field report: {title}" |
Access to home directory dotfiles
| 143 | |
| 144 | # 8. Greptile triage history (if available) |
| 145 | cat ~/.gstack/greptile-history.md 2>/dev/null || true |
| 146 | |
| 147 | # 9. TODOS.md backlog (if available) |
Access to home directory dotfiles
| 180 | Sort by commits descending. The current user (from `git config user.name`) always appears first, labeled "You (name)". |
| 181 | |
| 182 | **Greptile signal (if history exists):** Read `~/.gstack/greptile-history.md` (fetched in Step 1, command 8). Filter entries within the retro time window by date. Count entries by type: `fix`, `fp`, `already-fixed`. Compute signal ratio: `(fix + already-fixed) / (fix + already-fixed + fp)`. If no entries exist in the window or the file doesn't exist, skip the Greptile metric row. Skip unparseable lines silently. |
| 183 | |
| 184 | **Backlog Health (if TODOS.md exists):** Read `TODOS.md` (fetched in Step 1, command 9). Compute: |
Access to home directory dotfiles
| 391 | ``` |
| 392 | |
| 393 | **Note:** Only include the `greptile` field if `~/.gstack/greptile-history.md` exists and has entries within the time window. Only include the `backlog` field if `TODOS.md` exists. If either has no data, omit the field entirely. |
| 394 | |
| 395 | Include backlog data in the JSON when TODOS.md exists: |