claude-use 0.3.6 → 0.5.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/README.md +6 -2
- package/dist/cli.cjs +30 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -74,6 +74,7 @@ Select an identity with:
|
|
|
74
74
|
- `claude @<name>` — equivalent, once `claude-use shim enable` has been run (see [Install](#install))
|
|
75
75
|
- `CLAUDE_ACCOUNT=<name> claude` — equivalent, via environment variable (this is `claude-use`'s own variable, read by its launcher; Anthropic's own multi-account convention is a plain `CLAUDE_CONFIG_DIR=<path> claude`, which `claude-use` builds on top of rather than replaces) — also needs the shim enabled first
|
|
76
76
|
- `claude-use identity use <name>` — persistently, until changed again
|
|
77
|
+
- `claude-use @<name>` — the same, terser: shorthand for `claude-use identity use <name>`, matching the `@name` convention the other forms above already use. Deliberately requires the `@` prefix and requires `@<name>` to be the *only* argument — identity names are user-chosen and unconstrained against `claude-use`'s own subcommand vocabulary (`identity`, `profile`, `rules`, `check`, `configure`, `doctor`, `shim`, `run`), so a bare `claude-use <name>` (no `@`) is deliberately left alone as an "unknown command" error rather than risking a future identity name colliding with a future subcommand name
|
|
77
78
|
|
|
78
79
|
A directory rule (see below) can also pin a specific identity to a path, overriding whichever one is otherwise active — useful as a safety net so a particular client's directory always uses the right login regardless of habit.
|
|
79
80
|
|
|
@@ -126,6 +127,8 @@ Every top-level entry in `~/.claude` is classified into one of five categories,
|
|
|
126
127
|
|
|
127
128
|
This is a safe-by-default posture: only `knowledge` and `settings` are shared out of the box. A configuration profile can open up `history` (or anything else) wholesale, or share individual items within a closed category.
|
|
128
129
|
|
|
130
|
+
**`all` is shorthand for every overridable category at once**, for a profile that wants "share everything except credentials" without hand-listing `runtime`, `history`, `knowledge`, and `settings` individually — `{ "categories": { "all": true } }` expands to exactly those four set to `true`. `secret` can never be included, by construction: `all` only ever expands over the four categories a configuration layer is allowed to toggle in the first place, the same restriction a hand-written `categories` object is already under. An explicit named category always wins over `all` in the same object regardless of which one is written first, so `{ "all": true, "runtime": false }` means "share everything except runtime" — the general `all` setting, narrowed by the specific override, matching how a more specific layer already beats a less specific one everywhere else in this cascade. The same shorthand works identically from `--category all=true`/`CLAUDE_USE_CATEGORY_OVERRIDE=all=true` and `claude-use profile set <name> --category all=true`, not just profile JSON files — one expansion, shared by all three input paths.
|
|
131
|
+
|
|
129
132
|
`secret`'s "never, cannot be overridden" is an absolute check `resolve/decide.ts` makes *before* running the two-phase cascade at all — not merely the least-specific layer in that cascade, the way every other category is. This matters because [The cascade](#the-cascade-how-everything-composes)'s general rule is that a specific `entries` override always beats a category default; `secret` is the one deliberate exception, so an explicit `entries: { "secret/.credentials.json": true }` anywhere in any layer is rejected outright, the same as a bare `categories: { secret: true }` would be — path-specificity never gets a chance to apply to this one category.
|
|
130
133
|
|
|
131
134
|
**`~/.claude.json` isn't in this table at all, because — unlike `backups/` above — it isn't sourced from `~/.claude` the way everything else here is.** It's a sibling *file* next to the `~/.claude` directory, not an entry inside it: the OAuth session, personal (user/local-scope) MCP server definitions, and per-project trust decisions (which directories you've approved Claude Code to run in, and what it's allowed to do there). It fully relocates to `$CLAUDE_CONFIG_DIR/.claude.json` when set, the same as everything else — confirmed both in Anthropic's own Agent SDK documentation and empirically in this project's own development. Because it's generated fresh by Claude Code itself the moment it first runs under a new `CLAUDE_CONFIG_DIR`, `claude-use` treats it the same way as `secret`: always identity-local, never part of the shared cascade, and — since it isn't even a descendant of `~/.claude` — never something the resolver's directory walk encounters at all, rather than something explicitly excluded by category. `~/.claude/backups/` holds rolling timestamped copies of it (capped at five, auto-rotating) for Claude Code's own config-migration safety; being a genuine descendant of `~/.claude`, it *is* something the resolver walks past, which is exactly why it's listed under `secret` in the table above rather than merely assumed safe.
|
|
@@ -275,7 +278,7 @@ claude-use identity set <name> --allow-ambient-credential # persistently, for
|
|
|
275
278
|
|
|
276
279
|
| What you're setting | Global (persistent) | Temporary (this run only) | Directory-scoped (persistent) |
|
|
277
280
|
|---|---|---|---|
|
|
278
|
-
| **Identity** | `claude-use identity use <name>` (writes `~/.claude-use/active-identity`) | `claude-use run @<name>` / `claude @<name>` (needs `claude-use shim enable`) / `CLAUDE_ACCOUNT=<name> claude` (same) | `claude-use rules add <path> --identity <name>`; or `.claude-use.json`'s `"identity"` |
|
|
281
|
+
| **Identity** | `claude-use identity use <name>` / `claude-use @<name>` (writes `~/.claude-use/active-identity`) | `claude-use run @<name>` / `claude @<name>` (needs `claude-use shim enable`) / `CLAUDE_ACCOUNT=<name> claude` (same) | `claude-use rules add <path> --identity <name>`; or `.claude-use.json`'s `"identity"` |
|
|
279
282
|
| **Configuration profile** | `claude-use profile set-default <name>`; or `claude-use identity set-default-profile <identity> <profile>` | `claude --config-profile <name>` / `CLAUDE_USE_CONFIG_PROFILE=<name> claude` | `claude-use rules add <path> --profile <name>`; or `.claude-use.json`'s `"configProfile"` |
|
|
280
283
|
| **A category** | `claude-use profile set <name> --category history=true`; or `claude-use configure <identity>` | `claude --category history=true[,knowledge=false,...]` / `CLAUDE_USE_CATEGORY_OVERRIDE="history=true,knowledge=false"` | `claude-use configure <identity>` run from inside the ruled directory; or `.claude-use.json`'s `"categories"` |
|
|
281
284
|
| **An individual entry** | `claude-use profile set <name> --entry "path"=true`; or `claude-use configure <identity> <path>` | `claude --share <path>[,<path>,...]` / `claude --hide <path>[,<path>,...]` / `CLAUDE_USE_ENTRY_OVERRIDE="path=true,otherpath=false"` | `claude-use configure <identity> <path>` run from inside the ruled directory; or `.claude-use.json`'s `"entries"` |
|
|
@@ -289,6 +292,7 @@ The scriptable `claude-use profile set ...` commands exist alongside the interac
|
|
|
289
292
|
```
|
|
290
293
|
claude-use identity add <name>
|
|
291
294
|
claude-use identity use <name>
|
|
295
|
+
claude-use @<name> # shorthand for `identity use <name>`
|
|
292
296
|
claude-use identity list
|
|
293
297
|
claude-use identity set-default-profile <identity> <profile>
|
|
294
298
|
claude-use identity set <name> [--allow-ambient-credential | --no-allow-ambient-credential]
|
|
@@ -493,7 +497,7 @@ install.sh # downloads the latest release's binary for the runni
|
|
|
493
497
|
# checksum, and installs it as both `claude` and `claude-use` in ~/.local/bin
|
|
494
498
|
```
|
|
495
499
|
|
|
496
|
-
`schema.ts` models `categories` and `entries` differently despite their identical JSON-object appearance in every example above, because they have opposite key cardinality: `categories` only ever touches the four overridable names in the [category table](#category-based-sharing), so it's a closed `z.strictObject({ runtime: z.boolean().optional(), history: z.boolean().optional(), knowledge: z.boolean().optional(), settings: z.boolean().optional() })` — deliberately omitting `secret` from the shape entirely, so an attempted `secret` key is rejected at parse time rather than relying only on the runtime check described above — while `entries` is genuinely open-ended (any literal or glob path, each required to carry its `<category>/` prefix per the [Category-based sharing](#category-based-sharing) section above) and stays a `z.record(z.string().regex(ENTRY_KEY_RE), EntryValueSchema)`. The closed shape for `categories` also gives editors real key-name autocomplete from the published JSON Schema (the `schema/` directory above), which a record type
|
|
500
|
+
`schema.ts` models `categories` and `entries` differently despite their identical JSON-object appearance in every example above, because they have opposite key cardinality: `categories` only ever touches the four overridable names in the [category table](#category-based-sharing) plus the `all` shorthand, so it's a closed `z.strictObject({ all: z.boolean().optional(), runtime: z.boolean().optional(), history: z.boolean().optional(), knowledge: z.boolean().optional(), settings: z.boolean().optional() })` piped through a `.transform()` that expands `all` into the four real categories and drops it from the result — deliberately omitting `secret` from the shape entirely, so an attempted `secret` key is rejected at parse time rather than relying only on the runtime check described above — while `entries` is genuinely open-ended (any literal or glob path, each required to carry its `<category>/` prefix per the [Category-based sharing](#category-based-sharing) section above) and stays a `z.record(z.string().regex(ENTRY_KEY_RE), EntryValueSchema)`. The closed shape for `categories` also gives editors real key-name autocomplete from the published JSON Schema (the `schema/` directory above) — generated with Zod's `io: "input"` option specifically because a schema with a `.transform()` can't be represented in JSON Schema at all under the default `"output"` mode, and `"input"` is what a hand-written config actually needs describing anyway, which a record type couldn't offer either way.
|
|
497
501
|
|
|
498
502
|
`ConfigProfile.extends` is a flat `z.array(z.string()).optional()` — a list of other profiles' *names*, resolved by `resolve/extends.ts` loading each named file and walking the resulting graph at runtime. It's correctly **not** a self-referential Zod schema (no `z.lazy()` needed): nothing in `ConfigProfile`'s own shape points back at `ConfigProfile`. Because each profile file validates in isolation, though, Zod has no way to catch a circular `extends` definition (`a` extends `b` extends `a`) — the walker in `resolve/extends.ts` needs its own cycle guard (a visited-set), independent of schema validation.
|
|
499
503
|
|
package/dist/cli.cjs
CHANGED
|
@@ -221857,7 +221857,7 @@ var categories_default_default = {
|
|
|
221857
221857
|
// package.json
|
|
221858
221858
|
var package_default = {
|
|
221859
221859
|
name: "claude-use",
|
|
221860
|
-
version: "0.
|
|
221860
|
+
version: "0.5.0",
|
|
221861
221861
|
description: "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
|
|
221862
221862
|
license: "Apache-2.0",
|
|
221863
221863
|
author: "Joseph Mearman <joseph@mearman.co.uk>",
|
|
@@ -236532,12 +236532,21 @@ function isOverridableCategory(name) {
|
|
|
236532
236532
|
function isCategoryName(name) {
|
|
236533
236533
|
return CATEGORY_NAMES.some((category) => category === name);
|
|
236534
236534
|
}
|
|
236535
|
+
function expandAllCategoryKey(pairs) {
|
|
236536
|
+
const { all, ...rest } = pairs;
|
|
236537
|
+
if (all === void 0) {
|
|
236538
|
+
return { ...rest };
|
|
236539
|
+
}
|
|
236540
|
+
const expanded = Object.fromEntries(OVERRIDABLE_CATEGORIES.map((category) => [category, all]));
|
|
236541
|
+
return { ...expanded, ...rest };
|
|
236542
|
+
}
|
|
236535
236543
|
var CategoryMapSchema = external_exports.strictObject({
|
|
236544
|
+
all: external_exports.boolean().optional(),
|
|
236536
236545
|
runtime: external_exports.boolean().optional(),
|
|
236537
236546
|
history: external_exports.boolean().optional(),
|
|
236538
236547
|
knowledge: external_exports.boolean().optional(),
|
|
236539
236548
|
settings: external_exports.boolean().optional()
|
|
236540
|
-
});
|
|
236549
|
+
}).transform((input) => expandAllCategoryKey(input));
|
|
236541
236550
|
var DURATION_RE = /^(?:0|[1-9][0-9]*)(?:ms|s|m|h|d|w)$/;
|
|
236542
236551
|
var DurationSchema = external_exports.string().regex(DURATION_RE);
|
|
236543
236552
|
var WhenSchema = external_exports.strictObject({
|
|
@@ -240187,6 +240196,19 @@ function useIdentity(paths, name) {
|
|
|
240187
240196
|
writeTextAtomic(paths.activeIdentityFile, `${name}
|
|
240188
240197
|
`);
|
|
240189
240198
|
}
|
|
240199
|
+
function tryRunAtIdentityShortcut(paths, argv) {
|
|
240200
|
+
if (argv.length !== 1) {
|
|
240201
|
+
return false;
|
|
240202
|
+
}
|
|
240203
|
+
const [token] = argv;
|
|
240204
|
+
if (token === void 0 || !token.startsWith("@") || token.length === 1) {
|
|
240205
|
+
return false;
|
|
240206
|
+
}
|
|
240207
|
+
const name = token.slice(1);
|
|
240208
|
+
useIdentity(paths, name);
|
|
240209
|
+
console.log(`Active identity is now "${name}".`);
|
|
240210
|
+
return true;
|
|
240211
|
+
}
|
|
240190
240212
|
function readActiveIdentity(paths) {
|
|
240191
240213
|
if (!import_node_fs4.default.existsSync(paths.activeIdentityFile)) {
|
|
240192
240214
|
return void 0;
|
|
@@ -240394,9 +240416,10 @@ function validateCategoryNames(patch) {
|
|
|
240394
240416
|
}
|
|
240395
240417
|
function setProfileCategories(paths, name, patch) {
|
|
240396
240418
|
requireProfileExists(paths, name);
|
|
240397
|
-
|
|
240419
|
+
const expandedPatch = expandAllCategoryKey(patch);
|
|
240420
|
+
validateCategoryNames(expandedPatch);
|
|
240398
240421
|
const existing = readProfile(paths, name) ?? {};
|
|
240399
|
-
const mergedCategories = { ...existing.categories, ...
|
|
240422
|
+
const mergedCategories = { ...existing.categories, ...expandedPatch };
|
|
240400
240423
|
return applyPatch(profileJsonPath(paths, name), ConfigProfileSchema, { categories: mergedCategories });
|
|
240401
240424
|
}
|
|
240402
240425
|
function setProfileEntries(paths, name, patch) {
|
|
@@ -241459,8 +241482,9 @@ var InvalidCliEntryKeyError = class extends Error {
|
|
|
241459
241482
|
key;
|
|
241460
241483
|
};
|
|
241461
241484
|
function toCategoryMap(pairs) {
|
|
241485
|
+
const expanded = expandAllCategoryKey(pairs);
|
|
241462
241486
|
const result = {};
|
|
241463
|
-
for (const [key, value] of Object.entries(
|
|
241487
|
+
for (const [key, value] of Object.entries(expanded)) {
|
|
241464
241488
|
if (!isOverridableCategory(key)) {
|
|
241465
241489
|
throw new InvalidCliCategoryError(key);
|
|
241466
241490
|
}
|
|
@@ -241785,7 +241809,7 @@ function main() {
|
|
|
241785
241809
|
const invokedName = import_node_path20.default.basename(process.argv[1] ?? "claude-use");
|
|
241786
241810
|
if (isInvokedAsClaude(invokedName)) {
|
|
241787
241811
|
runClaude();
|
|
241788
|
-
} else {
|
|
241812
|
+
} else if (!tryRunAtIdentityShortcut(resolveLayoutPaths(), process.argv.slice(2))) {
|
|
241789
241813
|
buildClaudeUseProgram().parse(process.argv);
|
|
241790
241814
|
}
|
|
241791
241815
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-use",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "A profile manager and launcher for Claude Code that lets one person run multiple logins from one machine while controlling what gets shared between them.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Joseph Mearman <joseph@mearman.co.uk>",
|