@@ -126,14 +126,43 @@ need to pass a reserved token through literally, put it after `--`:
126126swisscode -- --cc-profile # claude receives "--cc-profile"
127127```
128128
129+ ## The four things
130+
131+ Four concepts, and only the last one is a thing you launch.
132+
133+ | | What it is | Optional? |
134+ | ---| ---| ---|
135+ | ** Provider** | An endpoint dialect — base URL, which credential variable, default models, compatibility flags. Eight ship built in | No. Every account names one. * Adding your own* is the optional part |
136+ | ** Account** | ** Who pays.** One provider plus one credential: an API key, an env var, or a Claude subscription login | No |
137+ | ** Setup** | ** What runs.** Which CLI (` claude-code ` , ` kilo ` , ` opencode ` ), which model per tier, permissions, env | No. Every profile names one |
138+ | ** Profile** | ** The pairing.** One setup + one or more accounts + how to choose between them | No — this is what ` swisscode <name> ` launches |
139+
140+ ```
141+ swisscode work
142+ └── profile "work"
143+ ├── setup "cc" claude-code, opus/sonnet/haiku
144+ └── accounts ["personal", "team"] strategy: usage
145+ └── account "personal" → provider "anthropic" → subscription login
146+ ```
147+
148+ Why split at all: they vary independently. One setup ("Claude Code, yolo, GLM on
149+ every tier") can be pointed at several accounts, and one account can back several
150+ setups. A profile naming more than one account is how rotation works.
151+
152+ Two mistakes the tool now catches for you, because both used to fail silently:
153+ an ** account with no profile** cannot be launched (` swisscode <account-name> `
154+ selects a * profile* , so the name would go to the agent as a prompt), and ** two
155+ accounts that are the same subscription** share one quota while looking like two.
156+
129157## Profiles
130158
131- A profile is a named provider + key + models. Name one after each account,
132- client or experiment.
159+ Name one after each account, client or experiment.
133160
134161``` sh
135162swisscode config work # create or edit the "work" profile
136163swisscode config list # every profile (keys are never printed)
164+ swisscode config setups # what runs, and which profiles share each
165+ swisscode config accounts # who pays, and which profiles use each
137166swisscode config default work # used when nothing else applies
138167swisscode config rm old # deletes it, and any bindings to it
139168```
@@ -148,6 +177,21 @@ If the first word isn't a profile name it's passed straight to `claude`, so
148177` swisscode fix the login bug ` still works. To be explicit either way, use
149178` --cc-profile work ` — an unknown name there is an error rather than a prompt.
150179
180+ One exception to that fallthrough: a first word that names an ** account** or an
181+ ** setup** is refused rather than sent as a prompt, because it is far
182+ likelier to be a mis-aimed selection than the start of a sentence.
183+
184+ ```
185+ $ swisscode personal
186+ swisscode: "personal" is an account, not a profile — accounts say who pays, and
187+ a profile is the pairing you launch. Known profiles: work. Make one that uses it
188+ with `swisscode config <name>`, or send this word to the agent as a prompt with
189+ `swisscode -- personal …`.
190+ ```
191+
192+ It only fires on an exact match against a name in your own config, so ordinary
193+ prompts are untouched — and ` swisscode -- personal … ` sends it through verbatim.
194+
151195Profile names must start with a letter or digit and contain only letters,
152196digits, ` . ` , ` _ ` or ` - ` . Names that would collide with a subcommand, or with a
153197word you're likely to start a prompt with (` fix ` , ` test ` , ` run ` , …), are
@@ -354,15 +398,35 @@ key — it is a **login**, stored by Claude Code in your keychain and pointed at
354398An account is one or the other, never both; a config naming a key * and* a
355399session directory is refused rather than resolved by precedence.
356400
401+ The terminal wizard covers this too — pick ** Anthropic (direct)** in
402+ ` swisscode config <name> ` and it asks how the account pays, offering a
403+ subscription kept separate from your other logins, the login you already use, or
404+ an API key. Or do it directly:
405+
357406``` sh
358407swisscode config accounts login work # make a session dir, run /login inside
359408swisscode config accounts login personal --dir ~ /.claude # adopt the login you already have
360409swisscode config accounts # who each account is, no keychain prompt
361410```
362411
363- ` login ` creates ` ~/.config/swisscode/accounts/<name> ` at ` 0700 ` , then runs the
364- agent there so you can complete ` /login ` once. After that the account is a
365- normal thing profiles can reference.
412+ ` login ` creates ` ~/.config/swisscode/accounts/<name> ` at ` 0700 ` , mints a profile
413+ of the same name so there is something to launch, then runs the agent there so
414+ you can complete ` /login ` once.
415+
416+ The profile matters: an account says * who pays* , and ` swisscode <name> ` selects
417+ a ** profile** . Without one the account is unreachable — which is why `config
418+ accounts` and ` config doctor` both flag an account no profile uses. Pass
419+ ` --no-profile ` if you mean to wire it into an existing multi-account profile
420+ yourself.
421+
422+ > ** A new directory does not start logged out — it starts as a copy of the login
423+ > you already have.** Claude Code seeds a fresh ` CLAUDE_CONFIG_DIR ` from your
424+ > current session, so if you exit without running ` /login ` as a * different*
425+ > account, you end up with two names for one subscription: both report their own
426+ > email and plan, both work, and neither adds any capacity. ` config accounts `
427+ > marks them ` DUPLICATE ` and ` config doctor ` fails the ` distinct accounts ` check,
428+ > because a ` usage ` profile would otherwise count that single quota twice and
429+ > rotate between two halves of the same thing.
366430
367431> ** Naming ` ~/.claude ` means * unsetting* ` CLAUDE_CONFIG_DIR ` , not setting it to
368432> that path.** Claude Code chooses its keychain item on whether the variable is
@@ -384,7 +448,7 @@ into each one to look. It caches them, and a profile with
384448` "strategy": "usage" ` then launches on whichever account has the most left:
385449
386450``` json
387- { "agentProfile " : " default" , "accounts" : [" personal" , " work" ], "strategy" : " usage" }
451+ { "setup " : " default" , "accounts" : [" personal" , " work" ], "strategy" : " usage" }
388452```
389453
390454Ranking uses the ** tighter of the two windows, never their average** . An account
@@ -569,12 +633,12 @@ holds an API key in plaintext.
569633
570634``` json
571635{
572- "version" : 3 ,
636+ "version" : 4 ,
573637 "providerAccounts" : {
574638 "openrouter" : { "provider" : " openrouter" , "apiKey" : " sk-or-…" },
575639 "personal" : { "provider" : " anthropic" , "configDir" : " /Users/me/.claude" }
576640 },
577- "agentProfiles " : {
641+ "setups " : {
578642 "default" : {
579643 "agent" : " claude-code" ,
580644 "models" : {
@@ -590,7 +654,7 @@ holds an API key in plaintext.
590654 }
591655 },
592656 "profiles" : {
593- "work" : { "agentProfile " : " default" , "accounts" : [" openrouter" ], "strategy" : " single" }
657+ "work" : { "setup " : " default" , "accounts" : [" openrouter" ], "strategy" : " single" }
594658 },
595659 "defaultProfile" : " work" ,
596660 "bindings" : { "/Users/me/clients/acme" : " acme" },
@@ -599,12 +663,16 @@ holds an API key in plaintext.
599663```
600664
601665Three separate things, because they vary independently. A ** provider account**
602- is who pays — a key, or a subscription login. An ** agent profile** is what runs
603- — which CLI, which model per tier, which flags. A ** profile** pairs them and
604- says how to choose when it names more than one account (` single ` , ` round-robin ` ,
605- or ` usage ` ). One agent profile can be shared by several profiles that bill
606- different accounts, which is the arrangement the older flat shape could not
607- express.
666+ is who pays — a key, or a subscription login. A ** setup** is what runs — which
667+ CLI, which model per tier, which flags. A ** profile** pairs them and says how to
668+ choose when it names more than one account (` single ` , ` round-robin ` , or
669+ ` usage ` ). One setup can be shared by several profiles that bill different
670+ accounts, which is the arrangement the older flat shape could not express.
671+
672+ > Setups were called ` agentProfiles ` before v4. Two things one word apart —
673+ > "agent profile" and "profile" — read backwards to almost everyone, so the one
674+ > nobody types got the new name. Existing configs migrate on first read, and
675+ > ` config agents ` still works as an alias for ` config setups ` .
608676
609677` bindings ` records absolute paths, which means client names and project layout.
610678That's new non-credential information in this file — worth remembering before
0 commit comments