Skip to content

feat: show teammate model in the agent panel - #14

Merged
GordonBeeming merged 2 commits into
mainfrom
gb/subagent-model-row
Jul 8, 2026
Merged

GordonBeeming merged 2 commits into
mainfrom
gb/subagent-model-row

Conversation

@GordonBeeming

Copy link
Copy Markdown
Owner

What

Background teammates show up as rows in Claude Code's agent panel, but the default row (name · description · token count) never says which model a teammate is running: a Sonnet teammate looks the same as an Opus one.

This adds subagent-statusline.sh, a subagentStatusLine command that rewrites each running teammate's row:

↳ 🐝 pr-pilot · 🔮 Sonnet 5 · ↓ 81.8k tok
↳ 🐝 explorer · 🍃 Haiku 4.5 · ↓ 12.1k tok
  • ↳ 🐝 marks a spawned worker nested under the main session.
  • The model comes from the teammate's own transcript, since the panel payload has no model field. It fills in once the teammate's first response lands.
  • Only actively-running teammates show; finished and idle rows are hidden, so the panel goes quiet once work is done.

Glyphs: 🦉 Opus · 🔮 Sonnet · 🍃 Haiku · 📖 Fable/Mythos. A model outside these families keeps its row without a glyph.

Also

  • statusline.sh's once-a-day auto-update now refreshes both scripts, so the subagent script never goes stale after install.
  • install.sh installs both scripts and prints the subagentStatusLine snippet.
  • README documents the feature.

Testing

Verified live through the configured command against real captured payloads:

tok=0     → ↳ 🐝 <name> · ↓ 0 tok                    (just spawned, no model yet)
tok=20504 → ↳ 🐝 <name> · 🦉 Opus 4.8 · ↓ 20.5k tok

Full model matrix (Opus, Sonnet, Haiku, Fable, plus legacy Haiku 3.5) and the edge cases all pass: unknown family keeps the row without a glyph, a completed teammate's row is hidden, and sub-1k token counts render raw. All three scripts pass bash -n.

Note: existing sessions load subagentStatusLine at startup, so restart or open a new session to pick it up.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EHAoGEYEfzyhPRHSQ1XkDZ

Add subagent-statusline.sh, a subagentStatusLine command that rewrites each
running teammate's row in the agent panel as
"↳ 🐝 <name> · <glyph> <model> · ↓ <tok> tok". The model is read from the
teammate's own transcript (the panel payload has no model field) and mapped to
a per-family glyph (Opus/Sonnet/Haiku/Fable). Only actively-running teammates
show; finished and idle rows are hidden.

statusline.sh's daily auto-update now refreshes both scripts, and install.sh
installs both and prints the subagentStatusLine snippet.

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: GitButler <gitbutler@gitbutler.com>
@GordonBeeming
GordonBeeming marked this pull request as ready for review July 8, 2026 09:48
Copilot AI review requested due to automatic review settings July 8, 2026 09:48
The Status Line Example now shows the four-line main block and the agent-panel
teammate rows together, so the difference is visible at a glance. Drop the
duplicate example from the Subagent rows section and link back to it.

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: GitButler <gitbutler@gitbutler.com>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new subagent-statusline.sh script to display active subagent/teammate models and token usage in the Claude Code agent panel, along with corresponding installer and auto-update integrations. The review feedback focuses on performance optimizations and robust error handling under set -e. Key recommendations include optimizing transcript scanning by only reading the tail of the file, replacing external awk calls with pure Bash arithmetic for token formatting, declaring loop variables as local, and safely capturing command substitution exit codes to prevent premature script termination.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread subagent-statusline.sh
Comment on lines +66 to +68
grep -oE '"model":"claude[^"]*"' "$file" 2>/dev/null \
| tail -1 \
| sed -E 's/.*"model":"//; s/"$//' || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Since this script runs on every panel refresh tick, scanning the entire teammate transcript file with grep can cause noticeable terminal lag as the transcript grows large. Since the model ID is repeated in recent messages, optimize this by only scanning the last 50 lines of the file using tail.

Suggested change
grep -oE '"model":"claude[^"]*"' "$file" 2>/dev/null \
| tail -1 \
| sed -E 's/.*"model":"//; s/"$//' || true
tail -n 50 "$file" 2>/dev/null \
| grep -oE '"model":"claude[^"]*"' \
| tail -1 \
| sed -E 's/.*"model":"//; s/"$//' || true
References
  1. In shell scripts running with 'set -e', guard command substitutions or pipelines that may fail with '|| true' to prevent script termination, provided that an empty result is safely handled by fallback logic.

Comment thread subagent-statusline.sh
Comment on lines +21 to +23
transcript_path=$(printf '%s' "$stdin_data" | jq -r '.transcript_path // ""' 2>/dev/null || echo "")
columns=$(printf '%s' "$stdin_data" | jq -r '.columns // 80' 2>/dev/null || echo 80)
[[ "$columns" =~ ^[0-9]+$ ]] || columns=80

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Capture command substitution exit codes using the || status=$? pattern to prevent unintended script termination on command failure under set -e.

Suggested change
transcript_path=$(printf '%s' "$stdin_data" | jq -r '.transcript_path // ""' 2>/dev/null || echo "")
columns=$(printf '%s' "$stdin_data" | jq -r '.columns // 80' 2>/dev/null || echo 80)
[[ "$columns" =~ ^[0-9]+$ ]] || columns=80
status=0
transcript_path=$(printf '%s' "$stdin_data" | jq -r '.transcript_path // ""' 2>/dev/null) || status=$?
columns=$(printf '%s' "$stdin_data" | jq -r '.columns // 80' 2>/dev/null) || status=$?
[[ "$columns" =~ ^[0-9]+$ ]] || columns=80
References
  1. When using 'set -e' in shell scripts, capture command substitution exit codes using the 'var=$(command) || status=$?' pattern to prevent unintended script termination on command failure.

Comment thread subagent-statusline.sh
Comment on lines +55 to +56
local first rest
first=$(printf '%s' "${family:0:1}" | tr '[:lower:]' '[:upper:]')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Under set -euo pipefail, command substitutions can cause unintended script termination if any command in the pipeline fails. Capture the exit code using the || status=$? pattern to prevent this.

Suggested change
local first rest
first=$(printf '%s' "${family:0:1}" | tr '[:lower:]' '[:upper:]')
local first rest status=0
first=$(printf '%s' "${family:0:1}" | tr '[:lower:]' '[:upper:]') || status=$?
References
  1. When using 'set -e' in shell scripts, capture command substitution exit codes using the 'var=$(command) || status=$?' pattern to prevent unintended script termination on command failure.

Comment thread subagent-statusline.sh
Comment on lines +72 to +80
fmt_tokens() {
local n="$1"
[[ "$n" =~ ^[0-9]+$ ]] || n=0
if (( n >= 1000 )); then
awk -v n="$n" 'BEGIN { printf "%.1fk", n/1000 }'
else
printf '%s' "$n"
fi
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Spawning an external awk process on every panel refresh tick inside a loop can be a performance bottleneck. Implement token formatting and rounding entirely in pure Bash, which is significantly faster and avoids process forks.

Suggested change
fmt_tokens() {
local n="$1"
[[ "$n" =~ ^[0-9]+$ ]] || n=0
if (( n >= 1000 )); then
awk -v n="$n" 'BEGIN { printf "%.1fk", n/1000 }'
else
printf '%s' "$n"
fi
}
fmt_tokens() {
local n="$1"
[[ "$n" =~ ^[0-9]+$ ]] || n=0
if (( n >= 1000 )); then
local rounded=$(( (n + 50) / 100 ))
printf '%d.%dk' $(( rounded / 10 )) $(( rounded % 10 ))
else
printf '%s' "$n"
fi
}

Comment thread subagent-statusline.sh
Comment on lines +84 to +89
tasks_tsv=$(printf '%s' "$stdin_data" | jq -r '
.tasks // []
| .[]
| [ .id, (.status // ""), (.label // .description // ""), ((.tokenCount // 0) | tostring) ]
| @tsv
' 2>/dev/null || true)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Capture command substitution exit codes using the || status=$? pattern to prevent unintended script termination on command failure under set -e.

Suggested change
tasks_tsv=$(printf '%s' "$stdin_data" | jq -r '
.tasks // []
| .[]
| [ .id, (.status // ""), (.label // .description // ""), ((.tokenCount // 0) | tostring) ]
| @tsv
' 2>/dev/null || true)
status=0
tasks_tsv=$(printf '%s' "$stdin_data" | jq -r '
.tasks // []
| .[]
| [ .id, (.status // ""), (.label // .description // ""), ((.tokenCount // 0) | tostring) ]
| @tsv
' 2>/dev/null) || status=$?
References
  1. When using 'set -e' in shell scripts, capture command substitution exit codes using the 'var=$(command) || status=$?' pattern to prevent unintended script termination on command failure.

Comment thread subagent-statusline.sh
Comment on lines +104 to +116
raw_model=$(model_of "$id")
if [[ -n "$raw_model" ]]; then
glyph=$(model_glyph "$raw_model")
if pretty=$(model_pretty "$raw_model"); then
if [[ -n "$glyph" ]]; then
content="${content} · ${glyph} ${pretty}"
else
content="${content} · ${pretty}"
fi
fi
fi

content="${content} · ↓ $(fmt_tokens "$tok") tok"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Declare loop variables as local to prevent scope leakage, and capture command substitution exit codes using the || status=$? pattern to adhere to the general rules and prevent unintended script termination under set -e.

Suggested change
raw_model=$(model_of "$id")
if [[ -n "$raw_model" ]]; then
glyph=$(model_glyph "$raw_model")
if pretty=$(model_pretty "$raw_model"); then
if [[ -n "$glyph" ]]; then
content="${content} · ${glyph} ${pretty}"
else
content="${content} · ${pretty}"
fi
fi
fi
content="${content} · ↓ $(fmt_tokens "$tok") tok"
local raw_model="" glyph="" pretty="" formatted_tok="" status=0
raw_model=$(model_of "$id") || status=$?
if [[ -n "$raw_model" ]]; then
glyph=$(model_glyph "$raw_model") || status=$?
pretty=$(model_pretty "$raw_model") || status=$?
if [[ $status -eq 0 && -n "$pretty" ]]; then
if [[ -n "$glyph" ]]; then
content="${content} · ${glyph} ${pretty}"
else
content="${content} · ${pretty}"
fi
fi
fi
formatted_tok=$(fmt_tokens "$tok") || status=$?
content="${content} · ↓ ${formatted_tok} tok"
References
  1. When using 'set -e' in shell scripts, capture command substitution exit codes using the 'var=$(command) || status=$?' pattern to prevent unintended script termination on command failure.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a dedicated subagentStatusLine command to improve Claude Code’s agent panel by showing each running teammate’s model (with optional glyphs), and updates install/auto-update flows so both statusline scripts stay current.

Changes:

  • Introduces subagent-statusline.sh to render per-subagent rows including model family/version and compact token counts.
  • Extends statusline.sh daily auto-update to refresh both statusline.sh and subagent-statusline.sh.
  • Updates install.sh and README.md to install/document the optional subagentStatusLine configuration.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
subagent-statusline.sh New script that parses tasks + subagent transcripts to render model-aware agent panel rows.
statusline.sh Auto-update now refreshes both the main and subagent statusline scripts.
install.sh Installer now installs both scripts and prints config snippets for both.
README.md Documents the new subagent rows feature and updated install/config instructions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread subagent-statusline.sh
Comment on lines +66 to +68
grep -oE '"model":"claude[^"]*"' "$file" 2>/dev/null \
| tail -1 \
| sed -E 's/.*"model":"//; s/"$//' || true
Comment thread install.sh
Comment on lines +20 to +23
if curl -sSL "${BASE_URL}/${name}" -o "$tmp"; then
cp "$tmp" "${INSTALL_DIR}/${name}"
chmod +x "${INSTALL_DIR}/${name}"
echo " Installed successfully."
Comment thread subagent-statusline.sh
Comment on lines +63 to +68
model_of() {
local id="$1" file="${subagents_dir}/agent-${id}.jsonl"
[[ -f "$file" ]] || return 0
grep -oE '"model":"claude[^"]*"' "$file" 2>/dev/null \
| tail -1 \
| sed -E 's/.*"model":"//; s/"$//' || true
Copilot AI review requested due to automatic review settings July 8, 2026 09:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

Comment thread subagent-statusline.sh
Comment on lines +22 to +23
columns=$(printf '%s' "$stdin_data" | jq -r '.columns // 80' 2>/dev/null || echo 80)
[[ "$columns" =~ ^[0-9]+$ ]] || columns=80
Comment thread subagent-statusline.sh
Comment on lines +66 to +68
grep -oE '"model":"claude[^"]*"' "$file" 2>/dev/null \
| tail -1 \
| sed -E 's/.*"model":"//; s/"$//' || true
Comment thread install.sh
echo "Installing ${name} to ${INSTALL_DIR}..."
local tmp
tmp=$(mktemp)
if curl -sSL "${BASE_URL}/${name}" -o "$tmp"; then

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 42250e150a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread subagent-statusline.sh
# Last assistant model recorded in a teammate's transcript. Empty if the file is
# missing or no assistant turn has landed yet (a just-spawned agent).
model_of() {
local id="$1" file="${subagents_dir}/agent-${id}.jsonl"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resolve teammate sessions before reading the model

When the row represents an Agent Teams teammate, .tasks[].id is the panel/task id while the teammate is a separate Claude session whose session id is recorded in the team config; its transcript is not <lead-session>/subagents/agent-$id.jsonl. With this hard-coded path [[ -f "$file" ]] returns false, so raw_model stays empty and the model never appears for the teammate rows this feature is meant to improve. Please map teammate rows to their session transcript and only use the subagents path for classic subagents.

Useful? React with 👍 / 👎.

@GordonBeeming
GordonBeeming merged commit 3f7eafb into main Jul 8, 2026
1 check passed
@GordonBeeming
GordonBeeming deleted the gb/subagent-model-row branch July 8, 2026 10:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants