feat: free-form sessions, rename/end from the panel, live Claude Context (0.2.0)
- Sessions no longer need a project folder: any name works and starts in DEVDESK_DEFAULT_DIR unless it matches a project; `devdesk new NAME [PROJECT]`. - Rename (✎) and end/forget (×) sessions from the Sessions panel, plus `devdesk rename`. The browser runs them as `devdesk attach --new|--rename|--end` through ttyd. Renames keep the running Claude and its recorded conversation: the hook, the run-wrapper and the statusline ask tmux for the current name. - Claude Context panel is live: devdesk-statusline snapshots model, context-window use, cost and edits per session, which --list reports; Claude's footer gets a one-line summary. The panel now sits under Sessions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Executable
+48
@@ -0,0 +1,48 @@
|
||||
#!/bin/bash
|
||||
# Claude Code statusLine command (wired in via claude-settings.json). Claude pipes
|
||||
# its status JSON in on every update; we keep a snapshot per DevDesk session for
|
||||
# the web UI's Claude Context panel and print a one-line status for Claude's footer.
|
||||
# Runs often while Claude streams, so it stays cheap and never fails loudly.
|
||||
|
||||
input=$(cat)
|
||||
|
||||
session=""
|
||||
if [ -n "${TMUX:-}" ] && [ -n "${TMUX_PANE:-}" ]; then
|
||||
session=$(tmux display-message -p -t "$TMUX_PANE" '#S' 2>/dev/null)
|
||||
fi
|
||||
session=${session:-${DEVDESK_SESSION:-}}
|
||||
|
||||
if [[ $session =~ ^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$ ]]; then
|
||||
dir="${DEVDESK_STATE_DIR:-/var/lib/devdesk}/context"
|
||||
if mkdir -p "$dir" 2>/dev/null && tmp=$(mktemp "$dir/.$session.XXXXXX" 2>/dev/null); then
|
||||
if jq -cM '{
|
||||
updated: (now | floor),
|
||||
claude_session_id: .session_id,
|
||||
model: .model.display_name,
|
||||
model_id: .model.id,
|
||||
effort: .effort.level,
|
||||
used_pct: .context_window.used_percentage,
|
||||
window: .context_window.context_window_size,
|
||||
used_tokens: (.context_window.current_usage
|
||||
| if . then ((.input_tokens // 0) + (.cache_creation_input_tokens // 0)
|
||||
+ (.cache_read_input_tokens // 0)) else null end),
|
||||
cost_usd: .cost.total_cost_usd,
|
||||
lines_added: .cost.total_lines_added,
|
||||
lines_removed: .cost.total_lines_removed
|
||||
}' <<<"$input" >"$tmp" 2>/dev/null; then
|
||||
mv -f "$tmp" "$dir/$session.json"
|
||||
else
|
||||
rm -f "$tmp"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Footer line, in TDS colours: session · model · context % · cost
|
||||
jq -rM --arg s "$session" '
|
||||
def c($rgb; $t): "\u001b[38;2;\($rgb)m\($t)\u001b[0m";
|
||||
def pct: if . == null then "—" else "\(. | floor)%" end;
|
||||
[ (if $s != "" then c("255;107;0"; "◈ \($s)") else empty end),
|
||||
c("0;212;255"; .model.display_name // "Claude"),
|
||||
c("127;163;191"; "ctx \(.context_window.used_percentage | pct)"),
|
||||
c("62;96;122"; "$\((.cost.total_cost_usd // 0) * 100 | round / 100)")
|
||||
] | join(c("62;96;122"; " · "))' <<<"$input" 2>/dev/null || true
|
||||
Reference in New Issue
Block a user