Add agent command group for non-interactive CLI control - #98
Open
Joacohbc wants to merge 3 commits into
Open
Conversation
Adds `devcontainer-cli agent`, an agent-facing facade over the CLI: a small command set that never opens a wizard and never waits for an answer, so an unattended session cannot hang on a TUI. - `agent cli-info [--json]` prints the live catalogue — modules, services, profiles, skills, how to add custom scripts, copyable assets and the path conventions — so an agent composes a create command from the ids this binary actually has instead of ones hardcoded in a document that can drift. - `agent create` is generate + build + up with prompting, overwriting and the build question already decided; `--no-up` stops after the build. - `agent clean` composes destroy with the removal of the image built for the project. A pulled image is left alone (other projects on the same profile share it) and an image already gone is not an error. `--all` widens the sweep past this project. - `connect`, `exec`, `forward`, `copy` and `list` reuse the existing handlers; `exec` requires a command, since `shell` without one opens a login shell that an agent can only hang on, and `list --json` returns structured entries. The flag registration of ssh/shell/port-forward/copy/ls moves into shared helpers so both spellings of each command are described in exactly one place, and destroy's target construction moves into destroyTargetFor. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmuL457oWuwXvrM7dRNun4
Rewrites the host-side skill so an agent reaching for this CLI finds the `agent` group first and the plain commands as a documented escape hatch, and points it at `agent cli-info` as the authority on module/service/profile/skill ids — the list in the markdown is a summary that can lag, the catalogue dump cannot. Fixes an id the document had wrong along the way: `zellij` is an always-on module, not something to pass to `--with`. The command that reads the catalogue is what surfaced it. Also documents the group in the README, in the AGENTS.md command table, and in a new architecture section covering the four load-bearing properties: the PreRunE defaults that only apply to unset flags, why `agent exec` refuses an empty command, why `agent create` registers the full generate flag set, and how `agent clean` resolves the project image before the destroy drops the catalog entry. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmuL457oWuwXvrM7dRNun4
A critical read of the agent facade found that the three failure modes a model actually hits with this CLI were all untouched by it. **agent exec ran as root.** There is no USER in the Dockerfile and no user: in the compose file, and shell leaves --user unset when given a command, so every `agent exec -- <cmd>` that wrote into the workspace left root-owned files in the user's real checkout on the host — which they then cannot edit without sudo. It now defaults to devuser through the existing agentDefaults, so an explicit --user still wins. This deliberately inverts shell's own rule, which leaves --user alone so it keeps working against a database container that has no devuser. Those now fail with `unable to find user devuser` until --user names the one they have. A loud failure beats a silently corrupted checkout. shell itself is unchanged, and a test pins that the two stay different on purpose. **A failed build exited 0.** saveAndPostProcess downgraded a failed `docker compose build` to a warning and returned nil, so generation reported success with no image; `agent create` then handed a caller a project it could not use, with the real cause scrolled away. It returns the error now — for the human command too, since a failed build is not a success for a script either. **Eight recovery hints pointed at the wizard.** Messages like "container is not running. Run 'devcontainer-cli'" sent a stuck non-interactive caller at the one command that hangs it. They now name up/start/agent create, and a test walks the source so the next message added cannot reintroduce it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AmuL457oWuwXvrM7dRNun4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces a new
agentcommand group that provides a non-interactive facade over the CLI for AI agents and automated tools. The group includes eight subcommands (cli-info,create,connect,exec,forward,copy,list,clean) that wrap or reuse existing human commands with agent-appropriate defaults (no prompts, required flags instead of interactive selection).Key Changes
New service layer (
cli/internal/service/agent.go):AgentService.Info()assembles the live catalogue (modules, services, profiles, skills, scripts, assets, paths) as structured data for agents to read before composing commandsAgentService.Clean()combines destroy + image cleanup into a single operationAgentInfo,AgentModuleInfo,AgentServiceInfo, etc.) that expose the CLI's capabilitiesNew command group (
cli/internal/cli/commands/agent.go):connect→ssh,exec→shell,forward→port-forward,copy→copy,list→ls) via extracted flag helperscli-info(catalogue dump) andcreate(generate + build + up in one call)agentDefaults()helper applies agent-specific flag defaults without overriding explicit user valuesNew info command (
cli/internal/cli/commands/agent_info.go):New create command (
cli/internal/cli/commands/agent_create.go):--forceand--buildby default; hides backwards-compatibility flags from--help--no-upto stop after build if neededFlag helper extraction:
ssh,shell,port-forward,copy,lsinto reusable helpers (addSshFlags,addShellFlags, etc.)Domain additions:
IsLocalImage()indomain/images.goto identify locally-built images (used by agent clean)CustomScriptNamePatternexport indomain/profile.gofor agent infoDocumentation updates:
cli/internal/infra/assets/skill-devcontainer-cli.mdandskills/devcontainer-cli/SKILL.md) to introduce the agent command group as the primary interfaceAGENTS.mdwith architecture notes on the facade patternTesting
cli/internal/service/agent_test.goandcli/internal/cli/commands/agent_test.gohttps://claude.ai/code/session_01AmuL457oWuwXvrM7dRNun4