From 27752a41d1aa4678538e59f8d48d087ee973c5c3 Mon Sep 17 00:00:00 2001 From: "Jinwook Jeong (Edgar)" Date: Sun, 8 Mar 2026 20:26:08 +0900 Subject: [PATCH] feat: full session deletion and CLAUDE_CONFIG_DIR support Delete associated data (subagent transcripts, file-history, tasks) when deleting a session, not just the conversation JSONL. Also respect CLAUDE_CONFIG_DIR env var for locating the Claude data directory. Co-Authored-By: Claude Opus 4.6 --- README.md | 5 +++++ internal/session/scanner.go | 3 +++ internal/tui/app.go | 4 ++++ main.go | 12 ++++++++++++ 4 files changed, 24 insertions(+) diff --git a/README.md b/README.md index f93b4e3..f2d6a9f 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,11 @@ ccx # launch TUI ccx --version # print version ``` +The Claude data directory is resolved in this order: +1. `--dir` flag +2. `CLAUDE_CONFIG_DIR` environment variable +3. `~/.claude` (default) + ## Features ### Session Browser diff --git a/internal/session/scanner.go b/internal/session/scanner.go index bfdd3fd..4b03ea8 100644 --- a/internal/session/scanner.go +++ b/internal/session/scanner.go @@ -47,6 +47,9 @@ var ( // ScanSessions scans for Claude Code sessions. If claudeDir is empty, // defaults to ~/.claude. func ScanSessions(claudeDir string) ([]Session, error) { + if claudeDir == "" { + claudeDir = os.Getenv("CLAUDE_CONFIG_DIR") + } if claudeDir == "" { home, err := os.UserHomeDir() if err != nil { diff --git a/internal/tui/app.go b/internal/tui/app.go index 7bf3fb3..4e523a8 100644 --- a/internal/tui/app.go +++ b/internal/tui/app.go @@ -205,6 +205,7 @@ const ( // Config holds application configuration from CLI flags. type Config struct { + ClaudeDir string // path to Claude data directory (e.g. ~/.claude) TmuxEnabled bool // enable tmux integration (I, J, live modal) TmuxAutoLive bool // auto-enter live session in same tmux window on startup WorktreeDir string // subdirectory name for worktrees (default ".worktree") @@ -1090,6 +1091,9 @@ func (a *App) deleteSession(sess session.Session) (tea.Model, tea.Cmd) { a.copiedMsg = "Delete failed: " + err.Error() return a, nil } + os.RemoveAll(filepath.Join(filepath.Dir(sess.FilePath), sess.ID)) + os.RemoveAll(filepath.Join(a.config.ClaudeDir, "file-history", sess.ID)) + os.RemoveAll(filepath.Join(a.config.ClaudeDir, "tasks", sess.ID)) // Remove from in-memory list and update the list widget idx := a.sessionList.Index() diff --git a/main.go b/main.go index 9f3bce7..1e37ffc 100644 --- a/main.go +++ b/main.go @@ -42,6 +42,17 @@ func main() { os.Exit(0) } + if claudeDir == "" { + claudeDir = os.Getenv("CLAUDE_CONFIG_DIR") + } + if claudeDir == "" { + home, err := os.UserHomeDir() + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } + claudeDir = home + "/.claude" + } sessions, err := session.ScanSessions(claudeDir) if err != nil { fmt.Fprintf(os.Stderr, "Error scanning sessions: %v\n", err) @@ -63,6 +74,7 @@ func main() { } app := tui.NewApp(sessions, tui.Config{ + ClaudeDir: claudeDir, TmuxEnabled: tmuxEnabled, TmuxAutoLive: tmuxAutoLive, WorktreeDir: worktreeDir,