claude-profile 1.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of claude-profile might be problematic. Click here for more details.

@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CloudOpsWorld and claude-profile contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ include README.md RELEASING.md LICENSE
2
+ include scripts/claudectl_entry.py scripts/demo.ps1
@@ -0,0 +1,185 @@
1
+ Metadata-Version: 2.4
2
+ Name: claude-profile
3
+ Version: 1.0.2
4
+ Summary: Per-customer profiles for Claude Code and Claude Desktop: separate logins, AI platforms, MCP servers, skills and history, side by side.
5
+ Author: claude-profile contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/CloudOpsWorld/claude-profile
8
+ Project-URL: Repository, https://github.com/CloudOpsWorld/claude-profile
9
+ Project-URL: Issues, https://github.com/CloudOpsWorld/claude-profile/issues
10
+ Keywords: claude,claude-code,claude-desktop,anthropic,profiles,mcp,deepseek,openrouter,cli
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: MacOS :: MacOS X
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Software Development
24
+ Classifier: Topic :: Utilities
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=9.1.1; extra == "dev"
30
+ Requires-Dist: ruff>=0.15.21; extra == "dev"
31
+ Requires-Dist: mypy>=2.3.0; extra == "dev"
32
+ Requires-Dist: build>=1.5.1; extra == "dev"
33
+ Dynamic: license-file
34
+
35
+ # claudectl
36
+
37
+ Use Claude Code with a separate profile for each customer, on Windows, macOS and Linux. Each profile has its own:
38
+
39
+ - sign-in or API key
40
+ - AI platform
41
+ - MCP servers
42
+ - skills and plugins
43
+ - session history and memory
44
+
45
+ Customers can run side by side in separate terminals. Switching never touches a session that's already running, and one customer's Jira or Confluence server never shows up in another customer's session.
46
+
47
+ claudectl doesn't change anything machine-wide. Your normal `claude` and `~/.claude` keep working exactly as before, and appear as the `default` profile.
48
+
49
+ It's pure Python 3.10+ with no dependencies beyond the standard library.
50
+
51
+ ## Install
52
+
53
+ From PyPI (the package is `claude-profile`, the command is `claudectl`):
54
+
55
+ ```bash
56
+ pipx install claude-profile # or: uv tool install claude-profile or: pip install claude-profile
57
+ claudectl install # optional: adds the "Claude Profiles" Start menu picker on Windows
58
+ ```
59
+
60
+ **Without Python:** download a standalone binary from [Releases](https://github.com/CloudOpsWorld/claude-profile/releases) and run it once with `install`, which puts it in `~/.local/bin`:
61
+ - `claudectl-windows-amd64.exe`
62
+ - `claudectl-macos-arm64`
63
+ - `claudectl-linux-amd64`
64
+
65
+ Each release has `SHA256SUMS` and build provenance you can check with `gh attestation verify <file> --repo CloudOpsWorld/claude-profile`.
66
+
67
+ **From source:**
68
+
69
+ ```bash
70
+ python claudectl/cli.py install
71
+ ```
72
+
73
+ This copies the single file to `~/.claudectl/app` and puts a launcher in `~/.local/bin`.
74
+
75
+ To remove claudectl, run `claudectl uninstall` (or `pipx uninstall claude-profile`). Your profiles are kept.
76
+
77
+ ## Daily use
78
+
79
+ ```bash
80
+ claudectl add acme # guided: name, AI platform, key or sign-in, bind this folder
81
+ cd ~/work/acme-repo
82
+ claudectl # starts Claude Code as ACME, because the folder is bound
83
+ claudectl tab globex # new terminal tab locked to Globex
84
+ claudectl acme --resume # any claude arguments pass through
85
+ claudectl mcp add jira -- npx -y <jira-mcp> # goes into this folder's profile only
86
+ claudectl list # profiles, bound folders, active profile, Desktop profile
87
+ ```
88
+
89
+ - **Bound folders** pick the profile automatically. If you start a different profile inside a bound folder, claudectl asks before continuing.
90
+ - **Everywhere else**, `claudectl` uses the active profile. Set it with `claudectl use <name>`.
91
+ - **Every session shows its customer** in Claude Code's status line and in the tab title.
92
+ - **On Windows**, tabs open in Windows Terminal with the customer's color. macOS uses Terminal.app. Linux uses the first terminal it finds: GNOME Terminal, Konsole, kitty, WezTerm, Alacritty or Xfce Terminal.
93
+
94
+ ## Import your existing setup
95
+
96
+ ```bash
97
+ claudectl import --scan # just show what's in your current Claude setup
98
+ claudectl import # guided: sort project folders into customer profiles
99
+ ```
100
+
101
+ **What the scan finds:**
102
+ - every project folder Claude has history for (worktrees are folded into their repo)
103
+ - MCP servers, both user-wide and per-project
104
+ - skills, agents, commands and output styles
105
+ - your `CLAUDE.md`, plugins and preferences
106
+ - Claude Desktop's MCP servers
107
+ - leftovers from older switcher scripts: extra `~/.claude-*` config folders, system-wide `ANTHROPIC_*` variables, and lines in your PowerShell or shell profile
108
+
109
+ It skips temporary folders, folders that no longer exist, your home folder and drive roots.
110
+
111
+ **The guided import** suggests customers from your folder layout. `D:\work\acme\api` and `D:\work\acme\web` become one `acme` profile, tied to `D:\work\acme`. You can:
112
+ - press Enter to accept each suggestion
113
+ - type a name to rename it or merge it into another profile
114
+ - press `k` to keep those folders in your default setup
115
+
116
+ Then you pick:
117
+ - the AI platform for each new profile
118
+ - which profiles get which MCP servers
119
+ - whether new profiles get your skills, `CLAUDE.md`, preferences and plugins (plugins are reinstalled cleanly in each profile)
120
+
121
+ **It only copies.** Each project's history, memory, prompt history, trust settings and per-project MCP servers go into its profile. Your current setup isn't changed, so it's safe while Claude is running.
122
+
123
+ **Your own sign-in, account details and caches are never copied into a customer profile.** The one exception: a `~/.claude-*` folder left by an older switcher is adopted whole, including its sign-in, because that sign-in belongs to the customer.
124
+
125
+ You can also work from a file, which is handy for many folders or for repeating the import:
126
+
127
+ ```bash
128
+ claudectl import --plan plan.json # write the suggestions to a file you can edit
129
+ claudectl import --apply plan.json --dry-run # show what would happen
130
+ claudectl import --apply plan.json # copy
131
+ claudectl import --apply plan.json --move # copy, then take it out of the default setup
132
+ ```
133
+
134
+ Running `--apply` again is safe: it never overwrites anything and doesn't duplicate history.
135
+
136
+ **`--move`** removes the imported customer folders, history and MCP servers from your default setup:
137
+ - It refuses while any Claude Code session is running, including Desktop's Code tab.
138
+ - It backs up your config first.
139
+ - It puts everything it removes in `~/.claudectl/import-backups/`.
140
+ - Desktop's Code tab uses your default setup, so moved history no longer shows up there.
141
+
142
+ `--from DIR` imports from another Claude config folder instead of `~/.claude`.
143
+
144
+ ## AI platforms
145
+
146
+ | Platform | How it connects |
147
+ |---|---|
148
+ | Claude subscription: Pro, Max, Team, Enterprise | Browser sign-in on first start. You can lock it to the customer's org UUID. |
149
+ | Anthropic API key | Pay per use. |
150
+ | DeepSeek | Native Claude-compatible endpoint. |
151
+ | OpenRouter | GPT, Gemini and others. Use this for OpenAI customers, with BYOK for their own OpenAI key. |
152
+ | Any Claude-compatible URL | For example a LiteLLM proxy in front of a direct OpenAI key, Moonshot, Z.ai or a company gateway. |
153
+ | AWS Bedrock, Google Vertex | Claude through the customer's own cloud account. |
154
+
155
+ To add a platform, create `~/.claudectl/providers.json`: a JSON list of entries in the same shape as `BUILTIN_PROVIDERS` at the top of [claudectl/cli.py](claudectl/cli.py). An entry with an existing `id` replaces the built-in one. To change a profile's models, run `claudectl edit <name>`.
156
+
157
+ **Where API keys are stored:**
158
+ - **Windows:** encrypted with DPAPI, so only your Windows user can read them.
159
+ - **macOS:** in your login Keychain.
160
+ - **Linux:** in your keyring through `secret-tool`. Without a keyring, in a file only you can read.
161
+
162
+ ## Claude Desktop
163
+
164
+ Desktop holds one sign-in at a time, so it switches with a restart:
165
+
166
+ 1. Quit Desktop.
167
+ 2. Run `claudectl desktop acme`.
168
+ 3. Start Desktop.
169
+
170
+ This swaps the local MCP servers in Desktop's config. Each customer's servers are saved automatically when you switch away.
171
+
172
+ Cloud connectors added on claude.ai belong to the signed-in account and follow it. If the customer uses a different Claude account, sign out and back in.
173
+
174
+ **Not isolated:** Desktop's own Code tab uses Desktop's built-in Claude Code and login. Do isolated customer work in a terminal with claudectl.
175
+
176
+ ## Where things live
177
+
178
+ Everything is in `~/.claudectl`, on every OS. On Windows this is deliberately not AppData: Microsoft Store Python redirects new files there into a private folder that Claude Code can't see.
179
+
180
+ Each profile lives in `~/.claudectl/profiles/<name>/`:
181
+ - `profile.json`: platform, models, how the key is stored
182
+ - `config/`: Claude Code's own folder for this customer (login, MCP, skills, plugins, history, memory)
183
+ - `desktop-mcp.json`: this customer's Claude Desktop MCP servers
184
+
185
+ Set `CLAUDECTL_HOME` to put the data folder somewhere else.
@@ -0,0 +1,151 @@
1
+ # claudectl
2
+
3
+ Use Claude Code with a separate profile for each customer, on Windows, macOS and Linux. Each profile has its own:
4
+
5
+ - sign-in or API key
6
+ - AI platform
7
+ - MCP servers
8
+ - skills and plugins
9
+ - session history and memory
10
+
11
+ Customers can run side by side in separate terminals. Switching never touches a session that's already running, and one customer's Jira or Confluence server never shows up in another customer's session.
12
+
13
+ claudectl doesn't change anything machine-wide. Your normal `claude` and `~/.claude` keep working exactly as before, and appear as the `default` profile.
14
+
15
+ It's pure Python 3.10+ with no dependencies beyond the standard library.
16
+
17
+ ## Install
18
+
19
+ From PyPI (the package is `claude-profile`, the command is `claudectl`):
20
+
21
+ ```bash
22
+ pipx install claude-profile # or: uv tool install claude-profile or: pip install claude-profile
23
+ claudectl install # optional: adds the "Claude Profiles" Start menu picker on Windows
24
+ ```
25
+
26
+ **Without Python:** download a standalone binary from [Releases](https://github.com/CloudOpsWorld/claude-profile/releases) and run it once with `install`, which puts it in `~/.local/bin`:
27
+ - `claudectl-windows-amd64.exe`
28
+ - `claudectl-macos-arm64`
29
+ - `claudectl-linux-amd64`
30
+
31
+ Each release has `SHA256SUMS` and build provenance you can check with `gh attestation verify <file> --repo CloudOpsWorld/claude-profile`.
32
+
33
+ **From source:**
34
+
35
+ ```bash
36
+ python claudectl/cli.py install
37
+ ```
38
+
39
+ This copies the single file to `~/.claudectl/app` and puts a launcher in `~/.local/bin`.
40
+
41
+ To remove claudectl, run `claudectl uninstall` (or `pipx uninstall claude-profile`). Your profiles are kept.
42
+
43
+ ## Daily use
44
+
45
+ ```bash
46
+ claudectl add acme # guided: name, AI platform, key or sign-in, bind this folder
47
+ cd ~/work/acme-repo
48
+ claudectl # starts Claude Code as ACME, because the folder is bound
49
+ claudectl tab globex # new terminal tab locked to Globex
50
+ claudectl acme --resume # any claude arguments pass through
51
+ claudectl mcp add jira -- npx -y <jira-mcp> # goes into this folder's profile only
52
+ claudectl list # profiles, bound folders, active profile, Desktop profile
53
+ ```
54
+
55
+ - **Bound folders** pick the profile automatically. If you start a different profile inside a bound folder, claudectl asks before continuing.
56
+ - **Everywhere else**, `claudectl` uses the active profile. Set it with `claudectl use <name>`.
57
+ - **Every session shows its customer** in Claude Code's status line and in the tab title.
58
+ - **On Windows**, tabs open in Windows Terminal with the customer's color. macOS uses Terminal.app. Linux uses the first terminal it finds: GNOME Terminal, Konsole, kitty, WezTerm, Alacritty or Xfce Terminal.
59
+
60
+ ## Import your existing setup
61
+
62
+ ```bash
63
+ claudectl import --scan # just show what's in your current Claude setup
64
+ claudectl import # guided: sort project folders into customer profiles
65
+ ```
66
+
67
+ **What the scan finds:**
68
+ - every project folder Claude has history for (worktrees are folded into their repo)
69
+ - MCP servers, both user-wide and per-project
70
+ - skills, agents, commands and output styles
71
+ - your `CLAUDE.md`, plugins and preferences
72
+ - Claude Desktop's MCP servers
73
+ - leftovers from older switcher scripts: extra `~/.claude-*` config folders, system-wide `ANTHROPIC_*` variables, and lines in your PowerShell or shell profile
74
+
75
+ It skips temporary folders, folders that no longer exist, your home folder and drive roots.
76
+
77
+ **The guided import** suggests customers from your folder layout. `D:\work\acme\api` and `D:\work\acme\web` become one `acme` profile, tied to `D:\work\acme`. You can:
78
+ - press Enter to accept each suggestion
79
+ - type a name to rename it or merge it into another profile
80
+ - press `k` to keep those folders in your default setup
81
+
82
+ Then you pick:
83
+ - the AI platform for each new profile
84
+ - which profiles get which MCP servers
85
+ - whether new profiles get your skills, `CLAUDE.md`, preferences and plugins (plugins are reinstalled cleanly in each profile)
86
+
87
+ **It only copies.** Each project's history, memory, prompt history, trust settings and per-project MCP servers go into its profile. Your current setup isn't changed, so it's safe while Claude is running.
88
+
89
+ **Your own sign-in, account details and caches are never copied into a customer profile.** The one exception: a `~/.claude-*` folder left by an older switcher is adopted whole, including its sign-in, because that sign-in belongs to the customer.
90
+
91
+ You can also work from a file, which is handy for many folders or for repeating the import:
92
+
93
+ ```bash
94
+ claudectl import --plan plan.json # write the suggestions to a file you can edit
95
+ claudectl import --apply plan.json --dry-run # show what would happen
96
+ claudectl import --apply plan.json # copy
97
+ claudectl import --apply plan.json --move # copy, then take it out of the default setup
98
+ ```
99
+
100
+ Running `--apply` again is safe: it never overwrites anything and doesn't duplicate history.
101
+
102
+ **`--move`** removes the imported customer folders, history and MCP servers from your default setup:
103
+ - It refuses while any Claude Code session is running, including Desktop's Code tab.
104
+ - It backs up your config first.
105
+ - It puts everything it removes in `~/.claudectl/import-backups/`.
106
+ - Desktop's Code tab uses your default setup, so moved history no longer shows up there.
107
+
108
+ `--from DIR` imports from another Claude config folder instead of `~/.claude`.
109
+
110
+ ## AI platforms
111
+
112
+ | Platform | How it connects |
113
+ |---|---|
114
+ | Claude subscription: Pro, Max, Team, Enterprise | Browser sign-in on first start. You can lock it to the customer's org UUID. |
115
+ | Anthropic API key | Pay per use. |
116
+ | DeepSeek | Native Claude-compatible endpoint. |
117
+ | OpenRouter | GPT, Gemini and others. Use this for OpenAI customers, with BYOK for their own OpenAI key. |
118
+ | Any Claude-compatible URL | For example a LiteLLM proxy in front of a direct OpenAI key, Moonshot, Z.ai or a company gateway. |
119
+ | AWS Bedrock, Google Vertex | Claude through the customer's own cloud account. |
120
+
121
+ To add a platform, create `~/.claudectl/providers.json`: a JSON list of entries in the same shape as `BUILTIN_PROVIDERS` at the top of [claudectl/cli.py](claudectl/cli.py). An entry with an existing `id` replaces the built-in one. To change a profile's models, run `claudectl edit <name>`.
122
+
123
+ **Where API keys are stored:**
124
+ - **Windows:** encrypted with DPAPI, so only your Windows user can read them.
125
+ - **macOS:** in your login Keychain.
126
+ - **Linux:** in your keyring through `secret-tool`. Without a keyring, in a file only you can read.
127
+
128
+ ## Claude Desktop
129
+
130
+ Desktop holds one sign-in at a time, so it switches with a restart:
131
+
132
+ 1. Quit Desktop.
133
+ 2. Run `claudectl desktop acme`.
134
+ 3. Start Desktop.
135
+
136
+ This swaps the local MCP servers in Desktop's config. Each customer's servers are saved automatically when you switch away.
137
+
138
+ Cloud connectors added on claude.ai belong to the signed-in account and follow it. If the customer uses a different Claude account, sign out and back in.
139
+
140
+ **Not isolated:** Desktop's own Code tab uses Desktop's built-in Claude Code and login. Do isolated customer work in a terminal with claudectl.
141
+
142
+ ## Where things live
143
+
144
+ Everything is in `~/.claudectl`, on every OS. On Windows this is deliberately not AppData: Microsoft Store Python redirects new files there into a private folder that Claude Code can't see.
145
+
146
+ Each profile lives in `~/.claudectl/profiles/<name>/`:
147
+ - `profile.json`: platform, models, how the key is stored
148
+ - `config/`: Claude Code's own folder for this customer (login, MCP, skills, plugins, history, memory)
149
+ - `desktop-mcp.json`: this customer's Claude Desktop MCP servers
150
+
151
+ Set `CLAUDECTL_HOME` to put the data folder somewhere else.
@@ -0,0 +1,72 @@
1
+ # Releasing claude-profile
2
+
3
+ Publishing is fully automated via GitHub Actions: pushing a new version to `main`
4
+ triggers a release.
5
+
6
+ ## Workflows
7
+
8
+ | Workflow | Trigger | What it does |
9
+ |----------|---------|--------------|
10
+ | `.github/workflows/ci.yml` | push / PR to `main`/`master` | Test matrix (Ubuntu + macOS + Windows × Python 3.10–3.13), advisory ruff lint & mypy |
11
+ | `.github/workflows/build.yml` | `workflow_call` / manual | Runs tests, builds standalone binaries (Linux, macOS, Windows via PyInstaller) and the wheel/sdist (`python -m build` + `twine check`) |
12
+ | `.github/workflows/release.yml` | push to `main`/`master` | Detects a new version, tags it, builds artifacts, creates a GitHub Release, and publishes to PyPI |
13
+
14
+ ## How a release happens
15
+
16
+ 1. Bump the version in **both** `pyproject.toml` and `claudectl/__init__.py`
17
+ (the release workflow fails if they disagree).
18
+ 2. Commit and push to `main`.
19
+ 3. `release.yml` will:
20
+ - see the version has no matching `vX.Y.Z` git tag,
21
+ - create and push that tag,
22
+ - build binaries + wheel/sdist,
23
+ - create a GitHub Release with the binaries and package attached,
24
+ - publish the wheel/sdist to PyPI as `claude-profile`.
25
+
26
+ If the tag already exists, the release is skipped — so pushing unrelated commits
27
+ never re-releases.
28
+
29
+ ## One-time PyPI setup (Trusted Publishing — recommended)
30
+
31
+ No API token required. On PyPI, signed in as an owner of the **CloudOpsWorld**
32
+ organization:
33
+
34
+ 1. Go to **Your organizations → CloudOpsWorld → Publishing → Add a new pending
35
+ publisher** (or **Your account → Publishing** for a personal project) with:
36
+ - PyPI project name: `claude-profile`
37
+ - Owner: `CloudOpsWorld`
38
+ - Repository: `claude-profile`
39
+ - Workflow name: `release.yml`
40
+ - Environment: `pypi`
41
+ 2. In the GitHub repo, the **Environment** named `pypi` must exist
42
+ (Settings → Environments) — optionally add required reviewers for a manual
43
+ approval gate before publish.
44
+
45
+ That's it: `release.yml` requests an OIDC token (`id-token: write`) and PyPI
46
+ trusts it. The first successful publish creates the project under the org.
47
+
48
+ ### Alternative: API token
49
+
50
+ If you prefer a token, add a repository secret `PYPI_API_TOKEN` and uncomment the
51
+ `password:` line in the `publish-pypi` job of `release.yml`.
52
+
53
+ ## Testing the pipeline first
54
+
55
+ - Run **Build** manually (Actions → Build → Run workflow) to confirm binaries and
56
+ the package build without cutting a release.
57
+ - Optionally point at **TestPyPI** first by adding `repository-url:
58
+ https://test.pypi.org/legacy/` to the publish step.
59
+
60
+ ## Re-running a failed publish
61
+
62
+ If the publish job failed (for example because the pending publisher wasn't set
63
+ up yet), fix the cause and use **Re-run failed jobs** on that workflow run. The
64
+ tag and GitHub Release already exist, and `skip-existing: true` makes re-runs safe.
65
+
66
+ ## Local dry run
67
+
68
+ ```bash
69
+ pip install build twine
70
+ python -m build
71
+ twine check dist/*
72
+ ```
@@ -0,0 +1,185 @@
1
+ Metadata-Version: 2.4
2
+ Name: claude-profile
3
+ Version: 1.0.2
4
+ Summary: Per-customer profiles for Claude Code and Claude Desktop: separate logins, AI platforms, MCP servers, skills and history, side by side.
5
+ Author: claude-profile contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/CloudOpsWorld/claude-profile
8
+ Project-URL: Repository, https://github.com/CloudOpsWorld/claude-profile
9
+ Project-URL: Issues, https://github.com/CloudOpsWorld/claude-profile/issues
10
+ Keywords: claude,claude-code,claude-desktop,anthropic,profiles,mcp,deepseek,openrouter,cli
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: Microsoft :: Windows
16
+ Classifier: Operating System :: MacOS :: MacOS X
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Software Development
24
+ Classifier: Topic :: Utilities
25
+ Requires-Python: >=3.10
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=9.1.1; extra == "dev"
30
+ Requires-Dist: ruff>=0.15.21; extra == "dev"
31
+ Requires-Dist: mypy>=2.3.0; extra == "dev"
32
+ Requires-Dist: build>=1.5.1; extra == "dev"
33
+ Dynamic: license-file
34
+
35
+ # claudectl
36
+
37
+ Use Claude Code with a separate profile for each customer, on Windows, macOS and Linux. Each profile has its own:
38
+
39
+ - sign-in or API key
40
+ - AI platform
41
+ - MCP servers
42
+ - skills and plugins
43
+ - session history and memory
44
+
45
+ Customers can run side by side in separate terminals. Switching never touches a session that's already running, and one customer's Jira or Confluence server never shows up in another customer's session.
46
+
47
+ claudectl doesn't change anything machine-wide. Your normal `claude` and `~/.claude` keep working exactly as before, and appear as the `default` profile.
48
+
49
+ It's pure Python 3.10+ with no dependencies beyond the standard library.
50
+
51
+ ## Install
52
+
53
+ From PyPI (the package is `claude-profile`, the command is `claudectl`):
54
+
55
+ ```bash
56
+ pipx install claude-profile # or: uv tool install claude-profile or: pip install claude-profile
57
+ claudectl install # optional: adds the "Claude Profiles" Start menu picker on Windows
58
+ ```
59
+
60
+ **Without Python:** download a standalone binary from [Releases](https://github.com/CloudOpsWorld/claude-profile/releases) and run it once with `install`, which puts it in `~/.local/bin`:
61
+ - `claudectl-windows-amd64.exe`
62
+ - `claudectl-macos-arm64`
63
+ - `claudectl-linux-amd64`
64
+
65
+ Each release has `SHA256SUMS` and build provenance you can check with `gh attestation verify <file> --repo CloudOpsWorld/claude-profile`.
66
+
67
+ **From source:**
68
+
69
+ ```bash
70
+ python claudectl/cli.py install
71
+ ```
72
+
73
+ This copies the single file to `~/.claudectl/app` and puts a launcher in `~/.local/bin`.
74
+
75
+ To remove claudectl, run `claudectl uninstall` (or `pipx uninstall claude-profile`). Your profiles are kept.
76
+
77
+ ## Daily use
78
+
79
+ ```bash
80
+ claudectl add acme # guided: name, AI platform, key or sign-in, bind this folder
81
+ cd ~/work/acme-repo
82
+ claudectl # starts Claude Code as ACME, because the folder is bound
83
+ claudectl tab globex # new terminal tab locked to Globex
84
+ claudectl acme --resume # any claude arguments pass through
85
+ claudectl mcp add jira -- npx -y <jira-mcp> # goes into this folder's profile only
86
+ claudectl list # profiles, bound folders, active profile, Desktop profile
87
+ ```
88
+
89
+ - **Bound folders** pick the profile automatically. If you start a different profile inside a bound folder, claudectl asks before continuing.
90
+ - **Everywhere else**, `claudectl` uses the active profile. Set it with `claudectl use <name>`.
91
+ - **Every session shows its customer** in Claude Code's status line and in the tab title.
92
+ - **On Windows**, tabs open in Windows Terminal with the customer's color. macOS uses Terminal.app. Linux uses the first terminal it finds: GNOME Terminal, Konsole, kitty, WezTerm, Alacritty or Xfce Terminal.
93
+
94
+ ## Import your existing setup
95
+
96
+ ```bash
97
+ claudectl import --scan # just show what's in your current Claude setup
98
+ claudectl import # guided: sort project folders into customer profiles
99
+ ```
100
+
101
+ **What the scan finds:**
102
+ - every project folder Claude has history for (worktrees are folded into their repo)
103
+ - MCP servers, both user-wide and per-project
104
+ - skills, agents, commands and output styles
105
+ - your `CLAUDE.md`, plugins and preferences
106
+ - Claude Desktop's MCP servers
107
+ - leftovers from older switcher scripts: extra `~/.claude-*` config folders, system-wide `ANTHROPIC_*` variables, and lines in your PowerShell or shell profile
108
+
109
+ It skips temporary folders, folders that no longer exist, your home folder and drive roots.
110
+
111
+ **The guided import** suggests customers from your folder layout. `D:\work\acme\api` and `D:\work\acme\web` become one `acme` profile, tied to `D:\work\acme`. You can:
112
+ - press Enter to accept each suggestion
113
+ - type a name to rename it or merge it into another profile
114
+ - press `k` to keep those folders in your default setup
115
+
116
+ Then you pick:
117
+ - the AI platform for each new profile
118
+ - which profiles get which MCP servers
119
+ - whether new profiles get your skills, `CLAUDE.md`, preferences and plugins (plugins are reinstalled cleanly in each profile)
120
+
121
+ **It only copies.** Each project's history, memory, prompt history, trust settings and per-project MCP servers go into its profile. Your current setup isn't changed, so it's safe while Claude is running.
122
+
123
+ **Your own sign-in, account details and caches are never copied into a customer profile.** The one exception: a `~/.claude-*` folder left by an older switcher is adopted whole, including its sign-in, because that sign-in belongs to the customer.
124
+
125
+ You can also work from a file, which is handy for many folders or for repeating the import:
126
+
127
+ ```bash
128
+ claudectl import --plan plan.json # write the suggestions to a file you can edit
129
+ claudectl import --apply plan.json --dry-run # show what would happen
130
+ claudectl import --apply plan.json # copy
131
+ claudectl import --apply plan.json --move # copy, then take it out of the default setup
132
+ ```
133
+
134
+ Running `--apply` again is safe: it never overwrites anything and doesn't duplicate history.
135
+
136
+ **`--move`** removes the imported customer folders, history and MCP servers from your default setup:
137
+ - It refuses while any Claude Code session is running, including Desktop's Code tab.
138
+ - It backs up your config first.
139
+ - It puts everything it removes in `~/.claudectl/import-backups/`.
140
+ - Desktop's Code tab uses your default setup, so moved history no longer shows up there.
141
+
142
+ `--from DIR` imports from another Claude config folder instead of `~/.claude`.
143
+
144
+ ## AI platforms
145
+
146
+ | Platform | How it connects |
147
+ |---|---|
148
+ | Claude subscription: Pro, Max, Team, Enterprise | Browser sign-in on first start. You can lock it to the customer's org UUID. |
149
+ | Anthropic API key | Pay per use. |
150
+ | DeepSeek | Native Claude-compatible endpoint. |
151
+ | OpenRouter | GPT, Gemini and others. Use this for OpenAI customers, with BYOK for their own OpenAI key. |
152
+ | Any Claude-compatible URL | For example a LiteLLM proxy in front of a direct OpenAI key, Moonshot, Z.ai or a company gateway. |
153
+ | AWS Bedrock, Google Vertex | Claude through the customer's own cloud account. |
154
+
155
+ To add a platform, create `~/.claudectl/providers.json`: a JSON list of entries in the same shape as `BUILTIN_PROVIDERS` at the top of [claudectl/cli.py](claudectl/cli.py). An entry with an existing `id` replaces the built-in one. To change a profile's models, run `claudectl edit <name>`.
156
+
157
+ **Where API keys are stored:**
158
+ - **Windows:** encrypted with DPAPI, so only your Windows user can read them.
159
+ - **macOS:** in your login Keychain.
160
+ - **Linux:** in your keyring through `secret-tool`. Without a keyring, in a file only you can read.
161
+
162
+ ## Claude Desktop
163
+
164
+ Desktop holds one sign-in at a time, so it switches with a restart:
165
+
166
+ 1. Quit Desktop.
167
+ 2. Run `claudectl desktop acme`.
168
+ 3. Start Desktop.
169
+
170
+ This swaps the local MCP servers in Desktop's config. Each customer's servers are saved automatically when you switch away.
171
+
172
+ Cloud connectors added on claude.ai belong to the signed-in account and follow it. If the customer uses a different Claude account, sign out and back in.
173
+
174
+ **Not isolated:** Desktop's own Code tab uses Desktop's built-in Claude Code and login. Do isolated customer work in a terminal with claudectl.
175
+
176
+ ## Where things live
177
+
178
+ Everything is in `~/.claudectl`, on every OS. On Windows this is deliberately not AppData: Microsoft Store Python redirects new files there into a private folder that Claude Code can't see.
179
+
180
+ Each profile lives in `~/.claudectl/profiles/<name>/`:
181
+ - `profile.json`: platform, models, how the key is stored
182
+ - `config/`: Claude Code's own folder for this customer (login, MCP, skills, plugins, history, memory)
183
+ - `desktop-mcp.json`: this customer's Claude Desktop MCP servers
184
+
185
+ Set `CLAUDECTL_HOME` to put the data folder somewhere else.
@@ -0,0 +1,17 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ RELEASING.md
5
+ pyproject.toml
6
+ claude_profile.egg-info/PKG-INFO
7
+ claude_profile.egg-info/SOURCES.txt
8
+ claude_profile.egg-info/dependency_links.txt
9
+ claude_profile.egg-info/entry_points.txt
10
+ claude_profile.egg-info/requires.txt
11
+ claude_profile.egg-info/top_level.txt
12
+ claudectl/__init__.py
13
+ claudectl/__main__.py
14
+ claudectl/cli.py
15
+ scripts/claudectl_entry.py
16
+ scripts/demo.ps1
17
+ tests/test_claudectl.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ claudectl = claudectl.cli:main
@@ -0,0 +1,6 @@
1
+
2
+ [dev]
3
+ pytest>=9.1.1
4
+ ruff>=0.15.21
5
+ mypy>=2.3.0
6
+ build>=1.5.1
@@ -0,0 +1,3 @@
1
+ """claudectl - per-customer profiles for Claude Code and Claude Desktop."""
2
+
3
+ __version__ = "1.0.2"
@@ -0,0 +1,3 @@
1
+ from claudectl.cli import main
2
+
3
+ main()