@synth1s/cloak 1.5.0 → 1.6.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.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Cloak your Claude. Switch identities in seconds.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { program } from 'commander'
3
+ import { program, Option } from 'commander'
4
4
  import { readFileSync } from 'fs'
5
5
  import { fileURLToPath } from 'url'
6
6
  import { dirname, join } from 'path'
@@ -33,7 +33,7 @@ program
33
33
  .command('switch <name>')
34
34
  .alias('use')
35
35
  .description('Wear a different cloak')
36
- .option('--print-env', 'Output export command for eval (used by shell integration)')
36
+ .addOption(new Option('--print-env').hideHelp())
37
37
  .action((name, opts) => switchAccount(name, { printEnv: opts.printEnv }))
38
38
 
39
39
  program
@@ -56,11 +56,11 @@ program
56
56
  program
57
57
  .command('rename <old> <new>')
58
58
  .description('Rename a cloak')
59
- .action(renameAccount)
59
+ .action((oldName, newName) => renameAccount(oldName, newName))
60
60
 
61
61
  program
62
62
  .command('init')
63
- .description('Output shell integration code')
63
+ .description('Output shell integration code (use with eval)')
64
64
  .action(initShell)
65
65
 
66
66
  program.parse()
@@ -1,9 +1,10 @@
1
1
  import { renameSync } from 'fs'
2
+ import inquirer from 'inquirer'
2
3
  import { profileDir, profileExists, getActiveProfile } from '../lib/paths.js'
3
4
  import { validateAccountName } from '../lib/validate.js'
4
5
  import * as msg from '../lib/messages.js'
5
6
 
6
- export async function renameAccount(oldName, newName) {
7
+ export async function renameAccount(oldName, newName, options = {}) {
7
8
  const oldValidation = validateAccountName(oldName)
8
9
  if (!oldValidation.valid) {
9
10
  console.error(msg.validationError(oldValidation.error))
@@ -30,6 +31,24 @@ export async function renameAccount(oldName, newName) {
30
31
  return
31
32
  }
32
33
 
34
+ if (options.confirm === false) {
35
+ console.log(msg.cancelled())
36
+ return
37
+ }
38
+
39
+ if (options.confirm === undefined) {
40
+ const { confirm } = await inquirer.prompt([{
41
+ type: 'confirm',
42
+ name: 'confirm',
43
+ message: msg.prompts.renameConfirm(oldName, newName),
44
+ default: true,
45
+ }])
46
+ if (!confirm) {
47
+ console.log(msg.cancelled())
48
+ return
49
+ }
50
+ }
51
+
33
52
  renameSync(profileDir(oldName), profileDir(newName))
34
53
 
35
54
  if (getActiveProfile() === oldName) {
@@ -4,7 +4,8 @@ import * as msg from '../lib/messages.js'
4
4
  export function whoami() {
5
5
  const active = getActiveProfile()
6
6
  if (!active) {
7
- console.log(msg.noCloak())
7
+ // stderr for info messages, so piping `cloak whoami` gives clean output
8
+ console.error(msg.noCloak())
8
9
  return null
9
10
  }
10
11
  console.log(active)
@@ -5,7 +5,6 @@ const icon = {
5
5
  success: chalk.green('✔'),
6
6
  error: chalk.red('✖'),
7
7
  warning: chalk.yellow('⚠'),
8
- info: chalk.blue('ℹ'),
9
8
  tip: '💡',
10
9
  active: chalk.green('●'),
11
10
  inactive: chalk.dim('○'),
@@ -14,7 +13,7 @@ const icon = {
14
13
  // --- Success messages ---
15
14
 
16
15
  export function cloakCreated(name) {
17
- return `${icon.success} Cloak ${chalk.bold(`"${name}"`)} created.`
16
+ return `${icon.success} Cloak ${chalk.bold(`"${name}"`)} created. Ready to wear!`
18
17
  }
19
18
 
20
19
  export function cloakSwitched(name) {
@@ -26,11 +25,11 @@ export function cloakDiscarded(name) {
26
25
  }
27
26
 
28
27
  export function cloakRenamed(oldName, newName) {
29
- return `${icon.success} Cloak ${chalk.bold(`"${oldName}"`)} renamed to ${chalk.bold(`"${newName}"`)}.`
28
+ return `${icon.success} Cloak ${chalk.bold(`"${oldName}"`)} is now ${chalk.bold(`"${newName}"`)}.`
30
29
  }
31
30
 
32
31
  export function shellIntegrationAdded(rcFile) {
33
- return `${icon.success} Shell integration added to ${chalk.bold(rcFile)}`
32
+ return `${icon.success} All set! Shell integration added to ${chalk.bold(rcFile)}.`
34
33
  }
35
34
 
36
35
  // --- Error messages ---
@@ -40,7 +39,7 @@ export function validationError(error) {
40
39
  }
41
40
 
42
41
  export function accountNotFound(name) {
43
- return `${icon.error} Account ${chalk.bold(`"${name}"`)} not found.`
42
+ return `${icon.error} Couldn't find a cloak named ${chalk.bold(`"${name}"`)}.`
44
43
  }
45
44
 
46
45
  export function noActiveSession() {
@@ -48,35 +47,35 @@ export function noActiveSession() {
48
47
  }
49
48
 
50
49
  export function cannotDiscardActive() {
51
- return `${icon.error} Can't discard a cloak you're wearing.`
50
+ return `${icon.error} You're currently wearing this cloak.`
52
51
  }
53
52
 
54
53
  export function accountAlreadyInUse(name) {
55
- return `${icon.error} Account ${chalk.bold(`"${name}"`)} is already in use.`
54
+ return `${icon.error} A cloak named ${chalk.bold(`"${name}"`)} already exists.`
56
55
  }
57
56
 
58
57
  // --- Warning messages ---
59
58
 
60
59
  export function alreadyWearing(name) {
61
- return `${icon.warning} Already wearing cloak ${chalk.bold(`"${name}"`)}.`
60
+ return `${icon.warning} You're already wearing cloak ${chalk.bold(`"${name}"`)}.`
62
61
  }
63
62
 
64
63
  export function switchRequired() {
65
- return `${icon.warning} Shell integration is required to switch accounts.`
64
+ return `${icon.warning} Quick setup needed to enable switching.`
66
65
  }
67
66
 
68
67
  export function updateSessionAfterRename(newName) {
69
- return `${icon.warning} Run ${chalk.white(`claude account switch ${newName}`)} to update your session.`
68
+ return `${icon.warning} To keep using this cloak, run: ${chalk.white(`claude account switch ${newName}`)}`
70
69
  }
71
70
 
72
71
  // --- Info / hints ---
73
72
 
74
73
  export function suggestCreate(name) {
75
- return chalk.dim(` Run: claude account create ${name || '<name>'}`)
74
+ return chalk.dim(` Try: cloak create ${name || '<name>'}`)
76
75
  }
77
76
 
78
77
  export function suggestSwitchFirst() {
79
- return chalk.dim(' Switch to another account first.')
78
+ return chalk.dim(' Switch to a different cloak first, then try again.')
80
79
  }
81
80
 
82
81
  export function loginFirst() {
@@ -84,11 +83,11 @@ export function loginFirst() {
84
83
  }
85
84
 
86
85
  export function cancelled() {
87
- return chalk.dim('Cancelled.')
86
+ return chalk.dim('No changes made.')
88
87
  }
89
88
 
90
89
  export function noCloak() {
91
- return chalk.dim('No cloak. Using default Claude Code config.')
90
+ return chalk.dim('No cloak active — using default Claude Code config.')
92
91
  }
93
92
 
94
93
  export function noCloaksYet() {
@@ -96,7 +95,7 @@ export function noCloaksYet() {
96
95
  }
97
96
 
98
97
  export function accountListHeader() {
99
- return chalk.bold('\nClaude Code Accounts\n')
98
+ return chalk.bold('\nYour Cloaks\n')
100
99
  }
101
100
 
102
101
  export function accountListItem(name, isActive) {
@@ -107,13 +106,13 @@ export function accountListItem(name, isActive) {
107
106
  }
108
107
 
109
108
  export function alreadyInstalled(rcFile) {
110
- return chalk.dim(` Already installed in ${rcFile}`)
109
+ return chalk.dim(` Already set up in ${rcFile} — you're good!`)
111
110
  }
112
111
 
113
112
  // --- Setup instructions ---
114
113
 
115
114
  export function setupRunCommand(rcFile, name) {
116
- return chalk.dim('\n Run: ') + chalk.white(`source ${rcFile} && cloak switch ${name}\n`)
115
+ return chalk.dim('\n Almost there! Run: ') + chalk.white(`source ${rcFile} && cloak switch ${name}\n`)
117
116
  }
118
117
 
119
118
  export function setupManualCommand(rcFile, name) {
@@ -122,9 +121,10 @@ export function setupManualCommand(rcFile, name) {
122
121
 
123
122
  // --- Tip ---
124
123
 
125
- export function shellIntegrationTip() {
126
- return chalk.dim('\n💡 Tip: Run this once to enable "claude -a" and "claude account":\n') +
127
- chalk.dim(' echo \'eval "$(cloak init)"\' >> ~/.bashrc && source ~/.bashrc\n\n')
124
+ export function shellIntegrationTip(rcFile) {
125
+ const file = rcFile || '~/.bashrc'
126
+ return chalk.dim(`\n${icon.tip} Tip: Enable "claude -a" and "claude account" with:\n`) +
127
+ chalk.dim(` echo 'eval "$(cloak init)"' >> ${file} && source ${file}\n\n`)
128
128
  }
129
129
 
130
130
  // --- Print-env (stdout, no chalk — evaluated by shell) ---
@@ -134,16 +134,17 @@ export function printEnvExport(dir) {
134
134
  }
135
135
 
136
136
  export function printEnvEcho(name) {
137
- return `echo "${cloakSwitched(name)}"\n`
137
+ return `echo "Now wearing cloak ${name}."\n`
138
138
  }
139
139
 
140
140
  // --- Prompt messages ---
141
141
 
142
142
  export const prompts = {
143
- accountName: 'Account name:',
144
- overwriteConfirm: (name) => `Cloak "${name}" already exists. Overwrite?`,
145
- deleteConfirm: (name) => `Delete cloak "${name}"?`,
143
+ accountName: 'Name your cloak:',
144
+ overwriteConfirm: (name) => `Cloak "${name}" already exists. Replace it?`,
145
+ deleteConfirm: (name) => `Remove cloak "${name}"? This can't be undone.`,
146
+ renameConfirm: (oldName, newName) => `Rename cloak "${oldName}" to "${newName}"?`,
146
147
  setupChoice: 'How would you like to proceed?',
147
148
  setupAuto: 'Set it up now (recommended)',
148
- setupManual: 'Show manual instructions',
149
+ setupManual: 'Show me the manual steps',
149
150
  }
package/src/lib/tip.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import { shellIntegrationTip } from './messages.js'
2
+ import { getRcFilePath } from './setup.js'
2
3
 
3
4
  export function showTipIfNeeded() {
4
5
  if (process.env.CLOAK_SHELL_INTEGRATION === '1') return
5
6
  if (process.env.CLOAK_TIP_SHOWN === '1') return
6
7
  if (!process.stdout.isTTY) return
7
8
 
8
- process.stderr.write(shellIntegrationTip())
9
+ process.stderr.write(shellIntegrationTip(getRcFilePath()))
9
10
 
10
11
  process.env.CLOAK_TIP_SHOWN = '1'
11
12
  }