Skip to content

Commit b795e95

Browse files
authored
docs: add AGENTS contribution guide (#1)
1 parent 9f8b730 commit b795e95

1 file changed

Lines changed: 194 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
You are an experienced, pragmatic software engineering AI agent. Do not over-engineer a solution when a simple one is possible. Keep edits minimal. If you want an exception to ANY rule, you MUST stop and get permission first.
2+
3+
# Project Overview
4+
5+
This repository contains the Linux-focused Coder Desktop implementation in C#/.NET. The app provides tray-based access to Coder workspaces through a local VPN-like tunnel (`Coder Connect`) and includes Linux packaging assets for distribution.
6+
7+
Primary goals:
8+
- Provide a Linux desktop/tray UX for connecting to Coder workspaces.
9+
- Coordinate with a local/root VPN service over RPC.
10+
- Ship installable Linux artifacts (`.deb`, `.rpm`, `.tar.gz`, and AUR source bundle).
11+
12+
Technology choices:
13+
- **Language/runtime:** C# on .NET 8 (`net8.0` across projects)
14+
- **UI:** Avalonia 11 (`App.Avalonia`)
15+
- **Architecture:** DI with `Microsoft.Extensions.*`, shared ViewModel/service layer in `App.Shared`
16+
- **RPC/protocol:** Protobuf messages (`Vpn.Proto/vpn.proto`) + custom stream RPC (`Vpn/Speaker.cs`)
17+
- **Logging:** Serilog + Microsoft.Extensions.Logging
18+
- **Testing:** NUnit (`Tests.*` projects)
19+
- **Packaging:** Bash scripts under `Packaging.Linux/`
20+
21+
# Reference
22+
23+
## Important files
24+
25+
- `Coder.Desktop.sln` — solution entrypoint for all projects
26+
- `App.Avalonia/App.axaml.cs` — application composition root (DI/service registration, startup flow)
27+
- `App.Avalonia/Program.cs` — UI process entrypoint + bootstrap logging
28+
- `App.Shared/Services/RpcController.cs` — app-side RPC lifecycle/state orchestration
29+
- `Vpn/Speaker.cs` — generic request/reply protocol transport over streams
30+
- `Vpn.Proto/vpn.proto` — protocol contract used by app/service/tunnel
31+
- `Vpn.Service/Program.cs` — VPN service host, config sources, platform transport wiring
32+
- `scripts/run-linux-dev.sh` — local Linux dev launcher (service + app)
33+
- `.github/workflows/ci.yaml` — CI source of truth for baseline build/test checks
34+
- `.editorconfig` — formatting/style baseline (including line endings)
35+
36+
## Important directories
37+
38+
- `App.Avalonia/` — Avalonia UI, views, controls, Linux desktop host wiring
39+
- `App.Shared/` — cross-UI application logic (ViewModels/Models/Services abstractions)
40+
- `App.Linux/` — Linux-only service implementations (startup, credential backend, notifications)
41+
- `Vpn.Service/` — long-running manager service (systemd-compatible on Linux)
42+
- `Vpn/`, `Vpn.Linux/`, `Vpn.Proto/` — RPC core, Linux transports, protobuf schema
43+
- `CoderSdk/`, `MutagenSdk/` — API clients and vendored proto-related integration code
44+
- `Tests.CoderSdk/`, `Tests.Vpn*/` — NUnit unit/integration-style test projects
45+
- `Packaging.Linux/` — package build scripts, unit files, desktop metadata
46+
- `scripts/` — developer automation scripts
47+
48+
## Project architecture (high level)
49+
50+
1. `App.Avalonia` boots and builds DI container in `App.axaml.cs`.
51+
2. `RpcController` in `App.Shared` connects to the local service via `IRpcClientTransport` (`UnixSocketClientTransport` on Linux).
52+
3. RPC is executed via `Speaker<TSend,TReceive>` request/reply framing and protobuf payloads.
53+
4. `Vpn.Service` hosts service logic (`Manager`, `TunnelSupervisor`, etc.) and exposes RPC over Unix socket.
54+
5. Packaging scripts stage/publish both app and service binaries into Linux package formats.
55+
56+
# Essential commands
57+
58+
Run all commands from repository root.
59+
60+
## Build
61+
62+
```bash
63+
dotnet restore Coder.Desktop.sln
64+
dotnet build Coder.Desktop.sln -c Release --no-restore
65+
```
66+
67+
## Format
68+
69+
```bash
70+
dotnet format Coder.Desktop.sln
71+
```
72+
73+
## Lint
74+
75+
No dedicated linter script exists. Use formatting/analyzer verification:
76+
77+
```bash
78+
dotnet format Coder.Desktop.sln --verify-no-changes
79+
```
80+
81+
## Test
82+
83+
Match CI coverage:
84+
85+
```bash
86+
dotnet test Tests.CoderSdk/Tests.CoderSdk.csproj --no-restore -v q
87+
dotnet test Tests.Vpn.Proto/Tests.Vpn.Proto.csproj --no-restore -v q
88+
dotnet test Tests.Vpn/Tests.Vpn.csproj --no-restore -v q
89+
dotnet test Tests.Vpn.Service/Tests.Vpn.Service.csproj --no-restore -v q
90+
```
91+
92+
## Clean
93+
94+
```bash
95+
dotnet clean Coder.Desktop.sln
96+
```
97+
98+
## Development server / local run
99+
100+
```bash
101+
./scripts/run-linux-dev.sh --show --sudo-service
102+
```
103+
104+
Useful variants:
105+
106+
```bash
107+
./scripts/run-linux-dev.sh --no-build -- --minimized
108+
./scripts/run-linux-dev.sh --help
109+
```
110+
111+
## Other important scripts
112+
113+
```bash
114+
# Multi-format Linux packages (deb/rpm/tar)
115+
VERSION=1.2.3 ./Packaging.Linux/build-release-packages.sh amd64
116+
117+
# AUR source bundle
118+
VERSION=1.2.3 ./Packaging.Linux/build-aur-source.sh
119+
120+
# Deb-only helper wrapper
121+
VERSION=1.2.3 ./Packaging.Linux/build-deb.sh amd64
122+
123+
# Refresh vendored Mutagen proto tree
124+
pwsh ./MutagenSdk/Update-Proto.ps1 -mutagenTag <tag>
125+
```
126+
127+
# Patterns
128+
129+
- **Keep App.Shared UI-framework-agnostic.**
130+
- Do: expose abstractions (`IWindowService`, `IDispatcher`) and neutral types.
131+
- Don’t: instantiate Avalonia-specific UI types in `App.Shared`.
132+
133+
- **UI thread handoff in ViewModels is explicit.**
134+
- Do: check `_dispatcher.CheckAccess()` and repost with `_dispatcher.Post(...)` when required.
135+
- Don’t: mutate UI-bound observable state from background threads.
136+
137+
- **Avoid redundant property writes in ViewModels.**
138+
- Do: compare old/new before assigning to reduce flashing and unnecessary notifications.
139+
- Don’t: blindly reassign observable properties during model refreshes.
140+
141+
- **RPC request/reply discipline.**
142+
- Do: use `SendRequestAwaitReply` for command flows needing responses and preserve message type checks.
143+
- Don’t: ignore unexpected message types or skip lifecycle transitions on failures.
144+
145+
- **Testing style.**
146+
- NUnit is standard; async tests commonly include `[CancelAfter(30_000)]` to avoid hangs.
147+
148+
# Anti-patterns
149+
150+
- **Do not wire both tray icon `Command` and click event behavior** in ways that double-trigger UI toggles (`App.Avalonia/App.axaml.cs` explicitly avoids this).
151+
- **Do not assume unvalidated URLs are safe for UI hyperlink controls**; invalid values can crash UI paths (see `TrayWindowViewModel` comments).
152+
- **Do not manually edit vendored/generated proto imports in `MutagenSdk/Proto/`** when they originate from Mutagen; regenerate via `Update-Proto.ps1`.
153+
- **Do not bypass serialization/lock patterns in RPC state management** (`RpcController` uses explicit operation/state locks for consistency).
154+
155+
# Code style
156+
157+
Source of truth: `.editorconfig`
158+
159+
Key rules currently in effect:
160+
- Default indentation: 4 spaces
161+
- JSON/YAML indentation: 2 spaces
162+
- `.proto` indentation: tabs (`indent_size = 1`)
163+
- Default line endings: `CRLF`
164+
- UTF-8, trim trailing whitespace, final newline
165+
- C# style prefers `var` in common scenarios and nullable reference types are enabled
166+
167+
When editing files, match surrounding style and existing naming/structure patterns.
168+
169+
# Commit and Pull Request Guidelines
170+
171+
## Before committing
172+
173+
- Run at minimum the CI-equivalent build/test flow for impacted areas.
174+
- If you touched shared/protocol/service code, run all test commands listed above.
175+
- If you touched packaging, run the relevant packaging script(s) and capture outputs/artifact names.
176+
177+
## Commit messages
178+
179+
Current history is minimal and imperative (e.g., `add linux release packaging workflow`).
180+
181+
Preferred format for new commits:
182+
- `type: concise imperative summary`
183+
- Examples: `fix: handle rpc reconnect timeout`, `build: adjust linux package dependencies`
184+
185+
If no clear type applies, use a concise imperative summary rather than vague text.
186+
187+
## Pull request description requirements
188+
189+
No PR template is present in this repository, so include:
190+
- **What changed** (bullet list)
191+
- **Why** (user/problem impact)
192+
- **How it was validated** (exact commands + results)
193+
- **Risk/rollback notes** for service, protocol, or packaging changes
194+
- **Screenshots/video** for tray/UI behavior changes

0 commit comments

Comments
 (0)