# Agent Guidelines — Wobkey Impact 80 RGB CLI ## Objective Cross-platform Go CLI library for programmatic/agent-friendly control of VIA-compatible keyboard RGB lighting (starting with Wobkey Impact 80). ## Architecture ``` cmd/ # Cobra-based CLI entrypoints internal/device/ # HID device discovery (VID/PID matching) internal/via/ # VIA protocol implementation + LED subsystem internal/rgb/ # Effects, values, color definitions keyboards.json # VID/PID database + keyboard metadata ``` ## CLI Interface ``` wobkey keyboard info # Discover connected VIA-compatible keyboards wobkey rgb effect # Set RGB effect (e.g. "solid", "breathing", "wave") wobkey rgb brightness # Set brightness (0-255) wobkey rgb speed # Set effect speed (0-255) wobkey rgb color # Set solid color (e.g. "ff0000") wobkey rgb mode # Set mode by index wobkey rgb enable # Enable RGB lighting wobkey rgb disable # Disable RGB lighting wobkey rgb info # Show current RGB state ``` ## VIA Protocol Essentials - Transport: QMK Raw HID over a 32-byte hidraw report, report number `0` - Message types: - `0x07` — Custom set value - `0x08` — Custom get value - Impact 80 lighting channels: `0x02` logo, `0x03` backlight, `0x04` side - RGB value IDs: brightness `0x01`, effect `0x02`, speed `0x03`, color `0x04` - No separate enable handshake is used ## Keyboards (Known Wobkey VID/PID) | Keyboard | VID | PID | |------------------|--------|--------| | Wobkey Rainy 75 | 0x6666 | 0x0001 | | Wobkey Impact 80 | TBD | TBD | `keyboards.json` maps VID+PID → VIA protocol config + RGB layout metadata. ## Stack - Go 1.26+ (cross-platform: Linux, macOS, Windows) - `github.com/sstallion/go-hid` for HID access - `github.com/spf13/cobra` for CLI framework ## Constraints - CLI-first, no GUI — designed for automation and agent consumption - Output should be machine-parseable (JSON when possible) - Cross-platform from day one ## Go Development ### Tooling - `gopls` — Go Language Server, built into Go toolchain (LSP, diagnostics, go-to-def, rename, references) - `gofmt` / `goimports` — formatting. `goimports` adds/removes imports automatically. Always run before committing. - `go test` — built-in test framework. Tests live in `*_test.go` files alongside source. - `go vet` — static analysis. Run before committing. - `go build` — compiles without installing. Fast, cached. - `go mod tidy` — adds missing deps, removes unused ones. Run after every import change. ### Style (Effective Go + Code Review Comments) - **Formatting**: always `gofmt` or `goimports`. Tabs for indentation, no line-length limit but avoid uncomfortably long lines. - **Names**: `MixedCaps` / `mixedCaps`, no underscores. Short local variables (`i`, `c`, `r`). Descriptive for globals. - **Initialisms**: consistent case — `URL`, `ID`, `HTTP` → `appID`, `urlPony`, `ServeHTTP`. - **Comments**: doc comments start with the name, end with period. `// Package rgb provides RGB effect handling.` - **Imports**: standard library first, blank line, then third-party. Grouped. ### Error Handling - Return errors, never `panic` for normal control flow. - Indent error flow early — happy path at minimal indentation: ```go if err != nil { return err } // normal code ``` - Error strings: lowercase, no period — `fmt.Errorf("device not found")`. - Do not discard errors with `_`. ### Interfaces & Types - Define interfaces in the **consumer** package, not the producer. - Use pointer receivers when in doubt (mutation, large structs, sync fields). - Return concrete types from constructors — let consumers mock if needed. - Empty slices: `var t []string` (nil), not `t := []string{}` (non-nil), unless JSON encoding requires `[]`. ### Concurrency - Pass `context.Context` as **first parameter**. Never store in structs. - Clear goroutine lifetimes — document when/why they exit. Avoid leaks via channels. - Prefer synchronous functions — callers can add concurrency, not remove it. ### Testing - Table-driven tests preferred for multiple cases. - Failure messages: `t.Errorf("Effect(%q) = %d, want %d", input, got, want)`. - Use `*_test.go` files. Test package should match source package (internal tests). - Example functions (`func Example...`) double as docs and tests. ### Modules & Packages - Module path: `github.com//` (when published). - Package names: short, single-word, lowercase. No `util`, `common`, `api`, `types`. - Zero values should be useful (e.g. `bytes.Buffer`, `sync.Mutex`). ## graphify This project has a knowledge graph at graphify-out/ with god nodes, community structure, and cross-file relationships. When the user types `/graphify`, use the installed graphify skill or instructions before doing anything else. Rules: - For codebase questions, first run `graphify query ""` when graphify-out/graph.json exists. Use `graphify path "" ""` for relationships and `graphify explain ""` for focused concepts. These return a scoped subgraph, usually much smaller than GRAPH_REPORT.md or raw grep output. - Dirty graphify-out/ files are expected after hooks or incremental updates; dirty graph files are not a reason to skip graphify. Only skip graphify if the task is about stale or incorrect graph output, or the user explicitly says not to use it. - If graphify-out/wiki/index.md exists, use it for broad navigation instead of raw source browsing. - Read graphify-out/GRAPH_REPORT.md only for broad architecture review or when query/path/explain do not surface enough context. - After modifying code, run `graphify update .` to keep the graph current (AST-only, no API cost).