claude-switch-profile 1.4.19 → 1.4.21

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.
@@ -3,6 +3,9 @@ name: Update Homebrew Formula
3
3
  on:
4
4
  push:
5
5
  tags: ['v*']
6
+ workflow_run:
7
+ workflows: ["Release on push to main"]
8
+ types: [completed]
6
9
  workflow_dispatch:
7
10
  inputs:
8
11
  version:
@@ -11,18 +14,23 @@ on:
11
14
 
12
15
  jobs:
13
16
  bump-formula:
17
+ if: github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success'
14
18
  runs-on: ubuntu-latest
15
19
  permissions:
16
20
  contents: write # Cho phép GITHUB_TOKEN mặc định được ghi dữ liệu vào repo này
17
21
  steps:
18
22
  - name: Checkout Repository
19
23
  uses: actions/checkout@v4
24
+ with:
25
+ fetch-depth: 0
20
26
 
21
27
  - name: Resolve Version
22
28
  id: version
23
29
  run: |
24
30
  if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
25
31
  VERSION="${{ github.event.inputs.version }}"
32
+ elif [ "${{ github.event_name }}" = "workflow_run" ]; then
33
+ VERSION=$(node -e "console.log(JSON.parse(require('fs').readFileSync('package.json', 'utf8')).version)")
26
34
  else
27
35
  VERSION="${{ github.ref_name }}"
28
36
  VERSION="${VERSION#v}"
@@ -1,34 +1,20 @@
1
- # Homebrew Formula Template for claude-switch-profile
2
- #
3
- # INSTRUCTIONS FOR MAINTAINER:
4
- # 1. Create a new GitHub repository named `homebrew-tap` (e.g. `ThanhThi2895/homebrew-tap`).
5
- # 2. Inside that repository, create a `Formula/` directory.
6
- # 3. Copy this file into `Formula/claude-switch-profile.rb`.
7
- # 4. Update the `url` and `sha256` fields with the latest npm tarball release.
8
- # (You can get the tarball url from `npm view claude-switch-profile dist.tarball`)
9
- # (You must calculate the sha256 of the tarball, e.g. `curl -sL <tarball_url> | shasum -a 256`)
10
-
11
1
  require "language/node"
12
2
 
13
3
  class ClaudeSwitchProfile < Formula
14
4
  desc "CLI tool for managing multiple Claude Code profiles"
15
5
  homepage "https://github.com/ThanhThi2895/claude-switch-profile"
16
- url "https://registry.npmjs.org/claude-switch-profile/-/claude-switch-profile-1.4.17.tgz"
17
- sha256 "REPLACE_WITH_ACTUAL_SHA256_OF_TARBALL"
6
+ url "https://registry.npmjs.org/claude-switch-profile/-/claude-switch-profile-1.4.20.tgz"
7
+ sha256 "5cb22677386f5220f92ccfe714e968e8121e27943daed2e816f6b1128cf8aba9"
18
8
  license "MIT"
19
9
 
20
10
  depends_on "node"
21
11
 
22
12
  def install
23
- # Language::Node.std_npm_install_args securely installs the node module into
24
- # the Homebrew Cellar, making it completely independent of any global Node.js
25
- # managers like NVM or FNM that the user might be running.
26
13
  system "npm", "install", *Language::Node.std_npm_install_args(libexec)
27
14
  bin.install_symlink Dir["#{libexec}/bin/*"]
28
15
  end
29
16
 
30
17
  test do
31
- # Simple test to verify the CLI initializes correctly
32
18
  assert_match "Usage: csp", shell_output("#{bin}/csp --help")
33
19
  end
34
20
  end
package/README.md CHANGED
@@ -51,6 +51,32 @@ brew install claude-switch-profile
51
51
  npm install -g claude-switch-profile
52
52
  ```
53
53
 
54
+ ## Uninstall
55
+
56
+ `csp uninstall` only removes the **CLI tool**. It does **not** delete any profile data.
57
+
58
+ - Profiles stay at `~/.claude-profiles/`
59
+ - Your `~/.claude` config is not mutated by this command
60
+
61
+ Choose uninstall method that matches how you installed CSP:
62
+
63
+ ```bash
64
+ # npm global install
65
+ csp uninstall --method npm
66
+ # then run:
67
+ npm uninstall -g claude-switch-profile
68
+
69
+ # Homebrew install
70
+ csp uninstall --method brew
71
+ # then run:
72
+ brew uninstall claude-switch-profile
73
+
74
+ # Standalone install.sh
75
+ csp uninstall --method standalone
76
+ # this removes ~/.local/bin/csp and ~/.csp-cli directly
77
+ ```
78
+
79
+ Use `--force` to skip confirmation.
54
80
 
55
81
  ## Quick Start
56
82
 
@@ -90,7 +116,7 @@ csp
90
116
  | `csp import <file>` | Import profile from archive |
91
117
  | `csp delete <name>` | Delete a profile |
92
118
  | `csp deactivate` | Switch back to `default` profile |
93
- | `csp uninstall` | Remove CSP and restore Claude to pre-CSP state |
119
+ | `csp uninstall --method <npm\|brew\|standalone>` | Uninstall csp CLI and keep all profiles |
94
120
 
95
121
  > 📖 **Full command reference with all options and detailed behavior:** [docs/commands-reference.md](docs/commands-reference.md)
96
122
 
package/bin/csp.js CHANGED
@@ -152,9 +152,9 @@ program
152
152
 
153
153
  program
154
154
  .command('uninstall')
155
- .description('Remove all profiles and restore Claude Code to pre-CSP state')
155
+ .description('Uninstall csp CLI while keeping all profile data intact')
156
156
  .option('-f, --force', 'Skip confirmation prompt')
157
- .option('--profile <name>', 'Restore specific profile instead of active one')
157
+ .option('--method <method>', 'Install method: npm | brew | standalone')
158
158
  .action(uninstallCommand);
159
159
 
160
160
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-switch-profile",
3
- "version": "1.4.19",
3
+ "version": "1.4.21",
4
4
  "description": "CLI tool for managing multiple Claude Code profiles",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,11 +1,10 @@
1
1
  import { existsSync, rmSync } from 'node:fs';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
2
4
  import { createInterface } from 'node:readline';
3
- import { getActive, profileExists, getProfileDir, ensureDefaultProfileSnapshot } from '../profile-store.js';
4
- import { removeItems, restoreItems } from '../item-manager.js';
5
- import { removeFiles, restoreFiles } from '../file-operations.js';
6
- import { withLock, createBackup, warnIfClaudeRunning } from '../safety.js';
7
- import { PROFILES_DIR, DEFAULT_PROFILE } from '../constants.js';
8
- import { success, error, info, warn } from '../output-helpers.js';
5
+ import { success, info, warn } from '../output-helpers.js';
6
+
7
+ const METHODS = ['npm', 'brew', 'standalone'];
9
8
 
10
9
  const confirm = (question) => {
11
10
  return new Promise((resolve) => {
@@ -17,80 +16,70 @@ const confirm = (question) => {
17
16
  });
18
17
  };
19
18
 
20
- export const uninstallCommand = async (options) => {
21
- const active = getActive();
19
+ const normalizeMethod = (method) => {
20
+ const normalized = (method || '').toLowerCase();
21
+ if (!normalized) return null;
22
+ return METHODS.includes(normalized) ? normalized : null;
23
+ };
22
24
 
23
- if (!existsSync(PROFILES_DIR)) {
24
- info('No profiles directory found. CSP is not initialized.');
25
- info('To remove the CLI: npm uninstall -g claude-switch-profile');
25
+ const printMethodHint = (method) => {
26
+ if (method === 'npm') {
27
+ info('Run this command to uninstall csp:');
28
+ info(' npm uninstall -g claude-switch-profile');
29
+ return;
30
+ }
31
+ if (method === 'brew') {
32
+ info('Run this command to uninstall csp:');
33
+ info(' brew uninstall claude-switch-profile');
26
34
  return;
27
35
  }
28
36
 
29
- const restoreProfile = options.profile || active;
30
- if (restoreProfile === DEFAULT_PROFILE) {
31
- try {
32
- ensureDefaultProfileSnapshot();
33
- } catch (err) {
34
- error(err.message);
35
- process.exit(1);
36
- }
37
+ info('Removed standalone install artifacts:');
38
+ info(' ~/.local/bin/csp');
39
+ info(' ~/.csp-cli');
40
+ };
41
+
42
+ const uninstallStandalone = () => {
43
+ const home = process.env.CSP_HOME || homedir();
44
+ const binDir = process.env.CSP_STANDALONE_BIN_DIR || join(home, '.local', 'bin');
45
+
46
+ rmSync(join(binDir, 'csp'), { force: true });
47
+ rmSync(join(home, '.csp-cli'), { recursive: true, force: true });
48
+ };
49
+
50
+ export const uninstallCommand = async (options) => {
51
+ const method = normalizeMethod(options.method);
52
+
53
+ if (!method) {
54
+ warn('Missing or invalid --method. Use one of: npm, brew, standalone');
55
+ return;
37
56
  }
38
57
 
39
- // Show what will happen
40
58
  console.log('');
41
- info('This will:');
42
- if (options.profile && profileExists(options.profile)) {
43
- info(` 1. Restore profile "${options.profile}" to ~/.claude`);
44
- } else if (active && profileExists(active)) {
45
- info(` 1. Restore active profile "${active}" to ~/.claude (use --profile <name> to choose)`);
46
- } else {
47
- warn(' 1. No profile to restore (managed items will be removed)');
48
- }
49
- info(` 2. Remove all profiles: ${PROFILES_DIR}`);
50
- info(' 3. You can then run: npm uninstall -g claude-switch-profile');
59
+ info('This will uninstall csp CLI only.');
60
+ info('Profiles are kept at ~/.claude-profiles (no data is removed).');
61
+ info(`Method: ${method}`);
51
62
  console.log('');
52
63
 
53
64
  if (!options.force) {
54
- const confirmed = await confirm('Uninstall CSP and remove all profiles? This cannot be undone. (y/N) ');
65
+ const confirmed = await confirm(`Proceed uninstall for method "${method}"? (y/N) `);
55
66
  if (!confirmed) {
56
67
  warn('Cancelled.');
57
68
  return;
58
69
  }
59
70
  }
60
71
 
61
- warnIfClaudeRunning();
62
-
63
- await withLock(async () => {
64
- // 1. Create final backup before uninstall
65
- try {
66
- const backupPath = createBackup();
67
- info(`Final backup created at ${backupPath}`);
68
- } catch {
69
- // Non-critical — profiles dir may be empty
70
- }
71
-
72
- // 2. Remove current managed items from ~/.claude
73
- removeItems();
74
- removeFiles();
75
-
76
- // 3. Restore the chosen profile's config
77
- if (restoreProfile && profileExists(restoreProfile)) {
78
- const profileDir = getProfileDir(restoreProfile);
79
- restoreItems(profileDir);
80
- restoreFiles(profileDir);
81
- success(`Restored "${restoreProfile}" profile to ~/.claude`);
82
- } else {
83
- warn('No profile restored. ~/.claude managed items have been cleared.');
84
- }
85
- });
72
+ if (method === 'standalone') {
73
+ uninstallStandalone();
74
+ success('Standalone csp uninstall completed.');
75
+ printMethodHint(method);
76
+ return;
77
+ }
86
78
 
87
- // 5. Remove profiles directory (after lock is released)
88
- rmSync(PROFILES_DIR, { recursive: true, force: true });
89
- success('Removed all profiles and CSP data.');
79
+ if (!existsSync(join(process.env.CSP_HOME || homedir(), '.claude-profiles'))) {
80
+ info('No profiles directory found.');
81
+ }
90
82
 
91
- console.log('');
92
- info('To complete uninstall, run:');
93
- info(' npm uninstall -g claude-switch-profile');
94
- info('');
95
- info('Restart your Claude Code session to apply changes.');
83
+ success('csp uninstall instructions are ready.');
84
+ printMethodHint(method);
96
85
  };