From cc9e095ec4dc9f476312e16fe93efba08b5bae00 Mon Sep 17 00:00:00 2001 From: Natalie Perret <11332444+natalie-o-perret@users.noreply.github.com> Date: Wed, 1 Jul 2026 16:16:55 +0200 Subject: [PATCH] docs: add AGENTS.md --- AGENTS.md | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..3f194e403 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,149 @@ +# AGENTS.md + +## Command pattern - always use RegisterCLICommand + +All new commands must use the struct-based pattern. +**Do not copy the old flat `var cmd = &cobra.Command{...}` commands** - they +exist in `cmd/storage/`, `cmd/dns/`, `cmd/dbaas/` and are legacy. + +Read this file before writing any new command: +`cmd/aiservices/deployment/deployment_create.go` + +Skeleton: + +```go +type myResourceCreateCmd struct { + exocmd.CliCommandSettings `cli-cmd:"-"` + + _ bool `cli-cmd:"create"` + + Name string `cli-arg:"#" cli-usage:"NAME"` // required positional + Tag string `cli-arg:"?" cli-usage:"TAG"` // optional positional + Zone string `cli-short:"z" cli-usage:"zone"` // becomes --zone / -z flag +} + +func (c *myResourceCreateCmd) CmdAliases() []string { return exocmd.GCreateAlias } +func (c *myResourceCreateCmd) CmdShort() string { return "Create a resource" } +func (c *myResourceCreateCmd) CmdLong() string { return "..." } + +func (c *myResourceCreateCmd) CmdPreRun(cmd *cobra.Command, args []string) error { + exocmd.CmdSetZoneFlagFromDefault(cmd) + return exocmd.CliCommandDefaultPreRun(c, cmd, args) +} + +func (c *myResourceCreateCmd) CmdRun(_ *cobra.Command, _ []string) error { + // c.Name, c.Zone are already populated here + return nil +} + +func init() { + cobra.CheckErr(exocmd.RegisterCLICommand(parentCmd, &myResourceCreateCmd{ + CliCommandSettings: exocmd.DefaultCLICmdSettings(), + })) +} +``` + +Supported struct tags: + +| Tag | Purpose | +|---|---| +| `cli-cmd:"-"` | Exclude field from CLI processing | +| `cli-cmd:"name"` | Sets the cobra command name (use on a `_ bool` field) | +| `cli-arg:"#"` | Required positional argument | +| `cli-arg:"?"` | Optional positional argument; `[]string` becomes variadic | +| `cli-flag:"flag-name"` | Override the auto-derived kebab-case flag name | +| `cli-short:"z"` | Single-character shorthand | +| `cli-usage:"text"` | Flag usage string; also used as positional arg label in help | +| `cli-hidden:""` | Mark flag hidden | +| `cli-deprecated:"msg"` | Mark flag deprecated | + +Supported field types: `string`, `int64`, `bool`, `[]string`, `map[string]string`. +Any other type panics at startup. + +Global alias vars to use for `CmdAliases()`: +`exocmd.GListAlias`, `GShowAlias`, `GCreateAlias`, `GDeleteAlias`, `GRemoveAlias`. + +## Folder layout + +New command group: + +``` +cmd/// + .go <- var Cmd; init -> parent.AddCommand(Cmd) + _list.go + _show.go + _create.go + _delete.go + _list_test.go + ... +``` + +Then add a blank import to `cmd/subcommands/init.go` - nothing else needs wiring. + +## Tests + +Tests live in the same package (white-box). Construct the struct directly and +call `CmdRun(nil, nil)`. Use `pkg/testutils` for HTTP test servers and client +setup. See `cmd/aiservices/deployment/deployment_create_test.go`. + +## File header on every AI-touched file + +Add a comment at the top of every file you create or modify. Use the +appropriate syntax for the language, and pick the right verb: + +```go +// AI-generated by claude-sonnet-4.6 - not reviewed yet // new file +// AI-modified by claude-sonnet-4.6 - not reviewed yet // existing file +``` +```yaml +# AI-generated by claude-sonnet-4.6 - not reviewed yet +# AI-modified by claude-sonnet-4.6 - not reviewed yet +``` +```html + + +``` + +The reviewer removes the line once they have read and approved the file. +It must be the very first line (before `package`, shebangs, etc.) except +where the language requires otherwise (e.g. after ` + +This makes AI-touched commits greppable across history: + + git log --grep="AI-assisted" + +and shows Copilot as a co-author in GitHub's commit view. + +For PRs, append this footer to the description (after a `---`), listing only categories that apply: + +``` +> [!NOTE] +> AI assistance: PR description, test scaffolding, boilerplate code. +``` + +Omit categories that don't apply. Omit the footer entirely if AI contributed nothing. + +## Before opening a PR or issue + +Use the existing templates - don't replace them with free-form text: +- PRs: `.github/pull_request_template.md` +- Issues: `.github/ISSUE_TEMPLATE/` (bug-report, feature_request, other_request) + +Keep every heading, fill each section in. + +## Before opening a PR + +``` +make build +make test-verbose +golangci-lint run --timeout 4m +``` + +Update `CHANGELOG.md` under `## Unreleased` with the PR number.