https://github.com/fgrehm/clotilde
A CLI for managing named Claude Code sessions, with support for forking.
https://github.com/fgrehm/clotilde
Last synced: 4 months ago
JSON representation
A CLI for managing named Claude Code sessions, with support for forking.
- Host: GitHub
- URL: https://github.com/fgrehm/clotilde
- Owner: fgrehm
- License: mit
- Created: 2025-12-02T10:50:40.000Z (7 months ago)
- Default Branch: main
- Last Pushed: 2025-12-04T17:18:26.000Z (6 months ago)
- Last Synced: 2025-12-08T01:28:36.473Z (6 months ago)
- Language: Go
- Size: 140 KB
- Stars: 9
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Roadmap: docs/ROADMAP.md
Awesome Lists containing this project
README
# Clotilde
Named sessions, profiles, and context management for Claude Code.
> **Documentation**: For the latest stable release, see [Clotilde on the `stable` branch](https://github.com/fgrehm/clotilde/tree/stable). This `main` branch contains development changes and may include features not yet released.
## About the Name
A traditional Brazilian name - sometimes considered old-fashioned or humorous - which adds a light, unpretentious personality to the tool. Pronounced more or less like **KLOH-teel-dee** (Portuguese-ish).
## Why?
Claude Code is great for single conversations, but as you start juggling multiple parallel sessions in the same project, things get painful:
- **Session naming is unreliable**: Claude Code has `/rename`, but names don't persist across resumes, can't be used with `--resume `, and get overwritten by auto-generated slugs. There's no way to name a session at startup either.
- **The resume picker doesn't scale**: Fine for 2-3 sessions, but with more it shows unhelpful text like "This session is being continued from a previous conversation that ran out of context..." Which one was your auth work again?
- **No per-session configuration**: Want to use Haiku for a quick question and Opus for deep feature work? You have to change settings globally or pass flags every time.
- **No persistent context injection**: There's no built-in way to feed the same background context (ticket info, project conventions, task goals) into every session automatically.
- **Forking is low-level**: `--fork-session` and `/fork` exist but require knowing UUIDs, have no named fork tracking, and don't record parent/child relationships. There's no way to fork by name.
## What Clotilde does
Clotilde is a thin wrapper around Claude Code that adds named sessions, profiles, context management, and user-friendly forking.
```bash
# Named sessions you can instantly switch between
clotilde start auth-feature
clotilde start bugfix-db-timeout
clotilde resume auth-feature
# Fork a session to explore a tangent
clotilde fork auth-feature auth-alternative-approach
# Incognito sessions that auto-delete on exit
clotilde incognito quick-question
# Profiles for different workflows
clotilde start review --profile strict # deny Bash/Write permissions
clotilde start spike --profile quick # use Haiku, bypass permissions
```
Session names are stored as external name-to-UUID mappings, so they work reliably regardless of Claude Code's internal naming behavior. Profiles let you define reusable presets (model, permissions, output style) in a single config file. Context files are automatically injected at session start via hooks.
## How It Works
Clotilde never patches or modifies Claude Code.
- Each session is a folder in `.claude/clotilde/sessions//` containing metadata, optional settings, and system prompt files
- SessionStart hooks handle fork registration, `/clear` UUID tracking, and context injection
- Claude Code is invoked with `--session-id`, `--resume`, `--settings`, and `--append-system-prompt-file` flags
**Note on worktrees:** Since `.claude/clotilde/` lives in each worktree's `.claude/` directory, each worktree gets its own independent sessions and context. Use worktrees for major branches/features, use Clotilde for managing multiple conversations within each worktree.
## Installation
**Download binary** (recommended)
Download the latest release for your platform from [GitHub Releases](https://github.com/fgrehm/clotilde/releases).
**Go install:**
```bash
go install github.com/fgrehm/clotilde@latest
```
**Build from source:**
```bash
git clone https://github.com/fgrehm/clotilde
cd clotilde
make build
make install # Installs to ~/.local/bin
```
## Quick Start
```bash
# Initialize in your project
clotilde init
# Start a new named session
clotilde start auth-feature
# Resume it later
clotilde resume auth-feature
# List all sessions
clotilde list
# Inspect a session
clotilde inspect auth-feature
# Fork a session to try something different
clotilde fork auth-feature experiment
# Delete when done
clotilde delete experiment
```
## Incognito Sessions
Incognito sessions automatically delete themselves when you exit. See [`clotilde incognito`](#clotilde-incognito-name-options) for usage.
**Note:** Cleanup runs on normal exit (Ctrl+D, `/exit`). If the process crashes or is killed (SIGKILL), the session may persist. Use `clotilde delete ` to clean up manually.
**Limitations:**
- Cannot fork FROM incognito sessions (they'll auto-delete when you exit)
- CAN fork TO incognito sessions (create an incognito fork of a regular session)
## Session Context
Attach context to a session so Claude knows what you're working on:
```bash
# Set context when starting a session
clotilde start auth-feature --context "working on ticket GH-123"
# Works with incognito and fork too
clotilde incognito --fast --context "quick spike on caching"
clotilde fork auth-feature experiment --context "trying JWT instead of sessions"
# Update context when resuming
clotilde resume auth-feature --context "now on GH-456"
```
Context is stored in session metadata and automatically injected into Claude at session start (alongside the session name). Forked sessions inherit context from the parent unless overridden with `--context`.
Use `clotilde inspect ` to see a session's current context.
## Shorthand Flags
Common permission modes and presets have short, memorable flags available on all session commands (`start`, `incognito`, `resume`, `fork`):
```bash
# Permission mode shortcuts
clotilde start refactor --accept-edits # auto-approve edits, ask for the rest
clotilde incognito --yolo # bypass all permission checks
clotilde start spike --plan # plan mode
clotilde resume my-session --dont-ask # approve everything
# Fast mode (haiku + low effort)
clotilde start quick-check --fast
clotilde incognito --fast --yolo # quick throwaway, no prompts
# Works on resume and fork too
clotilde resume my-session --fast
clotilde fork my-session experiment --accept-edits
```
**Permission shortcuts** (`--accept-edits`, `--yolo`, `--plan`, `--dont-ask`) are mutually exclusive with each other and with `--permission-mode`.
**`--fast`** sets `--model haiku` and `--effort low`. Cannot be combined with `--model`.
## Pass-Through Flags
Pass additional Claude Code flags directly using `--` separator:
```bash
# Debug mode
clotilde start my-session -- --debug api,hooks
# Verbose output
clotilde resume my-session -- --verbose
# Multiple flags
clotilde incognito test -- --debug --permission-mode plan
```
**Common use cases:**
- `--debug [filter]` - Debug specific categories (api, hooks, mcp, etc.)
- `--verbose` - Verbose output
- `--permission-mode ` - Override permission mode (acceptEdits, plan, etc.)
- `--dangerously-skip-permissions` - Bypass permissions (for sandboxed environments)
- `--print` - Non-interactive output for scripting
- `--output-format json` - JSON output
**Note:** These flags are passed directly to Claude Code for that session only. To persist settings across sessions, use the `--model` flag or configure `settings.json`.
## Session Profiles
Define named presets for common session configurations. Use `--profile ` when creating sessions to apply a profile's settings.
Profiles can be defined in two locations:
- **Global**: `~/.config/clotilde/config.json` (respects `$XDG_CONFIG_HOME`) - available in all projects
- **Project**: `.claude/clotilde/config.json` - scoped to a single project
When both define a profile with the same name, the project version wins.
```json
{
"profiles": {
"quick": {
"model": "haiku",
"permissionMode": "bypassPermissions"
},
"strict": {
"permissions": {
"deny": ["Bash", "Write"],
"defaultMode": "ask"
}
},
"research": {
"model": "sonnet",
"outputStyle": "Explanatory"
}
}
}
```
**Profile fields:**
- `model` - Claude model (haiku, sonnet, opus)
- `permissionMode` - Permission mode (acceptEdits, bypassPermissions, default, dontAsk, plan)
- `permissions` - Granular permissions:
- `allow` - Tools Claude can always use
- `deny` - Tools Claude cannot use
- `ask` - Tools that require approval
- `additionalDirectories` - Extra directories Claude can access
- `defaultMode` - Default action for tools not in allow/deny/ask (ask, allow, or deny)
- `disableBypassPermissionsMode` - Disable permission bypass (boolean)
- `outputStyle` - Output style (built-in or custom name)
**Usage examples:**
```bash
# Apply "quick" profile (haiku + bypass permissions)
clotilde start spike --profile quick
# Apply "strict" profile (deny Bash/Write, ask mode)
clotilde start sandboxed --profile strict
# Combine profiles with CLI flags (CLI flags win)
clotilde start research --profile quick --model sonnet
# Use profile on incognito sessions
clotilde incognito --profile quick
```
**Precedence:** Global profile → project profile → CLI flags (each layer overrides the previous). For example, `--profile quick --model opus` uses the quick profile's settings but replaces its model with opus.
## Output Styles
Customize how Claude communicates in each session using built-in or custom output styles:
```bash
# Built-in styles
clotilde start myfeature --output-style default
clotilde start myfeature --output-style Explanatory
clotilde start myfeature --output-style Learning
# Existing project/user styles (by name)
clotilde start myfeature --output-style my-project-style
clotilde start myfeature --output-style my-personal-style
# Custom inline content (creates new session-specific style)
clotilde start myfeature --output-style "Be concise and use bullet points"
# Custom from file (creates new session-specific style)
clotilde start myfeature --output-style-file ./my-style.md
```
**How `--output-style` flag works:**
1. Checks if value matches existing style in `.claude/output-styles/` or `~/.claude/output-styles/`
2. If found, uses that style (no new file created)
3. Else checks if value is a built-in style (`default`, `Explanatory`, `Learning`)
4. Otherwise treats value as inline content and creates `.claude/output-styles/clotilde/.md`
**Note:** Case sensitivity matters! `"default"` is lowercase, `"Explanatory"` and `"Learning"` are capitalized.
**Storage:** Session-specific custom styles are stored in `.claude/output-styles/clotilde/.md` and should be gitignored (much like `.claude/clotilde`, they're ephemeral per-user customizations). Team members can share output styles by placing them in `.claude/output-styles/` (without the `clotilde/` subdirectory) and committing them to git.
## Commands
### `clotilde init [--global]`
Initialize clotilde in the current project. Creates `.claude/clotilde/` directory and configures hooks.
By default, hooks are installed in `.claude/settings.local.json` (local to your machine, not committed to git). Use `--global` to install hooks in `.claude/settings.json` instead (shared with team, committed to git).
```bash
# Initialize with local hooks (default - recommended for experimental use)
clotilde init
# Initialize with project-wide hooks (team shares clotilde setup)
clotilde init --global
```
**Why settings.local.json by default?**
- Clotilde is experimental - people can try it without affecting team members
- `.local.json` files are typically gitignored, keeping your config private
- Team members who don't use clotilde won't see the hooks in project settings
**Note:** The `.claude/clotilde/` directory (containing session metadata, transcripts paths, and context) should be gitignored. This is intentional - sessions are ephemeral, per-user state that shouldn't be committed to the repository. Each developer maintains their own independent session list.
### `clotilde start [options]`
Start a new named session.
```bash
# Basic usage
clotilde start my-session
# With profile
clotilde start spike --profile quick
clotilde start sandboxed --profile strict
# With custom model
clotilde start bugfix --model haiku
# Profile + CLI flag override
clotilde start research --profile quick --model sonnet
# With custom system prompt (append to default)
clotilde start refactoring --append-system-prompt-file prompts/architect.md
clotilde start review --append-system-prompt "Be critical and thorough"
# Replace Claude's default system prompt entirely
clotilde start minimal --replace-system-prompt-file prompts/custom.md
clotilde start focused --replace-system-prompt "You are a focused coding assistant"
# Create incognito session
clotilde start quick-test --incognito
# With permissions
clotilde start sandboxed --permission-mode plan \
--allowed-tools "Read,Bash(npm:*)" \
--disallowed-tools "Write" \
--add-dir "../docs"
# Combine options
clotilde start research --model haiku --append-system-prompt "Focus on exploration"
```
**Options:**
- `--profile ` - Named profile from config (applies model, permissions, and output style as baseline)
- `--model ` - Model to use (haiku, sonnet, opus). CLI flag overrides profile.
- `--fast` - Use haiku model with low effort for quick tasks
- `--append-system-prompt ` - Add system prompt text (appends to Claude's default)
- `--append-system-prompt-file ` - Add system prompt from file (appends to Claude's default)
- `--replace-system-prompt ` - Replace Claude's default system prompt entirely with custom text
- `--replace-system-prompt-file ` - Replace Claude's default system prompt entirely with file contents
- `--context ` - Session context (e.g. "working on ticket GH-123"). Injected into Claude at session start.
- `--incognito` - Create incognito session (auto-deletes on exit)
- `--accept-edits` - Shorthand for `--permission-mode acceptEdits`
- `--yolo` - Shorthand for `--permission-mode bypassPermissions`
- `--plan` - Shorthand for `--permission-mode plan`
- `--dont-ask` - Shorthand for `--permission-mode dontAsk`
- `--permission-mode ` - Permission mode (acceptEdits, bypassPermissions, default, dontAsk, plan). CLI flag overrides profile.
- `--allowed-tools ` - Comma-separated list of allowed tools (e.g. `Bash(npm:*),Read`). CLI flag overrides profile.
- `--disallowed-tools ` - Comma-separated list of disallowed tools (e.g. `Write,Bash(git:*)`). CLI flag overrides profile.
- `--add-dir ` - Additional directories to allow tool access to. CLI flag overrides profile.
- `--output-style ` - Output style: `default`, `Explanatory`, `Learning`, existing style name, or custom content. CLI flag overrides profile.
- `--output-style-file <path>` - Path to custom output style file. CLI flag overrides profile.
### `clotilde incognito [name] [options]`
Start a new incognito session that automatically deletes when you exit. If no name is provided, a random name like "happy-fox" or "brave-wolf" will be generated.
```bash
# Random name (e.g., "clever-owl")
clotilde incognito
# Explicit name
clotilde incognito quick-test
# With model and random name
clotilde incognito --model haiku
```
**Options:** Same as `clotilde start` (except `--incognito` is implicit), including `--context`
### `clotilde resume [name] [options]`
Resume a session by name. Shorthand flags are passed directly to Claude Code for that invocation.
```bash
clotilde resume auth-feature
clotilde resume auth-feature --fast
clotilde resume auth-feature --accept-edits
clotilde resume auth-feature --context "now on GH-456"
```
**Options:**
- `--context <text>` - Update session context (e.g. "now working on GH-456")
- `--accept-edits`, `--yolo`, `--plan`, `--dont-ask`, `--fast` (see [Shorthand Flags](#shorthand-flags))
### `clotilde list`
List all sessions with details (name, model, last used).
### `clotilde inspect <name>`
Show detailed session information including files, settings, context sources, and Claude Code data status.
```bash
clotilde inspect auth-feature
```
### `clotilde fork <parent> [name] [options]`
Fork a session to try different approaches without losing the original.
If no name is provided for incognito forks, a random name will be generated.
```bash
clotilde fork auth-feature auth-experiment
# Create incognito fork with explicit name
clotilde fork auth-feature temp-experiment --incognito
# Create incognito fork with random name (e.g., "clever-owl")
clotilde fork auth-feature --incognito
```
**Options:**
- `--context <text>` - Override context for the fork (inherits from parent if not specified)
- `--incognito` - Create fork as incognito session (auto-deletes on exit)
- `--accept-edits`, `--yolo`, `--plan`, `--dont-ask`, `--fast` - Shorthand flags (see [Shorthand Flags](#shorthand-flags))
**Note:** You cannot fork FROM incognito sessions, but you can fork TO incognito sessions.
### `clotilde delete <name> [--force]`
Delete a session and all associated Claude Code data (transcripts, agent logs).
**Options:**
- `--force, -f` - Skip confirmation prompt
### `clotilde completion <shell>`
Generate shell completion scripts (bash, zsh, fish, powershell). See `clotilde completion --help` for setup instructions.
## Related Work
Claude Code has a `/rename` command, but session names don't persist reliably across resumes, can't be used with `--resume <name>`, and there's no `--session-name` flag for naming at startup. Several open issues track these gaps:
- [#25870](https://github.com/anthropics/claude-code/issues/25870) - `--session-name` flag for naming sessions at startup
- [#26249](https://github.com/anthropics/claude-code/issues/26249) - `/rename` names not indexed, can't resume by name
- [#26240](https://github.com/anthropics/claude-code/issues/26240) - Session names lost after resuming and continuing work
- [#11408](https://github.com/anthropics/claude-code/issues/11408) - Named sessions for easier identification
### Existing solutions
- [**tweakcc**](https://github.com/Piebald-AI/tweakcc) - Patches Claude Code to add custom system prompts, toolsets, themes, and more
- [**claude-code-session-name**](https://github.com/richardkmichael/claude-code-session-name) - Python wrapper adding `--session-name` flag, stores names in SQLite
Clotilde is different because:
- Non-invasive (doesn't patch or modify Claude Code)
- Native Go binary (no runtime dependencies)
- Goes beyond naming: profiles, context injection, incognito sessions, forking
- Built-in cleanup (deletes sessions + associated Claude Code data)
## Development
**Requirements:**
- Go 1.25+
- Make
- golangci-lint v2.x (for linting - matches CI)
**Setup golangci-lint:**
```bash
# Install golangci-lint v2.x (required for consistent linting with CI)
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin
# Verify installation
golangci-lint --version # Should show v2.x
```
**Configure git hooks** (recommended):
```bash
make setup-hooks
```
This enables pre-commit checks that automatically format and lint your code before committing, preventing CI failures.
**Build & Test:**
```bash
# Build
make build
# Run tests
make test
# Run tests with coverage
make coverage
# Run tests in watch mode
make test-watch
# Format code
make fmt
# Lint
make lint
# Install locally to ~/.local/bin
make install
```
**Note:** The `make lint` command will warn you if your local golangci-lint version doesn't match CI (v2.x).
## License
MIT