A local web UI to manage multiple Claude Code profiles on one machine.
Quick Start • Features • Screenshots • How It Works • Usage • Documentation • Configuration • Troubleshooting • License
cc-profiles keeps your Claude Code profiles in order: work and personal accounts side by side, each with its own memory, conversations, skills, MCP servers and settings. Move projects and memories between profiles, relink projects whose folder moved, share skills and plugins, and edit settings with safe dropdowns, all from a page in your browser. Every change is backed up first, so anything you do can be undone with one click.
Quick Start
Install with a single command:
curl -fsSL https://raw.githubusercontent.com/andreaiannarone/cc-profiles/main/install.sh | sh
The script installs cc-profiles with pipx or uv, whichever you have, and adds a /cc-profiles command to Claude Code in every profile. It never uses sudo and writes only in your home folder; read it first if you like. Run it again to update. To install the app without touching your profiles:
curl -fsSL https://raw.githubusercontent.com/andreaiannarone/cc-profiles/main/install.sh | sh -s -- --no-command
Then open it, from a terminal or from inside Claude Code:
cc-profiles # starts on http://127.0.0.1:4777 and opens your browser
/cc-profiles # inside any Claude Code session: opens the app and the session goes on
On the first run, cc-profiles finds ~/.claude and every ~/.claude-<name> folder that looks like a profile. Rename them from the Profiles tab.
Other ways to install
By hand, with pipx or uv:
pipx install git+https://github.com/andreaiannarone/cc-profiles.git # or: uv tool install git+…
cc-profiles install-command # optional: adds /cc-profiles to Claude Code
Try it without installing anything:
uvx --from git+https://github.com/andreaiannarone/cc-profiles.git cc-profiles
From the Claude Code plugin marketplace. The command is then /cc-profiles:open, because Claude Code prefixes plugin commands with the plugin's name. The plugin only opens the app, so install cc-profiles first:
/plugin marketplace add andreaiannarone/cc-profiles
/plugin install cc-profiles@cc-profiles
From source:
git clone https://github.com/andreaiannarone/cc-profiles.git
cd cc-profiles
python3 -m pip install -e .
cc-profiles
Unofficial. cc-profiles is a community project, not affiliated with or endorsed by Anthropic. It works with Claude Code's on-disk files, whose format is undocumented and may change between releases. That is why every operation it performs creates a backup you can restore with one click.
Key Features
- 🗂️ Projects: see which profile each project belongs to and what it holds in each one. Move a project to another profile with its conversations, memories, file snapshots, prompt history and per-project settings, after a preview of every file it touches. Relink a project whose folder you moved or renamed. Assign projects with simple path rules.
- 🧠 Memories: browse, edit, move and delete the memories of every project, with the
MEMORY.mdindexes kept in sync. - 👤 Profiles: see the account each profile is signed in with. Create a profile, empty or copied from another one; rename it, change its command, or delete it, optionally merging its content into another profile first.
- 🧩 Skills: browse, create, edit, copy and delete the skills of each profile.
- 🔌 MCP servers: add, edit, copy and remove MCP servers, for every project or for one. Tokens in environment variables and headers stay out of the list.
- 🔗 Sharing: share
skills,plugins,agents,commands,CLAUDE.mdorsettings.jsonwith the source profile through symlinks. Install once, use everywhere. - ⚙️ Settings: model, effort, output style, theme and more, with dropdowns that offer only the values Claude Code accepts and show which file each value comes from. Edit
CLAUDE.md, permissions and the raw JSON, with validation. - ⏪ Backups: every operation is journaled. Restore undoes it, and a restore can itself be undone. Delete the old ones in one go when they take too much space.
- 🩺 Health: login status, config validity, broken links, memory indexes, and projects whose folder disappeared, with candidate folders to relink them to.
- ⌨️ Inside Claude Code:
/cc-profilesopens the app from any session;cc-profiles labelshows the active profile in your status line. - 🌓 Light and dark: the theme button next to (i) picks System, Light or Dark; System follows your operating system.
- 🔒 Local and private: listens on
127.0.0.1only, with a token on every request. Nothing is ever sent anywhere.
Screenshots
|
Memories: every project's memories, with an editor |
Skills: browse, create, edit and copy skills |
|
MCP: servers for every project or for one |
Settings: safe dropdowns, compared across profiles |
The screenshots show sample data from the /sandbox skill. GitHub shows them in your theme, light or dark.
Why
Claude Code reads its configuration from ~/.claude, or from whatever directory CLAUDE_CONFIG_DIR points to. Each directory is a separate profile with its own memory, conversations, prompt history, settings and login:
claude # default profile (~/.claude)
CLAUDE_CONFIG_DIR=~/.claude-work claude # a second profile
That is great for keeping contexts apart, but maintaining profiles by hand is painful:
- Conversations live in folders named like
-Users-you-code-client--api, one per project path. - The prompt history is one JSONL file to filter line by line.
- The default profile's settings live in
~/.claude.json, outside~/.claude. - When you move a project folder, Claude Code silently loses its history.
cc-profiles does all of this for you, from a page in your browser.
How It Works
Core components:
- Local server: one Python file, standard library only. It listens on
127.0.0.1, checks theHostheader against DNS rebinding and a random token against requests from other websites. - Single-page UI: one HTML file with inline CSS and vanilla JavaScript, no build step and nothing loaded from the internet. Light and dark themes follow your system.
- Backups with a journal: before any change, the files it touches are copied to
~/.cc-profiles/backups/<date>_<operation>/, and every step (copy, move, new folder, new link) is written to amanifest.json. Restore replays the journal backwards. - Atomic writes: every file is written to a temporary file in the same folder and then renamed, so a running Claude Code never reads a half-written file. Writes follow symlinks, so shared files stay shared.
- Path recovery: Claude Code's project folder names cannot be turned back into paths. cc-profiles rebuilds them from config files, prompt history and the
cwdof conversations, and walks the disk when nothing mentions them. - Launchers and commands: new profiles get a small
claude-<id>script in~/.local/bin;cc-profiles install-commandadds/cc-profilesto Claude Code. Files cc-profiles creates carry a mark, and it never overwrites a file without it.
See Architecture and Claude Code's on-disk formats for details.
Usage
cc-profiles # starts on http://127.0.0.1:4777 and opens the browser; ctrl+C stops it
cc-profiles --port 4800 # another port
cc-profiles --no-browser # just the server
cc-profiles open # starts it in the background if needed, opens the browser and returns
cc-profiles install-command # adds the /cc-profiles command to Claude Code in every profile
cc-profiles label # prints the name of the active profile, for status lines
Open it from Claude Code
Type /cc-profiles in any Claude Code session: the app starts in the background, your browser opens on it, and the session goes on. The command is a small file, commands/cc-profiles.md, that cc-profiles install-command writes in every profile. Profiles that share commands with the source profile get it through the link.
Commands for each profile
When cc-profiles creates a profile, it adds a launcher to ~/.local/bin. For a profile called work that is claude-work:
#!/bin/sh
CLAUDE_CONFIG_DIR="$HOME/.claude-work" exec claude "$@"
The script works in every shell. Make sure ~/.local/bin is in your PATH; the official Claude Code installer usually adds it.
Show the profile in your status line
cc-profiles label prints the name of the profile in use, based on CLAUDE_CONFIG_DIR. Call it from your Claude Code status line script:
profile=$(cc-profiles label 2>/dev/null)
printf '(%s) ' "$profile"
Rules
The Projects tab assigns each project to a profile using rules: "a path containing this text belongs to that profile". Create them from the UI with Assign…. They are checked in order, the first match wins and new rules go first:
{ "match": "code/work", "profile": "work" }
"profile": "shared" marks paths that may appear in every profile, like your home folder.
Documentation
Getting Started
- Getting started: install, first run, launcher commands,
/cc-profiles - Concepts: profiles, the source profile, projects, rules, sharing, backups
Guides by Tab
- Projects: move, relink, assign
- Memories: browse, edit, move
- Profiles and sharing: create, edit, delete, share
- Skills and MCP servers: create, edit, copy, delete
- Settings: general settings,
CLAUDE.md, permissions, raw JSON - Backups: what gets saved and how restoring works
- Health and About: checks, orphan projects, installing Claude Code
Reference
- Configuration:
config.json, command line, environment variables - Status line: show the active profile in Claude Code
- Troubleshooting: common problems and their fixes
For Contributors
- Architecture: how the code is organized and why
- Claude Code's on-disk formats: what the app reads and writes
- HTTP API: every endpoint the UI uses
- Contributing and design system
Configuration
cc-profiles keeps its own data in ~/.cc-profiles/, never in the repository:
| Path | Content |
|---|---|
~/.cc-profiles/config.json |
profiles, rules, folders to search when relinking |
~/.cc-profiles/backups/ |
one folder per operation: a manifest.json journal plus the original files |
~/.cc-profiles/server.log |
output of the server started by cc-profiles open |
~/.local/bin/claude-<id> |
launchers created for new profiles |
<profile>/commands/cc-profiles.md |
the /cc-profiles command, if you added it |
| Environment variable | Effect |
|---|---|
CC_PROFILES_PORT |
default port instead of 4777 |
CC_PROFILES_HOME |
data folder instead of ~/.cc-profiles |
CC_PROFILES_QUIET |
if set, do not log HTTP requests to the terminal |
See the Configuration reference for config.json and every option.
System Requirements
- macOS or Linux (Windows is not supported yet)
- Python 3.9 or later: macOS's built-in Python works
- pipx or uv to install it
- Claude Code, or let cc-profiles install it for you with the official installer
No dependencies: cc-profiles uses only the Python standard library.
Security
- The server listens on
127.0.0.1only and accepts onlyHost: 127.0.0.1:<port>orlocalhost:<port>, which blocks DNS rebinding. - Every API call needs a random token, generated at each start and embedded in the page, so other websites cannot control the app.
- Writes are atomic (temporary file, then rename), so Claude Code never reads a half-written file, even while it is running.
- Names of projects, memories, skills and backups are validated against path traversal.
- Login credentials are never copied between profiles: each profile signs in on its own. Copying an MCP server copies its configuration, never its sign-in.
- The only network access is the optional Claude Code installer, which runs only if you click Install.
See SECURITY.md to report a vulnerability.
Limitations
- Claude Code's file formats are not a public API. Settings dropdowns were checked against Claude Code 2.1.289; the About panel shows which version you have.
- "Session open" means a
claudeprocess is running in the profile (read from the process list on macOS and from/procon Linux), or a conversation was written in the last 2 minutes. - Claude Code keeps
.claude.jsonin memory while it runs: restart open sessions after changing their MCP servers. - Deleting a profile does not remove credentials that Claude Code may have stored in the macOS Keychain for it.
Troubleshooting
| Problem | Fix |
|---|---|
| "Port 4777 is busy" | cc-profiles is already running: open the URL, or start it with --port 4800 |
| A tab says the page is newer than the server | you updated cc-profiles while it was running: stop it and start it again |
cc-profiles: command not found |
run pipx ensurepath (or uv tool update-shell) and open a new terminal |
/cc-profiles does not appear in Claude Code |
run cc-profiles install-command, then restart the session |
| A project shows "folder not found on disk" | click Relink… and pick the folder where it lives now |
| A setting has no effect | the Settings tab shows which file the value comes from: settings.local.json wins over settings.json |
See the Troubleshooting guide for more.
Contributing
Contributions are welcome! Please:
- Fork the repository and create a branch
- Make your changes with tests: every operation that writes must go through
Backupand have a test that restores it - Keep it standard library only and compatible with Python 3.9
- Update the documentation and
CHANGELOG.md - Open a pull request
See CONTRIBUTING.md to run the app and the tests locally. If you use Claude Code, the repository's .claude/ folder keeps you on a sandbox and has skills for the common chores. Good first contributions: translations (the UI is English only), Windows support, a "dry run" preview for big operations.
License
cc-profiles is licensed under the GNU General Public License v3.0 or later. © Andrea Iannarone
You can use, study, change and share it freely. If you distribute it, modified or not, you must do so under the same license and with the source code. Version 0.1.0 was released under MIT and stays available under it.
Support
- Documentation: docs/
- Issues: GitHub Issues
- Repository: github.com/andreaiannarone/cc-profiles
- Buy me a coffee: buymeacoffee.com/andreaiannarone
- Author: Andrea Iannarone (@andreaiannarone)
Built with Claude Code | Made for Claude Code | Pure Python standard library
Metadata
Release files for cc-profiles 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cc_profiles-0.2.0.tar.gz | 89.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cc_profiles-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 165.7 kB
Release files / cc_profiles-0.2.0.tar.gz
| Download URL | cc_profiles-0.2.0.tar.gz |
|---|---|
| Size | 89.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dd78d1149bdd9cfb7a43ef26e9c63dd58fd2b30fc22c72baefd26bddbe4a53dd
|
|
BLAKE2b-256 checksum How to use checksums |
931c2f8c091548b241ab970ddc1ea38ec4ae37d27dc00ee935158e927838be33
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency logRelease files / cc_profiles-0.2.0-py3-none-any.whl
| Download URL | cc_profiles-0.2.0-py3-none-any.whl |
|---|---|
| Size | 76.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fd8c00eb0ca322fe00e46be34948a42b88fb5994126a4fea1a1a175ee16c6b9a
|
|
BLAKE2b-256 checksum How to use checksums |
757e0eb11697562164ffc4021c678bf1ab3e862dd19bdaa1d30b2ba9a4f0a3ed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency log