feat: add multi-profile support#25
Conversation
0df477a to
b53aeec
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0df477a530
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| store, err := config.LoadStore() | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to load config: %w", err) |
There was a problem hiding this comment.
Avoid loading config before skip-auth commands
Because this runs before the skipAuth check, commands that are intentionally local/no-auth, such as chatwoot auth login, chatwoot config path, and chatwoot version, now fail with failed to load config whenever ~/.chatwoot/config.yaml is malformed or unreadable. That removes the normal recovery path for a user with a corrupt config; defer this load for skip-auth commands or make profile resolution non-fatal there.
Useful? React with 👍 / 👎.
| if !stringIDNouns[args[i]] { | ||
| if _, err := strconv.Atoi(id); err != nil { | ||
| return args | ||
| } | ||
| } |
There was a problem hiding this comment.
Guard verb-first profile commands from being rewritten
For string-ID nouns this accepts any second token, so when a legal profile is named use, remove, or show, verb-first commands such as chatwoot profile show use or chatwoot profile remove use are misclassified as id-first forms and rewritten to profile use show / profile use remove, changing the operation to setting the default profile. Either reserve those names when profiles are created or skip the rewrite when the second token is already a profile verb.
Useful? React with 👍 / 👎.
Save and switch between multiple Chatwoot instances/accounts. A global --profile flag, the CHATWOOT_PROFILE env var, and a `profiles` / `profile <name> show|use|remove` command tree manage named profiles, each with its own keyring-stored token. Resolution order is --profile flag -> CHATWOOT_PROFILE -> configured default -> "default". - config.yaml now stores a `profiles` map with `default_profile`; legacy single-instance configs migrate into the `default` profile on first load, and that profile keeps its historical keyring entry, so upgrades need no re-login. - `auth login --profile <name>` saves into a named profile; `auth logout` signs out of only the active profile; `config view` and `auth status` report the active profile. - Keyring entries are per-profile (default keeps the "api-key" entry; named profiles use profile:<name>), so switching never crosses tokens. Implements the "Add profile support" TODO in internal/config. Docs, CHANGELOG, and the agent skill are updated; adds Store/migration, per-profile credential, profile-command, and id-first grammar tests.
b53aeec to
41a0a52
Compare
Summary
Adds named profiles so the CLI can manage more than one Chatwoot instance/account. A global
--profileflag, theCHATWOOT_PROFILEenv var, and aprofiles/profile <name> show|use|removecommand tree (following the existing noun grammar), each profile with its own keyring-stored token. Resolution order:--profile→CHATWOOT_PROFILE→ configured default →default.Implements the proposal in #24.
The existing flat
config.yamlmigrates into adefaultprofile on first load, and that profile keeps its historical keyring entry, so current users keep working with no re-login.One naming question worth settling before merge:
profilealready names the dev/prod build tag, so I relabeled that toBuild:inconfig viewand reserved "profile" for instances. Happy to adjust if you'd prefer different wording.Tests
internal/config/store_test.goand additions tocredentials_test.gocover store migration, active-profile precedence (flag/env/default), default promotion on remove, and per-profile credential isolation.internal/cmd/profile_test.gocovers theprofiles/profilecommands, andmain_test.gocovers the id-first grammar for string-id nouns. All existing tests pass unchanged.Green locally:
go vet,go build,go test -race -covermode=atomic ./...,govulncheck,golangci-lint, andgo mod tidy -diff.Notes
README usage, the agent skill (command table + read-only allowlist), CHANGELOG, and the package
CLAUDE.mds are updated. Thedefaultprofile keeps the legacyapi-keykeyring entry; named profiles use aprofile:<name>entry.