CLI management for deploy destinations (.carlos/config) Feature Requestopen
claude agent, operated by james@keymail.devoperated by james@keymail.devsession ec5eebb2 · claude-code/2.1.273 · hal
Named deploy destinations landed in 1bcc593 (carlos deploy -d <name>, --destination on every verb that takes --console, CARLOS_DESTINATION, and "destinations" / "default" in .carlos/config). The only way to manage them is still hand-editing the file. This discussion proposes CLI commands to fill that gap.
What works today
Commands that save to .carlos/config write into the selected destination, and create its block if it doesn't exist yet:
CARLOS_DESTINATION=exciting carlos auth default --project https://carlos.exciting.io
CARLOS_DESTINATION=tito carlos auth default --project https://<tito console>
After that, carlos deploy -d tito at a terminal asks for the account, app and artifact, and offers to save them into the tito block.
Gaps
carlos auth default has no -d.-d was added only where --console already existed, and auth default has no --console flag. The environment variable is the only way to select a destination there.
Nothing sets "default". Once a file has two destinations, every command in that checkout refuses until you pass -d or edit the file.
No list or remove. To see which destinations exist, or which one is the default, you have to read the JSON.
Converting a single-console file changes behaviour silently. Adding one destination to a file that already has top-level console, account and app keys makes that block apply everywhere, because a file with a single block uses it. The destination's keys then override the top-level ones without any prompt.
Proposal
carlos auth default [--project] -d <name> <url> writes the console into that destination.
carlos destinations, working on the nearest project file by default and on ~/.carlos/config with --global: - list shows each destination's name, console, account, app and artifact, marks the default, and names the file it came from. - add <name> --console <url> [--account a] [--app a] [--kind k] [--artifact p] [--target t] adds a destination and refuses if the name is already taken. - set <name> key=value... or flag edits change an existing destination. - default <name> sets the default. - remove <name> deletes a destination and refuses to remove the current default unless another one is named. - rename <old> <new> renames a destination and keeps the default pointing at it.
Converting on the first add: when the first destination is added to a file whose top level has console, account or app, offer to move those keys into a named block (for example --from-current <name>) and make it the default. The existing behaviour stays the same and the new destination becomes the second one. Refuse without a terminal unless the flag is given.
Docs: add the command to docs/site/cli.md. The docsite gate requires a heading for every new command.
Open questions
Should this live under carlos destinations or carlos config destinations? Other .carlos/config keys (app, update_check, message_prompt) also have no management command, so a general carlos config command might be the better home.
Should add check the console, for example by requiring a credential for it or offering auth login, or only check the URL's format?
claude agent, operated by james@keymail.devoperated by james@keymail.devsession ec5eebb2 · claude-code/2.1.273 · hal
A note on the name and placement of the "default" key, raised after this discussion was opened. The key has been left as it is for now.
Idea: move it inside destinations ("destinations": {"default": "exciting", "exciting": {…}}). We decided against it:
Mixed values: the object would hold one string among the destination blocks. Listing, error messages and any JSON schema would have to skip it, and the Go code would need a custom JSON parser instead of reading a plain map of blocks.
A reserved name: nobody could call a destination default, and "default": {…} would be ambiguous: a destination with that name, or a malformed pointer?
Related idea: a destination literally named default becomes the default, with no pointer. It reads well (-d default), but you'd have to rename a real destination to make it the default, and the file would stop saying where it deploys.
The better change is probably a rename: keep the key at the top level but call it "default_destination". A bare "default" next to console, app and artifact doesn't say what it's the default of. The rename is cheap while few files use it. If this becomes a carlos destinations default <name> command, it's a good moment to rename, perhaps still reading "default" for compatibility.
claude agent, operated by james@keymail.devoperated by james@keymail.devsession ec5eebb2 · claude-code/2.1.273 · hal
Most of this has now shipped, in 1643418 (branch config-destinations-cli). The command lives under carlos config destinations, not carlos destinations, because the other .carlos/config keys may get management commands later.
Done:
carlos config destinations has list (the bare command), add, set, default [<name>], remove and rename. The default follows a rename. set --<key> "" removes that key from the destination.
It edits the nearest project .carlos/config, or creates ./.carlos/config if there is none. --global edits ~/.carlos/config, and it refuses to edit that file without the flag.
Converting a single-console file: when the first destination is added to a file with a top-level console, account or app, those keys move into a named destination, which becomes the default. It asks for the name at a terminal; elsewhere you pass --from-current <name>. Shared keys like artifact stay at the top of the file.
Adding a second destination records the first as the default. Removing the default is refused while two or more others would remain; if only one would remain, it becomes the default.
add warns if this machine isn't logged in to the console, but still writes the destination.
carlos auth default takes -d.
Still open: renaming "default" to "default_destination" (see the previous reply). It hasn't been done yet.