feat: v0.12.0 Settings window, per-session Remote Control, delete conversations
build-deb / Lint, test, package (push) Successful in 4m59s
build-deb / Deploy to CT 126 (push) Successful in 14s
build-deb / Notify on failure (push) Skipped

- Settings (⋯ → Settings…, palette): theme, terminal text size, interface
  size, notifications, Remote Control & privacy. The ⋯ menu shrinks.
- Remote Control per session: registry choice > Settings default >
  DEVDESK_REMOTE_CONTROL. Switching an idle session restarts its Claude
  on the same conversation; busy sessions change at the next start.
  rc_active comes from the running process; RC tag on sessions.
- --delete-convo: remove a conversation's local transcript and subagent
  files; refused while in use. Delete… in Search past conversations.
Closes #61

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHRLCCdXYm41Qx5kNhehaP
This commit is contained in:
2026-11-03 21:23:29 -05:00
co-authored by Claude Opus 5.5
parent 65114165e7
commit 20134c1e58
14 changed files with 454 additions and 50 deletions
+11 -1
View File
@@ -27,7 +27,8 @@ RESET=$'\033[0m'
common_args() {
printf '%s\0' --settings "$SETTINGS"
if [ "${DEVDESK_REMOTE_CONTROL:-0}" = "1" ]; then
# Per session since devdesk#61 (Settings → Remote Control).
if [ "$(dd_rc_wanted "$NAME")" = 1 ]; then
printf '%s\0' --remote-control "devdesk-$NAME"
fi
if [ ${#EXTRA[@]} -gt 0 ]; then
@@ -97,6 +98,15 @@ while :; do
if [ "$mode" = new ]; then run_new; else run_resume; fi
rc=$?
NAME=$(dd_current_session)
# Settings changed Remote Control: Claude was stopped to restart on the same
# conversation with the new setting (devdesk#61), no menu.
restart="$DEVDESK_STATE_DIR/restart/$NAME"
if [ -e "$restart" ]; then
rm -f "$restart"
printf '\n%s◈ Restarting Claude with Remote Control %s…%s\n' "$MUTED" "$([ "$(dd_rc_wanted "$NAME")" = 1 ] && echo on || echo off)" "$RESET"
mode=resume
continue
fi
while :; do
menu "$rc"
IFS= read -rsn1 key || exit 0
+27
View File
@@ -115,3 +115,30 @@ cmd_presence() {
setsid -f bash -c 'sleep 120; [ -n "$(find "$1" -newermt "-110 seconds" 2>/dev/null)" ] || rm -f "$1"' _ "$marker" \
</dev/null >/dev/null 2>&1 3>&- || true
}
# --delete-convo ID (devdesk#61): permanently delete a conversation's local files
# (the transcript ~/.claude/projects/<folder>/<id>.jsonl and its <id>/ folder of
# subagent transcripts and tool results). Refused while a running session uses
# it. Dormant sessions that would resume it forget it (they start fresh).
# Copies kept by Anthropic (Remote Control, the API) are not touched: those are
# deleted at claude.ai.
cmd_delete_convo() {
[ $# -eq 1 ] || dd_die "usage: devdesk attach --delete-convo ID"
local id=$1 file dir other
[[ $id =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ ]] || dd_die "bad conversation id: $id"
file=$(dd_convo_file "$id") || true
{ [ -n "$file" ] && [ -f "$file" ]; } || dd_die "no conversation $id"
case "$file" in "$(dd_projects_dir)"/*/"$id.jsonl") ;; *) dd_die "unexpected path: $file" ;; esac
for other in $(jq -rM --arg id "$id" '.sessions | to_entries[] | select(.value.claude_session_id == $id) | .key' "$DEVDESK_REGISTRY" 2>/dev/null); do
if dd_server_up && dd_tmux has-session -t "=$other" 2>/dev/null; then
dd_die "session $other is using this conversation: end it first"
fi
done
dir=${file%.jsonl}
rm -f -- "$file"
[ ! -d "$dir" ] || rm -rf -- "$dir"
# shellcheck disable=SC2016 # jq variables
dd_registry_update '.sessions |= with_entries(if .value.claude_session_id == $id then .value |= (del(.claude_session_id) | del(.claude_source)) else . end)' \
--arg id "$id"
jq -cMn --arg id "$id" '{ok: true, deleted: $id}'
}
+12
View File
@@ -183,6 +183,18 @@ dd_registry_set_dir() {
--arg n "$1" --arg d "$2" --arg t "$(date -Is)"
}
# Remote Control for session NAME (devdesk#61): its own choice if it made one,
# else the default set in Settings (state settings.json), else
# DEVDESK_REMOTE_CONTROL from the env files. Prints 1 or 0.
dd_rc_wanted() {
local own def
# (not dd_registry_get: its `// empty` would turn false into "unset")
own=$(jq -Mr --arg n "$1" '.sessions[$n].remote_control | if . == null then empty else tostring end' "$DEVDESK_REGISTRY" 2>/dev/null)
case $own in true) echo 1; return ;; false) echo 0; return ;; esac
def=$(jq -rM '.remote_control_default // empty' "$DEVDESK_STATE_DIR/settings.json" 2>/dev/null)
case $def in true) echo 1 ;; false) echo 0 ;; *) [ "${DEVDESK_REMOTE_CONTROL:-0}" = 1 ] && echo 1 || echo 0 ;; esac
}
dd_registry_set_claude() {
dd_registry_update '.sessions[$n] = ((.sessions[$n] // {}) + {claude_session_id: $id, claude_source: $src, updated: $t})' \
--arg n "$1" --arg id "$2" --arg src "$3" --arg t "$(date -Is)"