No description
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
sam b8f1794d8a forward arguments after -- to claude
cmd_tmp already appended an args.claude_args to the command line, but no
parser ever defined it: the only caller passed a hardcoded empty list, so
`sxcc --tmp -- --model opus` died on the very flag it was meant to hand
over. The other three call sites built the command line without it at all.

argv is now split at the first `--` before argparse runs, since argparse
would claim those flags as sxcc's own, and the tail reaches all four
invocations. Flags pass unfiltered — whether one makes sense next to
--resume is claude's call, and a filter here would only go stale.

Passing them to a subcommand that never launches claude is an error rather
than a silent drop.
2026-09-25 19:38:32 +02:00
.gitignore route every invocation through one parser 2026-09-03 21:46:54 +02:00
install route every invocation through one parser 2026-09-03 21:46:54 +02:00
LICENSE update 2026-05-10 22:22:57 +02:00
README.md forward arguments after -- to claude 2026-09-25 19:38:32 +02:00
sxcc forward arguments after -- to claude 2026-09-25 19:38:32 +02:00

sxcc — snix Claude Code

A command-line tool to manage Claude Code projects, sessions, memory files, and configuration.

Requirements

  • Python 3.10+
  • rich: pip install rich

Installation

curl -sL https://sh.snix.me/sxcc | sh

The installer writes sxcc to /usr/local/bin by default; pass a directory to install elsewhere:

curl -sL https://sh.snix.me/sxcc | sh -s ~/.local/bin

sxcc reads what Claude Code has already written, so on a machine where no session has ever run there is nothing to read: Claude Code creates ~/.claude/projects/ when the first session starts. Until then the commands that read data answer No sessions found. and exit 1. sxcc, sxcc --tmp and sxcc version work regardless — the first two are what create the directory in the first place.

The same message appears when CLAUDE_CONF or --conf points somewhere without a .claude/, which is worth checking first if a machine that does have sessions reports none.

Usage

Naming a project

Commands that take a project — run, sessions, show, stats, rename — accept the same forms and resolve them the same way. Matches are ranked by how precisely they identify one project:

Rank Matches
1 Full MD5 hash, or the exact absolute path
2 Hash prefix, at least 6 characters
3 Exact directory name — myproject for /home/sam/code/myproject
4 Exact /rename title
5 Directory name or path prefix
6 Partial title

Only the strongest rank is considered, so an exact directory name is never shadowed by another project that happens to carry it as a title. If two projects tie there, a selection list is shown — except when the output is JSON or the command runs under --force, where the ambiguity is reported along with the hashes instead of blocking on a prompt.

Short hash prefixes are refused below 6 characters, since they collide often enough that a typo would select a neighbouring project.

The destructive commands are stricter: delete and merge accept only an exact, unambiguous identifier, and all three of move, merge and delete can be rehearsed first with --dry-run.

Launch Claude (run)

sxcc                        # launch claude in current directory
sxcc --tmp                  # launch in a temporary session (auto-deleted on exit)
sxcc myproject              # resume latest session of project "myproject"
sxcc myproject --num 3      # resume 3rd oldest session of project "myproject"
sxcc <session-id>           # resume a specific session by ID
sxcc run myproject          # explicit run (use when project name matches a subcommand)
sxcc run --tmp              # explicit temporary session

A session ID is resolved as a session; anything else names a project (see Naming a project).

Anything after -- goes to claude itself:

sxcc -- --model opus                  # new session, with claude's own flags
sxcc myproject -- --model opus        # resume, with flags
sxcc --tmp -- --add-dir /elsewhere    # temporary session, with flags

They are forwarded unfiltered — whether a flag makes sense alongside --resume is claude's judgement, not sxcc's. Passing them to a command that does not launch claude is an error rather than silently ignored.

After each session, allowedTools is automatically reset in ~/.claude.json.

Each temporary session runs in its own subdirectory /tmp/claude-tmp/<uuid>, so multiple --tmp sessions can run concurrently. On exit it cleans up its own /tmp/claude-tmp/<uuid>, the matching ~/.claude/projects/-tmp-claude-tmp-<uuid> and ~/.cache/claude-cli-nodejs/ directories, and the project entry in ~/.claude.json; the shared /tmp/claude-tmp parent is removed only when empty.

The cleanup runs on a normal exit, on Ctrl-C, and on SIGTERM — closing the terminal or logging out included. Only SIGKILL can bypass it, and the next --tmp run clears whatever a killed one left behind.

List projects

sxcc list                   # list all projects with memory count and last title
sxcc list --json

A project whose sessions are gone but whose memory files remain is listed as ! no sessions. Its path column shows the encoded directory name, since the real path is read from the sessions and there are none left. sxcc delete <hash> removes such a project and its memories.

Sessions

sxcc sessions               # sessions for current project
sxcc sessions myproject     # sessions for project "myproject", grouped by cwd
sxcc sessions --json

See Naming a project for what the argument accepts.

Show session details

sxcc show                        # details of latest session in current project
sxcc show myproject              # latest session of project "myproject"
sxcc show <session-id>           # specific session
sxcc show myproject --memory     # include project memories
sxcc show --json

Dump transcript

sxcc dump <session-id>              # full transcript
sxcc dump <session-id> --user       # only user messages
sxcc dump <session-id> --claude     # only Claude messages
sxcc dump <session-id> --no-tools   # hide tool calls
sxcc dump <session-id> --grep text  # filter by content
sxcc dump <session-id> --msg 5      # show message #5
sxcc dump <session-id> --msg 3-7    # show messages #3 to #7
sxcc dump <session-id> --json

dump takes a session ID, and a leading fragment of one is enough — the eight characters sxcc history prints will do.

Stats

sxcc stats                   # token usage and cost for all projects
sxcc stats myproject         # stats per session for a specific project
sxcc stats <session-id>      # stats for a single session
sxcc stats --all             # include projects with zero tokens
sxcc stats --json

Prices are fetched from LiteLLM and cached for 24h in /tmp/lite_llm_prices.json.

History (search every prompt)

sxcc history firewall              # every prompt containing "firewall"
sxcc history --project dnsleak     # every prompt from a project
sxcc history --session <id>        # every prompt from one session
sxcc history                       # the most recent prompts
sxcc history firewall --full       # full text, with pasted blocks
sxcc history firewall -n 100       # at most 100 results (default 40)
sxcc history --json

Searches ~/.claude/history.jsonl, which Claude Code keeps across every project and which outlives the transcripts — most of what it holds belongs to sessions that have since been deleted. Session ids shown in yellow no longer exist: those prompts are all that remains of them. For the ones that do, take the id to sxcc dump.

Only your side of the conversation is recorded there — no replies, no tool calls. Pasted blocks are stored separately and pruned over time; --full prints them where they survive and says so where they do not.

Rename (set title on all sessions)

sxcc rename myproject "new title"

Sets the /rename title on all sessions of a project at once. The project can be named any of the ways above, or by one of its session IDs.

Move (copy project with new path)

sxcc move /path/to/myproject /path/to/myproject-new            # copy project, keep original
sxcc move /path/to/myproject /path/to/myproject-new --delete   # delete source after move
sxcc move /path/to/myproject /path/to/myproject-new --force    # skip confirmation
sxcc move /path/to/myproject /path/to/myproject-new --dry-run  # show what would happen
sxcc move <session-id> /path/to/newproject                     # copy session to new project
sxcc move <session-id> /path/to/newproject --delete            # move session (remove from source)

Copies the project folder (or session) in ~/.claude/projects/ to the new encoded path and rewrites the cwd in all session files. If the destination project already exists when moving a single session, the session is added to it.

Merge

sxcc merge <src> <dst>           # merge src sessions into dst
sxcc merge <src> <dst> --delete  # delete source after merge
sxcc merge <src> <dst> --force   # skip confirmation
sxcc merge <src> <dst> --dry-run # show what would happen

src and dst accept: absolute path, project hash (MD5), or session ID.

Delete

sxcc delete <session-id>                                          # delete a single session
sxcc delete <project-hash>                                        # delete all sessions of a project
sxcc delete <project-hash> --keep <session-id-1> <session-id-2>  # keep listed sessions
sxcc delete <project-hash> --force                                # skip confirmation
sxcc delete <project-hash> --dry-run                              # show what would happen

Deleting a session also removes what Claude Code stores for it outside the project folder: ~/.claude/file-history/<session-id>, which holds the previous versions of every file that session edited and is usually the largest part, and ~/.claude/session-env/<session-id>. The confirmation names their total size before anything is removed.

Deleting every session of a project removes the project itself: its folder in ~/.claude/projects/, the memory files under it, and its entry in ~/.claude.json. The same happens when the session you delete is the last one left. With --keep, the project survives and so do its memories — they belong to the project, not to the sessions being removed.

Use sxcc list to find the project hash. Unlike the other commands, delete takes only a full 32-character hash or an exact session ID — deliberately, so a partial name cannot wipe a project that merely resembles the one you meant. merge is restricted the same way, to an absolute path, a full hash, or a session ID.

Automatically updates ~/.claude.json: removes the project entry if no sessions remain, or updates last* fields if some sessions are kept.

Dry run

move, merge, and delete take --dry-run. The command resolves its arguments and reports exactly what it would do, then stops before writing anything:

$ sxcc delete 1f7709c6ff2d65bac115f71839344059 --dry-run

Sessions to delete (3):
  44444444-1111-1111-1111-111111111111  2026-09-03 22:17  184.2K
  33333333-1111-1111-1111-111111111111  2026-09-02 09:41  12.9K
  55555555-1111-1111-1111-111111111111  2026-08-30 18:03  1.1K

Dry run: 3 session(s) would be deleted. Nothing was changed.

move also names the working directory it would rename, which is the part of the operation that happens outside ~/.claude:

$ sxcc move /home/sam/code/myproject /home/sam/code/renamed --dry-run
Source:      ~/.claude/projects/-home-sam-code-myproject
Destination: ~/.claude/projects/-home-sam-code-renamed
Directory will be renamed: /home/sam/code/myproject → /home/sam/code/renamed
Dry run: 3 session(s) would be copied to
~/.claude/projects/-home-sam-code-renamed, and /home/sam/code/myproject
renamed to /home/sam/code/renamed. Nothing was changed.

--dry-run takes precedence over --force: passing both still changes nothing. Without either flag, these commands ask for confirmation.

Config

sxcc config                      # global Claude Code configuration overview
sxcc config projects             # list all projects from ~/.claude.json
sxcc config project myproject    # configuration for a specific project
sxcc config --json

Shell completion

sxcc config bash                 # print the bash completion script
sxcc config zsh                  # print the zsh completion script

Completes subcommands, flags, and the project names, hashes, and session IDs taken from your own data. To enable it, add to ~/.bashrc:

source <(sxcc config bash)

or to ~/.zshrc:

source <(sxcc config zsh)

Version

sxcc version

Configuration

Environment variable Default Description
CLAUDE_CONF ~ Base directory containing .claude/

Or use --conf <dir>, which accepts ~, ~/.claude, or ~/.claude/projects and works either before or after the subcommand. It redirects everything sxcc touches: .claude/projects/, .claude.json, .claude/history.jsonl, and the .cache/claude-cli-nodejs/ directories that --tmp cleans up.

The reading commands — list, sessions, show, dump, stats, history, config — take -j/--json. Output is highlighted on a terminal and written plain when redirected, so sxcc list --json | jq and sxcc list --json > file behave as expected.

history.jsonl is only ever read, never written. The two commands that reach outside ~/.claude say so where they are documented: move renames the working directory itself, and --tmp removes its own /tmp/claude-tmp/<uuid> and cache directory on exit.

License

GNU General Public License v3.0 — see LICENSE.