feat: mark remote sessions as experimental#17
Merged
gavin-jeong merged 62 commits intomasterfrom Apr 2, 2026
Merged
Conversation
…ons, badge toggle - Unified config file (~/.config/ccx/config.yaml) with keybindings, preferences, and shortcuts - Number key shortcuts (1-9) scoped by view + focus side with sensible defaults - View state persistence: group/preview/view mode, detail level, split ratio auto-saved on quit - Memory import from worktree (M action) and memory removal (X action) - Badge toggle via :badge:toggle command, persisted in preferences - Worktree detection fallback for cleaned-up worktrees - Conversation detail:text/tool/hook commands - Live preview restore fix (async pane lookup from Update path) - Help modal alignment fix (wider modal, shortcuts section) - Diff rendering for Edit/Write tool blocks
…ments, fork action Phase 1 - Smart chain-mode filter: - In chain/tree/fork/repo group modes, filter preserves parent-child relationships - Parent match keeps all children visible; child match keeps parent visible Phase 2 - Base-project group mode (group:repo): - Groups sessions by base repository using git worktree info - ResolveBaseRepo reads .git file to find main repo (not just path matching) - Works for external worktrees outside the repo directory - Uses configurable worktreeDir from preferences Search/filter improvements: - proj:<name> filter for sessions - Conversation filter now includes tool names (tool:Read, tool:Bash) - Selection preserved when clearing filter (Esc) - Filter term persisted across restarts Other: - Fork session action (F in actions menu) - Editor input mode persistence (ctrl+e toggles, saved in preferences) - Memory import hint shows for all worktree sessions - Config explorer shows KEYMAPS and SHORTCUTS categories - Badge toggle, config:edit, detail commands, fillKeymapDefaults on save
…rrow, design docs
Phase 3 - Worktree alignment:
- :worktree:align (:wt:align) detects worktrees not under configured dir
- Lists misaligned worktrees via git worktree list --porcelain
- Moves selected worktrees via git worktree move
- Updates in-memory session paths after move
Phase 4 - Session/worktree creation:
- :new (:n) opens new Claude session in project dir (tmux window or exec)
- :worktree:new (:wt:new) <branch> creates git worktree + new session
- NewWindowClaudeNew tmux helper for fresh sessions
Smart left arrow:
- In live pane preview, left arrow at cursor column 0 escapes to list
- Uses tmux display-message #{cursor_x} to detect cursor position
- Normal left arrow forwarded when cursor can move
Design documents:
- docs/design-image-rendering.md - Kitty graphics protocol modal
- docs/design-remote-execution.md - K8s pod execution architecture
- docs/design-multi-session-orchestration.md - Multi-session DAG orchestration
…flow - Press x → n on any session to create a new session in the same project - Prompted for branch name: enter name = create worktree + new session, empty = new session in main project dir - Separate from w (worktree) which moves existing session - Also supports :new <path> command for arbitrary directories - Help line shows context-sensitive hint for the input prompt
- Auto-refresh session list 2s after spawning new session/worktree - delayedRefreshMsg triggers doRefresh() to pick up new sessions - Non-git projects skip branch prompt, create session directly - Git repos show branch prompt (worktree-first workflow)
When task directory files are cleaned up after completion, the task preview now falls back to parsing TaskCreate/TaskUpdate tool_use entries from the JSONL conversation data. Shows "(from conversation)" label to distinguish from active/ongoing tasks.
New package internal/remote/ for executing Claude Code on K8s pods: - config.go: RemoteConfig with defaults and validation - pod.go: Pod spec generation, create/delete/wait via CLI - sync.go: Config tarball (CLAUDE.md, settings, memory) upload - stream.go: JSONL streaming from pod via logs -f - session.go: Full lifecycle orchestrator (auth, pod, config, stream) TUI integration: - :remote:start <context> <repo> [branch] [prompt] - create pod and stream - :remote:stop - stop session and delete pod - Stream content displayed in session preview pane - Auth via macOS Keychain OAuth token injection Also: moved keymaps under keymaps section in config.yaml
…sync
Remote execution improvements:
- Sync local workdir to pod via tar (respects .gitignore via git ls-files)
- Falls back to git clone when no local dir specified
- Configurable env vars (env_vars map) and local env mirroring (mirror_env list)
- Full Claude config sync: settings, memory, skills, agents, commands,
contexts, rules, hooks, and project-specific config
- Usage: :remote:start <context> [prompt] (uses selected session's project)
Config example in config.yaml:
remote:
env_vars:
AWS_PROFILE: mesg-prod
KUBECONFIG: /path/to/kubeconfig
mirror_env: [AWS_PROFILE, AWS_REGION, GITHUB_TOKEN]
Redesigned remote execution: - Single container pod (sleep infinity) — exec into it for setup and Claude - Progress reporting during each step (auth, pod create, install, sync) - Interactive Claude via tea.ExecProcess (takes over terminal like $EDITOR) - :remote:start [prompt] — uses current context, selected session for resume - :remote:attach — reattach to running remote Claude - :remote:stop — delete pod - Auto-detects current context (no arg needed) - Session JSONL synced for --resume support - Full config sync: skills, agents, hooks, memory, commands, contexts, rules
Remote sessions now appear as first-class items in the session list: 1. :remote:start creates pod and inserts virtual [LIVE] session at top 2. Preview pane tracks setup progress (auth, pod, install, sync) 3. Once Claude starts, JSONL output streams to live preview 4. :remote:attach opens interactive Claude (takes over terminal) 5. :remote:stop deletes pod and removes virtual session Setup steps channel tracked separately from stream channel. Virtual sessions have IsRemote=true, RemotePodName, RemoteStatus fields.
- Remote sessions saved to ~/.config/ccx/remote-sessions.yaml - Restored as virtual items on ccx startup - Status updates persisted (starting, running, stopped, failed) - Removed from disk on :remote:stop - Filterable with / search: is:remote, pod name, status
- :remote:stop on saved/restored sessions (no active in-memory session) now reads saved config to delete the pod from the cluster - Works on selected remote session even after ccx restart - Added is:remote to search filter hints in help modal
- R key in actions menu starts remote execution for selected session - Shows R:remote hint in actions hint box - Auto-cleanup on startup: checks pod phase via cluster API - Running/Pending pods kept - Succeeded/Failed/Unknown pods removed from saved sessions - Cluster unreachable: session kept (no blind deletion) - Added PodPhase() to remote/pod.go
…re start 1. Default image changed from node:22-slim to ubuntu:24.04 - Installs Node.js + git + Claude Code in the pod setup step 2. Remote sessions no longer show [LIVE] badge — show [R] (purple) instead 3. Before starting remote, shows confirmation with context/namespace - "Remote → context/namespace? (y/n)" — press y to proceed, any other key cancels
…m, correct selection Issues fixed: 1. Confirmation now shows "Start remote on <context>/<namespace>? (y/n)" with the actual cluster context prominently displayed 2. Session info (project path, session ID) captured at confirm time, not re-read after y press (prevents wrong session pickup) 3. Guard prevents creating multiple remote sessions — must :remote:stop first 4. Progress steps accumulate correctly (previous shown as ✓, current as ◉) 5. Preview updates use helper to check selected session matches 6. Cleaned up duplicate code paths in the full rewrite
Preview flickering fix: - Remote preview only calls SetContent when cacheKey changes - Render path skips re-setting content for remote sessions entirely - CacheKey set to "remote:<id>" prevents conversation loader from overriding Delete persistence fix: - Deleting remote session via 'd' action now also: - Stops active remote session (if matching) - Deletes pod from cluster (for saved sessions) - Removes from remote-sessions.yaml - Works for both active and persisted remote sessions
Remote sessions now have their own preview type (sessPreviewRemote): - Automatically activated when a remote session is selected - Never overridden by conversation/stats/memory preview loading - Resize only updates viewport dimensions, doesn't reload content - Skipped in tab cycling (like sessPreviewLive) - Content managed exclusively by remote progress/stream handlers
- Enter on a remote session opens interactive Claude (takes over terminal) - L (Live) on a remote session also attaches interactively - Works for both active sessions and saved/restored ones - Saved sessions use stored context/namespace/pod to build exec command - Returns to ccx when Claude exits (pod stays running)
Remote sessions now support conversation, stats, memory, and tasks preview modes — same as local sessions: - Streamed JSONL output written to temp file as it arrives - Virtual session's FilePath set to temp file path - During setup: shows progress view (sessPreviewRemote) - Once streaming: normal preview modes work (tab to cycle) - Conversation preview auto-refreshes on new data - Temp file cleaned up on :remote:stop
- L key on remote sessions opens/refreshes preview (not attach) - Enter key still attaches interactively - claude_args config: extra CLI args for remote Claude (e.g. --model, --allowedTools, --permission-mode) - buildClaudeCmd helper used by both streaming and attach - Config example: claude_args: ["--permission-mode", "bypassPermissions"]
Folded summaries: - Bash: $ command (yellow, with description prefix) - Read: ~/path L10-30 (with line range) - Grep: /pattern/ path glob - Glob: pattern path - Agent: subagent_type description Expanded view: - Bash: # description + $ command lines (multi-line support) Updated tests and golden files for new tool formatting.
- text → compact (text only) - tool → standard (text + tools) - hook → verbose (text + tools + hooks) Commands: :detail:compact, :detail:standard, :detail:verbose Old names still work as aliases (detail:text, detail:tool, detail:hook) Status bar shows COMPACT/STANDARD/VERBOSE Shortcuts updated: 1=compact, 2=standard, 3=verbose conv_detail_level persisted across restarts (already was)
…changes - Number key shortcuts (1:conv 2:stats etc.) shown in the session help line - Changing group mode (Tab/G) preserves the active search filter - Filter is saved before rebuild and reapplied to the new list
Add [R·exp] badge, (experimental) label in progress view, and (exp) suffix in filter hints to signal remote session support is experimental.
dikpaal
approved these changes
Apr 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
[R·exp]badge for remote sessions (was[R])(experimental)label in remote session progress viewTest plan
[R·exp]badge renders on remote sessions in session listis:remotefilter hint shows "(exp)" suffix