AGENTS.md 5.7 KB

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 <name>          # Set RGB effect (e.g. "solid", "breathing", "wave")
wobkey rgb brightness <val>       # Set brightness (0-255)
wobkey rgb speed <val>            # Set effect speed (0-255)
wobkey rgb color <hex>            # Set solid color (e.g. "ff0000")
wobkey rgb mode <index>           # 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: HID reports, Report ID 0x52
  • Message types:
    • 0x01 — Enable/Handshake
    • 0x02 — Set Value
    • 0x03 — Get Value
  • RGB runs via QMK rgblight subsystem (LED-Type 0x01)
  • No existing Go package for VIA/QMK — must implement minimal protocol

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/<user>/<project> (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 "<question>" when graphify-out/graph.json exists. Use graphify path "<A>" "<B>" for relationships and graphify explain "<concept>" 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).