@synth1s/cloak 1.2.0 → 1.3.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synth1s/cloak",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "Cloak your Claude. Switch identities in seconds.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,8 @@
1
1
  import chalk from 'chalk'
2
+ import inquirer from 'inquirer'
2
3
  import { profileDir, profileExists, getActiveProfile } from '../lib/paths.js'
3
4
  import { validateAccountName } from '../lib/validate.js'
5
+ import { getRcFilePath, isAlreadyInstalled, installToRcFile } from '../lib/setup.js'
4
6
 
5
7
  export async function switchAccount(name, options = {}) {
6
8
  const validation = validateAccountName(name)
@@ -25,13 +27,46 @@ export async function switchAccount(name, options = {}) {
25
27
 
26
28
  const dir = profileDir(name)
27
29
 
30
+ // Shell integration is active — output for eval
28
31
  if (options.printEnv) {
29
32
  process.stdout.write(`export CLAUDE_CONFIG_DIR=${dir}\n`)
30
33
  process.stdout.write(`echo "${chalk.green(`✔ Now wearing cloak "${name}".`)}"\n`)
31
34
  return
32
35
  }
33
36
 
34
- // Manual instructions (no shell integration)
35
- console.log(chalk.dim('Run this command to switch:'))
36
- console.log(`\n export CLAUDE_CONFIG_DIR=${dir}\n`)
37
+ // No shell integration prompt user to set it up
38
+ console.log(chalk.yellow('\n⚠ Shell integration is required to switch accounts.\n'))
39
+
40
+ let choice = options.setupChoice
41
+ if (choice === undefined) {
42
+ const answer = await inquirer.prompt([{
43
+ type: 'list',
44
+ name: 'choice',
45
+ message: 'How would you like to proceed?',
46
+ choices: [
47
+ { name: 'Set it up now (recommended)', value: 'auto' },
48
+ { name: 'Show manual instructions', value: 'manual' },
49
+ ],
50
+ }])
51
+ choice = answer.choice
52
+ }
53
+
54
+ if (choice === 'auto') {
55
+ const rcFile = getRcFilePath()
56
+ if (!isAlreadyInstalled(rcFile)) {
57
+ installToRcFile(rcFile)
58
+ console.log(chalk.green(`✔ Shell integration added to ${rcFile}`))
59
+ } else {
60
+ console.log(chalk.dim(` Already installed in ${rcFile}`))
61
+ }
62
+ console.log(chalk.dim(`\n Reload your shell to activate:`))
63
+ console.log(chalk.dim(` source ${rcFile}\n`))
64
+ console.log(chalk.dim(` Then run:`))
65
+ console.log(chalk.dim(` claude account switch ${name}\n`))
66
+ } else {
67
+ console.log(chalk.dim('\n Add this to your shell config:'))
68
+ console.log(` eval "$(cloak init)"`)
69
+ console.log(chalk.dim('\n Then reload and run:'))
70
+ console.log(chalk.dim(` claude account switch ${name}\n`))
71
+ }
37
72
  }
@@ -0,0 +1,27 @@
1
+ import { readFileSync, writeFileSync, existsSync } from 'fs'
2
+ import { join } from 'path'
3
+ import { homedir } from 'os'
4
+
5
+ function getHome() {
6
+ return process.env.HOME || homedir()
7
+ }
8
+
9
+ export function getRcFilePath() {
10
+ const shell = process.env.SHELL || ''
11
+ if (shell.includes('zsh')) {
12
+ return join(getHome(), '.zshrc')
13
+ }
14
+ return join(getHome(), '.bashrc')
15
+ }
16
+
17
+ export function isAlreadyInstalled(rcFilePath) {
18
+ if (!existsSync(rcFilePath)) return false
19
+ const content = readFileSync(rcFilePath, 'utf8')
20
+ return content.includes('cloak init')
21
+ }
22
+
23
+ export function installToRcFile(rcFilePath) {
24
+ if (isAlreadyInstalled(rcFilePath)) return
25
+ const line = '\neval "$(cloak init)"\n'
26
+ writeFileSync(rcFilePath, line, { flag: 'a' })
27
+ }