diff --git a/.mise.toml b/.mise.toml index 738fa1d27..f6ebf6461 100644 --- a/.mise.toml +++ b/.mise.toml @@ -3,3 +3,4 @@ go = "1.25" just = "latest" node = "22" bun = "latest" +uv = "latest" diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..ff18639ac --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,55 @@ +# AGENTS.md + +Test: `just test` | Before committing: `just ready` + +Read @CONTRIBUTING.md first. It covers prerequisites, setup, project structure, +code standards, testing, input validation, and how to add an API domain β€” all of +which apply to agents exactly as they apply to people. This file carries only +what is specific to agents. + +## Running tools + +Invoke tools through `mise`, not from your path: + +```bash +mise exec -- just test +``` + +`mise` is active in a person's shell and supplies the versions `.mise.toml` +declares. An agent's shell has no activation, so a bare `just` resolves to +whatever is installed globally β€” usually an older version. + +The symptom is a check that fails here and passes in continuous integration, on +a file nobody edited. When that happens, establish which version ran before +treating the failure as real. + +## Never build with the Go toolchain directly + +`go build ./...` and `go test ./...` fail in this repository. The UI is embedded +via `//go:embed dist/*`, which requires `ui/dist/` to hold files at compile +time. Use `just build`, `just test`, or `just ready` β€” each builds the UI first. +See @CONTRIBUTING.md under "Building and running". + +## Where the rules come from + +Repository layout, shared tooling, and the Go conventions this repository +follows are specified in [osapi-io/specs](https://github.com/osapi-io/specs). +When a convention here and the specification disagree, the specification wins β€” +say so rather than following the code. + +## Commit trailer + +When committing via Claude Code, end the message with: + +``` +πŸ€– Generated with [Claude Code](https://claude.ai/code) + +Co-Authored-By: Claude +``` + +## Task tracking + +Implementation planning and execution uses the superpowers plugin workflows +(`writing-plans` and `executing-plans`). Plans are working notes and are not +committed β€” the design record for a change lives in +[osapi-io/specs](https://github.com/osapi-io/specs). diff --git a/CLAUDE.md b/CLAUDE.md index d463eda75..4365898c8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,928 +1,8 @@ -# CLAUDE.md +# Claude Code -This file provides guidance to Claude Code (claude.ai/code) when working with -code in this repository. +All agent guidance lives in @AGENTS.md β€” how to invoke tools, why the Go +toolchain is never called directly, where the rules come from, the commit +trailer, and task tracking. This file exists so Claude Code finds it; the +content is upstream. -## Project Overview - -OSAPI is a Linux system management REST API and CLI written in Go 1.25. It uses -NATS JetStream for distributed async job processing with a KV-first, -stream-notification architecture. - -## Development Reference - -For setup, building, testing, and contributing, see the Docusaurus docs: - -- @docs/docs/sidebar/development/development.md - Prerequisites, setup, code - style, testing, commit conventions -- @docs/docs/sidebar/development/contributing.md - PR workflow and contribution - guidelines -- @docs/docs/sidebar/development/testing.md - How to run tests and list just - recipes -- @docs/docs/sidebar/development/ui-development.md - UI prerequisites, setup, - code style, components -- @docs/docs/sidebar/architecture/principles.md - Guiding principles - (simplicity, minimalism, design philosophy) -- @docs/docs/sidebar/architecture/api-guidelines.md - API design guidelines - (REST conventions, endpoint structure) -- @docs/docs/sidebar/architecture/ui.md - UI architecture, embedding, component - layers -- @docs/docs/sidebar/usage/configuration.md - Configuration reference - (osapi.yaml, env overrides) -- @docs/docs/sidebar/architecture/architecture.md - Architecture overview (links - to system and job architecture) - -Quick reference for common commands: - -```bash -just deps # Install all dependencies -just build # Build production binary (React UI + Go) -just test # Run all tests (lint + unit + coverage) -just go-unit # Run unit tests only -just go-unit-int # Run integration tests (requires running osapi) -just go-vet # Run golangci-lint -just go-fmt # Auto-format (gofumpt + golines) -go test -run TestName -v ./internal/job/... # Run a single test - -just react-dev # Start UI dev server (http://localhost:5173) -just react-build # Production UI build -just react-lint # Run ESLint on UI -just react-fmt # Format UI with Prettier -``` - -## Architecture (Quick Reference) - -- **`cmd/`** - Cobra CLI commands (`client`, `node agent`, `controller.api`, - `nats server`) -- **`internal/controller/api/`** - Echo REST API. Node-targeted handlers nest - under `node/{domain}/`. Controller-only handlers are top-level (`job/`, - `health/`, etc.). Each domain has its own `gen/` with OpenAPI spec. Combined - spec: `api/gen/api.yaml` -- **`internal/job/`** - Job domain types, subject routing. `client/` for - high-level ops -- **`internal/agent/`** - Node agent: consumer/handler/processor pipeline for - job execution -- **`internal/telemetry/tracing/`** - OpenTelemetry tracer initialization, slog - trace handler, context propagation\\ -- **`internal/telemetry/metrics/`** - Per-component Prometheus metrics server - with isolated registries\\ -- **`internal/provider/`** - Operation implementations organized by category - then domain. Browse the directory to see current providers -- **`internal/telemetry/process/`** - Agent self-metrics (CPU%, RSS, goroutines) - and process condition evaluation for heartbeat -- **`internal/controller/notify/`** - Pluggable condition notification system: - watches registry KV for condition transitions, dispatches via `Notifier` - interface (`log` backend) -- **`internal/config/`** - Viper-based config from `osapi.yaml`. Struct fields - use `validate` tags (same validator as API handlers). Defaults are set via - `viper.SetDefault()` in `cmd/root.go` -- **`pkg/sdk/`** - Go SDK for programmatic REST API access (`client/` client - library). See @docs/docs/sidebar/sdk/guidelines.md for SDK development rules -- Shared `nats-client` and `nats-server` are sibling repos, consumed as pinned - module versions in `go.mod` (no `replace` directive) - -## UI Architecture (Quick Reference) - -- **`ui/`** - React 19 + TypeScript + Vite + Tailwind CSS v4. Embedded into the - Go binary at build time. -- **`ui/src/sdk/gen/`** - Generated TypeScript SDK (orval) from the combined - OpenAPI spec. DO NOT EDIT. -- **`ui/src/sdk/fetch.ts`** - Hand-written fetch mutator: auth token + base URL - wiring for orval. -- **`ui/src/components/ui/`** - Reusable UI primitives. Every visual pattern is - a component. -- **`ui/src/components/layout/`** - Page structure (Navbar, PageLayout, - ContentArea, NetworkMapBackground). -- **`ui/src/components/domain/`** - Domain-specific components (blocks, cards, - pickers). -- **`ui/src/hooks/`** - Data fetching, state, keyboard navigation hooks. -- **`ui/src/lib/`** - `cn.ts`, `auth.tsx`, `permissions.ts`, `features.ts`. -- **`ui/embed.go`** - `//go:embed dist/*` directive exposing `ui.Assets`. -- **`internal/controller/api/ui/`** - SPA serving handler (static files + - `index.html` fallback for client-side routing). -- Config: `controller.ui.enabled` in `osapi.yaml` (default `true`). -- `//go:embed dist/*` requires `ui/dist/` to have files at compile time. Always - use `just build` / `just test` / `just ready` β€” these run `just react-build` - first. Running `go build` / `go test` directly without a prior UI build will - fail. - -## UI Conventions (MANDATORY) - -- One component per file. Use `cva` for variants, `cn()` for conditional - classes. -- Icons from lucide-react only. No inline styles β€” Tailwind only. -- Always use the `Text` component for styled text. Always use `Dropdown` β€” never - ``. -- Use Tailwind scale only (`text-xs`, `text-sm`, etc.). Never use arbitrary - pixel values like `text-[10px]`. - -### File naming - -- Components: `kebab-case.tsx` (e.g., `agent-card.tsx`) -- Hooks: `use-kebab-case.ts` (e.g., `use-health.ts`) -- Utilities: `kebab-case.ts` (e.g., `cn.ts`) - -## SDK regeneration - -When the OSAPI Go API changes, copy the combined OpenAPI spec from the osapi -repo and regenerate the TypeScript SDK: - -```bash -# In the osapi repo, run `just generate` first to produce the combined spec. -# Then copy it into this repo: -cp /internal/controller/api/gen/api.yaml src/sdk/gen/api.yaml - -# Regenerate typed fetch functions from the spec: -just react-generate -``` - -See the [Architecture](architecture.md) docs for the full generation flow. - -## Before committing - -Run `just ready` before committing to ensure SDK generation, formatting, lint, -and build are all up to date: - -```bash -just ready # generate + fmt + lint + build -``` - -## Branching - -All changes should be developed on feature branches. Create a branch from `main` -using the naming convention `type/short-description`, where `type` matches the -[Conventional Commits] type: - -- `feat/add-dns-block` -- `fix/agent-card-overflow` -- `docs/update-architecture` -- `refactor/extract-component` -- `chore/update-dependencies` - -When using Claude Code's `/commit` command, a branch will be created -automatically if you are on `main`. - -## Commit messages - -Follow [Conventional Commits] with the 50/72 rule: - -- **Subject line**: max 50 characters, imperative mood, capitalized, no period -- **Body**: wrap at 72 characters, separated from subject by a blank line -- **Format**: `type(scope): description` -- **Types**: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore` -- Summarize the "what" and "why", not the "how" - -Try to write meaningful commit messages and avoid having too many commits on a -PR. Most PRs should likely have a single commit (although for bigger PRs it may -be reasonable to split it in a few). Git squash and rebase is your friend! - -[bun]: https://bun.sh -[claude code]: https://claude.ai/code -[conventional commits]: https://www.conventionalcommits.org -[eslint]: https://eslint.org -[just]: https://just.systems -[mise]: https://mise.jdx.dev -[node.js]: https://nodejs.org -[prettier]: https://prettier.io