|
| 1 | +# Repository Guidelines |
| 2 | + |
| 3 | +> **Last verified**: 2026-02-10 |
| 4 | +
|
| 5 | +Essential guidance for AI coding agents working in the Render CLI. |
| 6 | + |
| 7 | +## Project Overview |
| 8 | + |
| 9 | +**What**: Terminal interface for Render platform (Go + Bubble Tea TUI) |
| 10 | +**Why**: Manage deployments, services, logs, and infrastructure from the command line |
| 11 | + |
| 12 | +## Before You Code |
| 13 | + |
| 14 | +1. Search existing code for similar implementations |
| 15 | +2. Follow established patterns in `pkg/tui/` |
| 16 | +3. Check if types exist in `pkg/client/` before defining new ones |
| 17 | + |
| 18 | +## Boundaries |
| 19 | + |
| 20 | +**Never do (without explicit approval)**: |
| 21 | +- Edit files in `pkg/client/` (generated code) |
| 22 | +- Modify `*_gen.go` files |
| 23 | +- Remove existing tests |
| 24 | +- Change navigation stack architecture in `pkg/tui/stack.go` |
| 25 | + |
| 26 | +**Always ask first**: |
| 27 | +- Major TUI architectural changes |
| 28 | +- Adding new dependencies |
| 29 | +- Changes to command flag APIs (breaking changes) |
| 30 | + |
| 31 | +**Safe to do**: |
| 32 | +- Add new views in `pkg/tui/views/` |
| 33 | +- Add new commands in `cmd/` |
| 34 | +- Write tests anywhere |
| 35 | +- Refactor within a single package |
| 36 | + |
| 37 | +## When Uncertain |
| 38 | + |
| 39 | +- **Requirements unclear**: Ask before implementing |
| 40 | +- **Architecture questions**: Propose minimal approach, get feedback |
| 41 | +- **TUI interactions**: Describe intended flow, get confirmation |
| 42 | + |
| 43 | +Prefer small, incremental changes over large speculative implementations. |
| 44 | + |
| 45 | +## Essential Commands |
| 46 | + |
| 47 | +```bash |
| 48 | +# Building |
| 49 | +go build -o render . # Build binary |
| 50 | + |
| 51 | +# Testing |
| 52 | +go test ./... # All tests |
| 53 | +go test -run TestName ./pkg/... # Single test |
| 54 | + |
| 55 | +# Linting & Formatting |
| 56 | +golangci-lint run # Lint |
| 57 | +pre-commit run --all-files # All hooks |
| 58 | + |
| 59 | +# Type Generation (from public-api-schema) |
| 60 | +export RENDER_API_PATH=/path/to/api |
| 61 | +cd ../public-api-schema && ./generate-cli.sh |
| 62 | +``` |
| 63 | + |
| 64 | +## Project Structure |
| 65 | + |
| 66 | +- `cmd/` - Cobra command definitions |
| 67 | +- `pkg/client/` - **Generated** API client (READ-ONLY) |
| 68 | +- `pkg/tui/` - Bubble Tea TUI framework ([see AGENTS.md](pkg/tui/AGENTS.md)) |
| 69 | +- `pkg/config/` - User config file (`~/.render/cli.yaml`) |
| 70 | +- `pkg/cfg/` - Environment defaults (different from config!) |
| 71 | +- `pkg/command/` - Output formats, context utilities |
| 72 | +- `pkg/dependencies/` - Dependency injection container |
| 73 | +- `pkg/style/` - Lipgloss styling system |
| 74 | + |
| 75 | +## Key Patterns |
| 76 | + |
| 77 | +**TUI**: Elm Architecture (Message → Update → View). See [pkg/tui/AGENTS.md](pkg/tui/AGENTS.md). |
| 78 | + |
| 79 | +**Data Access**: Service → Repo → Client (three-layer architecture): |
| 80 | +- **Client** (`pkg/client/`): Generated HTTP client - never edit |
| 81 | +- **Repo** (`pkg/*/repo.go`): Wraps client, handles pagination & error parsing |
| 82 | +- **Service** (`pkg/*/service.go`): Business logic, orchestrates multiple repos, enriches data |
| 83 | + |
| 84 | +```go |
| 85 | +// Service combines data from multiple repos |
| 86 | +svc, _ := s.repo.ListServices(ctx, params) // calls client internally |
| 87 | +proj, _ := s.projectRepo.ListProjects(ctx) // different repo |
| 88 | +return s.enrich(svc, proj) // business logic |
| 89 | +``` |
| 90 | + |
| 91 | +**Output formats**: Use `command.IsInteractive(ctx)` for branching: |
| 92 | +```go |
| 93 | +if command.IsInteractive(ctx) { |
| 94 | + return runTUI(deps) |
| 95 | +} |
| 96 | +return runNonInteractive(ctx, deps) // JSON, YAML, TEXT |
| 97 | +``` |
| 98 | + |
| 99 | +**Naming**: |
| 100 | +| Element | Pattern | Example | |
| 101 | +|---------|---------|---------| |
| 102 | +| Commands | `New{Action}Cmd()` | `NewServiceListCmd()` | |
| 103 | +| Models | `{Entity}Model` | `ServiceListModel` | |
| 104 | +| Messages | `{Action}Msg` | `LoadServicesMsg` | |
| 105 | + |
| 106 | +## Testing Against Local Dev API |
| 107 | + |
| 108 | +```bash |
| 109 | +# Start API |
| 110 | +tilt up api |
| 111 | +curl -k https://api.localhost.render.com:8443/health |
| 112 | + |
| 113 | +# Configure CLI |
| 114 | +export RENDER_HOST="https://api.localhost.render.com:8443/v1/" |
| 115 | +export RENDER_API_KEY="your-api-key" |
| 116 | +./render services list |
| 117 | +``` |
| 118 | + |
| 119 | +| Variable | Description | |
| 120 | +|----------|-------------| |
| 121 | +| `RENDER_HOST` | API base URL | |
| 122 | +| `RENDER_API_KEY` | API key (skips OAuth) | |
| 123 | +| `RENDER_WORKSPACE` | Workspace ID override | |
| 124 | +| `RENDER_CLI_CONFIG_PATH` | Config file path override | |
| 125 | + |
| 126 | +## Testing |
| 127 | + |
| 128 | +- **Table-driven tests** with `stretchr/testify` |
| 129 | +- **Manual fakes** in `pkg/tui/testhelper/` |
| 130 | +- **Pre-commit hooks**: golangci-lint, go fmt, yaml checks, large file detection |
| 131 | + |
| 132 | +## Common Gotchas |
| 133 | + |
| 134 | +- Don't block in `Update()` - use `tea.Cmd` for async work |
| 135 | +- Handle `tea.KeyCtrlC` and `tea.KeyCtrlD` for proper exit |
| 136 | +- Run `reset` if terminal breaks after a crash |
| 137 | +- `Push()` returns a `tea.Cmd` that must be returned from `Update()` |
| 138 | +- Generated types are read-only - regenerate via `generate-cli.sh` |
| 139 | + |
| 140 | +## Package-Specific Guides |
| 141 | + |
| 142 | +- `pkg/tui/`: [See AGENTS.md](pkg/tui/AGENTS.md) for Bubble Tea patterns and examples |
| 143 | + |
| 144 | +## Reference |
| 145 | + |
| 146 | +- [Bubble Tea](https://github.com/charmbracelet/bubbletea) | [Cobra](https://github.com/spf13/cobra) | [Render CLI Docs](https://render.com/docs/cli) |
0 commit comments