feat: v0.12.0 Settings window, per-session Remote Control, delete conversations
- 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:
+79
-2
@@ -80,6 +80,8 @@ cmd_list() {
|
||||
--argjson ctx "$(per_session_json "$DEVDESK_CONTEXT_DIR")" \
|
||||
--argjson st "$(per_session_json "$DEVDESK_STATUS_DIR")" \
|
||||
--argjson tags "$(per_session_json "$DEVDESK_STATE_DIR/tags")" \
|
||||
--arg rclive "$(dd_rc_live)" \
|
||||
--argjson rcdef "$(dd_rc_default)" \
|
||||
--arg dflt "$DEVDESK_DEFAULT_SESSION" \
|
||||
--arg root "$DEVDESK_PROJECTS_ROOT" '
|
||||
def rows($s): $s | split("\n") | map(select(length > 0) | split("\t"));
|
||||
@@ -98,7 +100,10 @@ cmd_list() {
|
||||
activity: null, windows: 0,
|
||||
claude_session_id: (.value.claude_session_id // null),
|
||||
worktree: (.value.worktree // null)}))
|
||||
) | map(. + {context: ($ctx[.name] // null), status: ($st[.name] // null), tags: ($tags[.name].hosts // [])}),
|
||||
) | map(. + {context: ($ctx[.name] // null), status: ($st[.name] // null), tags: ($tags[.name].hosts // []),
|
||||
remote_control: (($known[.name].remote_control) as $own | if $own == null then $rcdef else $own end),
|
||||
rc_active: (.name as $n | $rclive | split("\n") | any(.[]; . == $n))}),
|
||||
remote_control_default: $rcdef,
|
||||
projects: ([{name: $dflt, dir: $root}]
|
||||
+ [rows($proj)[] | {name: .[0], git: (.[1] == "1"), dir: (.[2:] | join("\t"))}
|
||||
| select(.name | test("^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$"))])}'
|
||||
@@ -203,6 +208,78 @@ cmd_unsplit() {
|
||||
jq -cMn --argjson c "$closed" '{ok: true, closed: $c}'
|
||||
}
|
||||
|
||||
# Sessions whose running Claude has Remote Control on, read from the processes
|
||||
# themselves (devdesk#61), one name per line.
|
||||
dd_rc_live() {
|
||||
local session window pid child
|
||||
dd_server_up || return 0
|
||||
while IFS=$'\t' read -r session window pid; do
|
||||
[ "$window" = claude ] || continue
|
||||
for child in $(pgrep -P "$pid" 2>/dev/null); do
|
||||
if tr '\0' '\n' <"/proc/$child/cmdline" 2>/dev/null | grep -qx -- --remote-control; then
|
||||
printf '%s\n' "$session"
|
||||
break
|
||||
fi
|
||||
done
|
||||
done < <(dd_tmux list-panes -a -F $'#{session_name}\t#{window_name}\t#{pane_pid}' 2>/dev/null)
|
||||
}
|
||||
|
||||
# The Claude process of a session's claude window, if any.
|
||||
dd_claude_pid() {
|
||||
local pid
|
||||
pid=$(dd_tmux list-panes -t "=$1:claude" -F '#{pane_pid}' 2>/dev/null | head -n1)
|
||||
[ -n "$pid" ] && pgrep -P "$pid" 2>/dev/null | head -n1
|
||||
}
|
||||
|
||||
# --remote-control NAME on|off (devdesk#61): the session's own choice. A running,
|
||||
# idle Claude restarts on the same conversation right away; one that is working
|
||||
# or waiting gets it at its next start. Prints {ok, remote_control, applied}.
|
||||
cmd_remote_control() {
|
||||
[ $# -eq 2 ] || dd_die "usage: devdesk attach --remote-control NAME on|off"
|
||||
local name=$1 value applied=saved pid state
|
||||
dd_valid_name "$name" || dd_die "invalid session name: $name"
|
||||
case $2 in on) value=true ;; off) value=false ;; *) dd_die "on or off" ;; esac
|
||||
{ session_exists "$name"; } || dd_die "no session named '$name'"
|
||||
# shellcheck disable=SC2016 # jq variables
|
||||
dd_registry_update '.sessions[$n] = ((.sessions[$n] // {}) + {remote_control: ($v == "true")})' --arg n "$name" --arg v "$value"
|
||||
if dd_server_up && dd_tmux has-session -t "=$name" 2>/dev/null && pid=$(dd_claude_pid "$name") && [ -n "$pid" ]; then
|
||||
state=$(jq -rM '.state // empty' "$DEVDESK_STATUS_DIR/$name.json" 2>/dev/null) || state="" # no state yet: idle
|
||||
if [ "$state" = working ] || [ "$state" = waiting ]; then
|
||||
applied=next-start
|
||||
else
|
||||
mkdir -p "$DEVDESK_STATE_DIR/restart"
|
||||
touch "$DEVDESK_STATE_DIR/restart/$name"
|
||||
kill -TERM "$pid" 2>/dev/null || true
|
||||
applied=now
|
||||
fi
|
||||
fi
|
||||
jq -cMn --argjson v "$value" --arg a "$applied" '{ok: true, remote_control: $v, applied: $a}'
|
||||
}
|
||||
|
||||
# Remote Control default for new sessions: Settings, else DEVDESK_REMOTE_CONTROL. true/false.
|
||||
dd_rc_default() {
|
||||
local def
|
||||
def=$(jq -rM '.remote_control_default | if . == null then empty else tostring end' "$DEVDESK_STATE_DIR/settings.json" 2>/dev/null)
|
||||
if [ -n "$def" ]; then echo "$def"; elif [ "${DEVDESK_REMOTE_CONTROL:-0}" = 1 ]; then echo true; else echo false; fi
|
||||
}
|
||||
|
||||
# --settings [remote-control-default on|off] (devdesk#61): DevDesk-wide settings
|
||||
# kept in $DEVDESK_STATE_DIR/settings.json; prints them.
|
||||
cmd_settings() {
|
||||
local file="$DEVDESK_STATE_DIR/settings.json" tmp
|
||||
if [ $# -eq 2 ]; then
|
||||
[ "$1" = remote-control-default ] || dd_die "unknown setting: $1"
|
||||
case $2 in on | off) ;; *) dd_die "on or off" ;; esac
|
||||
tmp=$(mktemp "$DEVDESK_STATE_DIR/.settings.XXXXXX")
|
||||
jq -cM --argjson v "$([ "$2" = on ] && echo true || echo false)" '. + {remote_control_default: $v}' "$file" 2>/dev/null >"$tmp" ||
|
||||
jq -cMn --argjson v "$([ "$2" = on ] && echo true || echo false)" '{remote_control_default: $v}' >"$tmp"
|
||||
mv -f "$tmp" "$file"
|
||||
elif [ $# -ne 0 ]; then
|
||||
dd_die "usage: devdesk attach --settings [remote-control-default on|off]"
|
||||
fi
|
||||
jq -cMn --argjson d "$(dd_rc_default)" '{ok: true, remote_control_default: $d}'
|
||||
}
|
||||
|
||||
cmd_rename() {
|
||||
[ $# -eq 2 ] || dd_die "usage: devdesk rename OLD NEW"
|
||||
local old=$1 new=$2 running=0
|
||||
@@ -388,7 +465,7 @@ cmd_attach() {
|
||||
dd_linger
|
||||
return
|
||||
;;
|
||||
--peek | --search | --last-reply | --unsplit)
|
||||
--peek | --search | --last-reply | --unsplit | --remote-control | --settings | --delete-convo)
|
||||
local action=${1#--}
|
||||
shift
|
||||
"cmd_${action//-/_}" "$@"
|
||||
|
||||
Reference in New Issue
Block a user