# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

zrok is a secure, zero-trust internet sharing platform built on OpenZiti. This repo is a Go monorepo containing the
CLI/agent binary, the controller (REST API service), several React UIs, and SDKs in Go/Node.js/Python.

Project-wide contribution conventions (naming, style guides per language, Markdown rules) live in `CONTRIBUTING.md`
and are the authoritative source — this file is git-ignored and supplements it for local agent use only.

## Naming

- **zrok** (lowercase, never code-quoted) is the project name in prose/headings.
- **`zrok2`** (code-quoted) is the CLI binary name and the namespace for code-level identifiers (package names,
  service units, env vars like `ZROK2_TOKEN`).

## Build

Requires Go (see `go.mod` for version), Node.js v18+, and a C compiler (CGO required for SQLite3).

```bash
# Build UI assets (only needed once, or when UI source changes)
(cd ui && npm install && npm run build)
(cd agent/agentUi && npm install && npm run build)

# Build the zrok2 binary
mkdir -p dist
go build -o dist ./cmd/zrok2
```

Snapshot build matching CI, with embedded UIs: `goreleaser build --snapshot --clean -f .goreleaser-linux-amd64.yml`
(other platform configs: `.goreleaser-darwin.yml`, `.goreleaser-windows.yml`, `.goreleaser-linux-{arm64,armel,armhf}.yml`).

Docker-based / cross-compiled builds: `bin/build.bash` (see `docker/images/cross-build/README.md`).

## Test

```bash
go test ./...                 # full Go test suite (what CI runs)
go test ./controller/limits/...      # a single package
go test -run TestName ./path/to/pkg  # a single test
```

Python SDK: `cd sdk/python && pytest --cov=zrok_api --verbose src/`, linted with `flake8 .` using the root `.flake8`
config (also applies to any other Python in the repo).

UI lint: `(cd ui && npm run lint)`, `(cd agent/agentUi && npm run lint)`.

Markdown lint (run on every changed `.md` file before a PR): `npx markdownlint-cli <file>` using `.markdownlint.yaml`.

CI reference: `.github/workflows/ci-build.yml` builds both UIs, `go install`s all of `./...`, runs `go test -v ./...`,
and runs the Python SDK matrix (3.10–3.13) with pytest + flake8. `.github/workflows/integration-tests.yml` and
`node-sdk.yml` cover integration and Node SDK testing respectively.

## Architecture

### Binary and command tree

`cmd/zrok2/main.go` is the single CLI entrypoint (built as `zrok2`), using Cobra. Every subcommand file lives flat in
`cmd/zrok2/` (e.g. `sharePublic.go`, `agentStart.go`, `adminCreateAccount.go`) and registers itself onto one of the
root command groups defined in `main.go` (`share`, `access`, `admin`, `agent`, `config`, `create`/`delete`/`list`/
`modify`, `organization`, `rebase`, `test`). The same binary also embeds the `controller` server — `cmd/zrok2/controller.go`
invokes `controller.Run(cfg)`, so `zrok2 controller` runs the backend service from this binary too.

### Controller (backend service)

`controller/` is the REST API server backing the hosted/self-hosted zrok service.

- `controller/controller.go` wires every generated `rest_server_zrok/operations` handler to a `new*Handler()`
  constructor defined in a same-named file at the `controller/` top level (e.g. `createAccount.go` ↔
  `AccountRegisterHandler`, `listFrontends.go` ↔ `AdminListFrontendsHandler`). To add or change an API operation,
  the handler wiring, the handler implementation, and the OpenAPI spec (see below) all need to move together.
- `controller/store/` is the persistence layer (SQLite via CGO), one file per domain model (`account.go`, `share.go`,
  `environment.go`, `frontend.go`, `organization.go`, `namespace*.go`, grants, limits journal, etc.), with
  `controller/store/sql/` holding migrations.
- `controller/limits/` implements bandwidth/resource limit enforcement and classes (checked against InfluxDB metrics).
- `controller/agentController/` and `controller/dynamicProxyController/` are gRPC-based subsystems for managing
  remote zrok agents and dynamic proxy frontends respectively (`.proto` sources live alongside, regenerated via
  `bin/generate_pb.sh`).
- `controller/config/` defines the controller's own config file schema.
- `controller/automation/` and `controller/metrics/` handle scheduled housekeeping and metrics collection.

### Agent (local daemon)

`agent/` implements the local `zrok2 agent` daemon that manages shares/accesses on behalf of a user, exposed over
gRPC (`agent/agentGrpc/`, proto-generated) and a local web UI (`agent/agentUi/`, React). `agent/agent.go` is the
core event-loop type (`Agent`) coordinating shares and accesses via channels; `agent/proctree/` manages child
process lifecycles for the CLI's subordinate mode (see `cmd/zrok2/subordinate`).

### Endpoints (backend modes)

`endpoints/` implements each backend mode a share can front: `proxy` (HTTP reverse proxy), `publicProxy`,
`dynamicProxy`, `drive` (file sharing, built on `drives/davServer` — a WebDAV server), `socks`, `tcpTunnel`,
`udpTunnel`. `endpoints/proxyUi` renders the interstitial/warning pages shown to visitors of public shares.

### Environment (client-side config)

`environment/` models the local `~/.zrok` environment (enrolled identity, config, directories). `env_core` defines
the abstract `Root` interface; `env_v0_4` is the current on-disk format implementation. Most CLI/agent code depends
on `env_core.Root`, not the concrete version, to stay format-agnostic.

### Generated REST/API code — do not hand-edit

`rest_client_zrok/`, `rest_server_zrok/`, and `rest_model_zrok/` are generated by `go-swagger` from the OpenAPI spec.
`ui/src/api`, `agent/agentUi/src/api`, and `sdk/nodejs/sdk/src/api` (TypeScript fetch clients) and
`sdk/python/src/zrok_api` are generated by `openapi-generator-cli`. The source of truth is the modular spec under
`specs/src/*.yml` (`head.yml`, `account.yml`, `admin.yml`, `agent.yml`, `environment.yml`, `metadata.yml`,
`share.yml`, `definitions.yml`, `tail.yml`), combined into `specs/zrok.yml`. Regenerate everything with
`bin/generate_rest.sh` (requires `swagger` and `openapi-generator-cli` on `PATH`; must be run from the repo root).
Never hand-edit files under the generated directories — change the spec source and regenerate instead. gRPC/protobuf
code (`agent/agentGrpc`, `controller/dynamicProxyController`) is regenerated with `bin/generate_pb.sh`.

### SDKs

`sdk/golang`, `sdk/nodejs`, `sdk/python` are client SDKs for embedding zrok sharing into applications, each wrapping
the generated REST client for its language.

### UIs

- `ui/` — the web console (React + MUI + Vite), embedded into the controller binary via `ui/embed.go`.
- `agent/agentUi/` — the local agent's web UI, embedded into the CLI binary similarly.
- `tui/` — terminal UI helpers (Bubble Tea-style) used by CLI commands like `accessTui.go`/`shareTui.go`.

### Other

- `canary/` — synthetic/looping test harness for exercising a live deployment (public/private HTTP loopers).
- `drives/` — WebDAV client/server and sync logic backing `--backend-mode drive` shares.
- `util/` — small shared helpers (sizes, durations, host parsing, templating, CORS, etc.).
- `docker/images/cross-build/` — the Docker-based cross-compilation build used by `bin/build.bash`.
- `website/` — the Docusaurus documentation site (docs.zrok.io); build/dev commands are in `BUILD.md`. Documentation
  changes always target the unversioned `website/docs/` tree — `versioned_docs/`/`zrok_versioned_docs/` are frozen
  snapshots of past releases and are not maintained.

## Logging conventions

Uses `github.com/michaelquigley/df/dl` (new code) and legacy `pfxlog`/`logrus`. Log messages begin with a lowercase
letter and no trailing punctuation, e.g. `dl.Errorf("tried a thing and failed: %v", err)`. This convention applies
across Go and Python code in this repo.
