Build, lint, test, and verification workflow for the portal-tunnel Go+frontend monorepo. Use when setting up the repo, running CI-equivalent checks, or before committing changes.
npx skills add https://github.com/gosuda/portal-tunnel --skill dev-workflow
go1.26.4 via go.mod; the Makefile exports GOTOOLCHAIN=go1.26.4, so make targets self-pin even on other Go installs.make install installs the pinned dev tools: [email protected] and [email protected] (into $(go env GOPATH)/bin, usually ~/go/bin — put it on PATH).bun is needed only for make build-docs.Run these three before pushing; they are what CI enforces:
make vet # go vet ./cmd/... ./portal/... ./sdk/... ./types/... ./utils/...
make lint # golangci-lint run (same package set)
make test # go test -coverprofile=coverage.out (same set) + `cd frontend && npm test` (vitest)
Per AGENTS.md, run tests only when needed/asked; make tidy is local maintenance, not a CI gate.
.pre-commit-config.yaml runs whitespace/EOL/BOM fixers, golangci-lint (config-verify, --new-from-rev HEAD --fix, and full --fix), plus local make fmt and go vet ./....
make fmt runs gofmt -w . then goimports -w ., so goimports MUST be on PATH or the commit hook fails with goimports: No such file or directory — run make install first.v2.10.1) and the Makefile (v2.11.1); expect minor lint-behavior drift.make build → build-tunnel + build-server (full artifacts).make build-frontend builds the SPA (cd frontend && npm ci && npm run build) and copies frontend/dist/. into cmd/relay-server/dist/app (embedded by the relay via //go:embed dist/*).make build-server-bin compiles only bin/relay-server; it assumes dist/app already exists (use after build-frontend, or the binary fails at startup asking you to run make build-frontend).make build-tunnel cross-compiles cmd/portal-tunnel for linux/darwin/windows × amd64/arm64.GO_BUILD_FLAGS (-trimpath -ldflags "-s -w"); the Dockerfile calls make build-server-bin rather than duplicating them.types/ (e.g. types/paths.go), never duplicated in runtime/helpers.utils/; stateful/domain logic stays with its real owner (sdk/ or portal/).Take gosuda/dev-workflow from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference go.
Without those the skill loads but fails at the first command.