Contributing¶
Thank you for your interest in contributing to Clincus. This guide covers the development setup, testing, code style, and pull request process.
Development Setup¶
Prerequisites¶
- Go 1.24+ —
go version - Node.js 20+ —
node --version - npm —
npm --version - Incus — see Prerequisites
- golangci-lint —
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest - pre-commit —
pip install pre-commitorbrew install pre-commit - MkDocs MaterialX —
pip install mkdocs-materialx(for local docs preview)
Clone and Build¶
git clone https://github.com/bketelsen/clincus.git
cd clincus
# Install pre-commit hooks
pre-commit install
# Build everything (Go binary + Svelte frontend)
make build
# Install to $GOPATH/bin
make install
Frontend Development¶
The Svelte app lives in web/. For hot-reloading during UI development:
The dev server proxies API requests to http://127.0.0.1:3000 (assumes clincus serve is
running).
To build the frontend for embedding:
Running Tests¶
Unit Tests¶
go test ./...
# With race detector (recommended before submitting a PR)
go test -race ./...
# Verbose output
go test -race -v ./...
Integration Tests¶
Integration tests require a running Incus instance and are skipped automatically when Incus
is not available. They are marked with //go:build integration or detected via
container.Available().
Python Tests (CLI integration)¶
The tests/ directory contains pytest-based integration tests that exercise the clincus
binary end-to-end.
These tests use a dummy stub tool (instead of the real Claude Code) to run quickly without
requiring an API key. Set CLINCUS_USE_DUMMY=1 to use the dummy in any test run.
Code Style¶
Go¶
- Format with
gofmt:make fmt - Lint with golangci-lint:
make lint - Follow standard Go idioms and the project's existing patterns
- All exported symbols must have doc comments
- Avoid
//nolintunless the lint rule is genuinely wrong; add a comment explaining why
TypeScript / Svelte¶
- The frontend uses the default ESLint and Prettier configuration from the Svelte template
- Run
npm run lintandnpm run formatfrom theweb/directory
Commit Messages¶
Follow the Conventional Commits format:
feat: add --timeout flag to clincus run
fix: correctly handle SIGTERM during session cleanup
docs: document resource limit config options
refactor: extract session naming into session.Naming type
test: add integration test for persistent session resume
chore: bump golangci-lint to v1.62
Adding a New Tool¶
- Create
internal/tool/<toolname>.goimplementing thetool.Toolinterface:
type MyTool struct{}
func (t *MyTool) Name() string { return "mytool" }
func (t *MyTool) ConfigDirName() string { return ".mytool" }
func (t *MyTool) BuildCommand(sessionID string, resume bool, cliSessionID string) []string {
cmd := []string{"mytool"}
if resume && cliSessionID != "" {
cmd = append(cmd, "--session", cliSessionID)
}
return cmd
}
func (t *MyTool) DiscoverSessionID(statePath string) string {
// read session ID from state files
return ""
}
- Register it in
internal/tool/registry.go:
-
Add tests in
internal/tool/<toolname>_test.go. -
Document the tool in docs/guides/tools.md.
Pull Request Process¶
-
Open an issue first for significant changes. For small bug fixes or doc improvements, a PR without a prior issue is fine.
-
Fork and branch:
-
Make your changes — keep commits focused and atomic.
-
Run the full check suite before pushing:
-
Push and open a PR against
mainongithub.com/bketelsen/clincus. -
PR description should:
- Summarize what the change does and why
- Reference any related issues (
Closes #123) -
List any manual testing you did
-
A maintainer will review. Address review comments and push new commits to the same branch (do not force-push after a review has started).
-
Once approved, the PR is squash-merged.
Release Process¶
Releases are automated via GoReleaser and GitHub Actions. To cut a new release:
make bump runs svu next to determine the next semantic version, creates an annotated
git tag, and pushes it. The GitHub Actions release workflow picks up the tag and runs
GoReleaser to build binaries, create .deb/.rpm/.apk packages, and publish a GitHub
Release.
Project Governance¶
Clincus is a community-maintained project. For questions, open a GitHub Discussion. For bugs, open a GitHub Issue.