Contributing Guide
Relevant source files
The following files were used as context for generating this wiki page:This guide provides instructions for setting up your development environment, understanding the codebase, and contributing to the Tusk Drift CLI. For any questions, you can open an issue or contact support@usetusk.ai.
Sources: CONTRIBUTING.md:3-4
Getting Started
To begin contributing, you'll need to set up your local environment and build the project.
Requirements
- Go 1.25+
- (Optional) Nix: Use
nix developto enter a pre-configured development shell.
Sources: CONTRIBUTING.md:8-10
Initial Setup
- Clone the repository:
git clone https://github.com/Use-Tusk/tusk-drift-cli.git cd tusk-drift-cli - Configure Go for private modules:
go env -w GOPRIVATE="github.com/Use-Tusk/*" - Install dependencies:
make deps - Build the binary:
make build - Run the CLI:
go run . --help
Sources: CONTRIBUTING.md:11-16, README.md:100-105
Development Workflow
The project uses a Makefile to streamline common development tasks.
Common Make Targets
| Command | Description |
|---|---|
make build | Build the binary to ./tusk. |
make run | Build and run the application. |
make test | Run tests for the module root. |
make test-ci | Run tests for all packages, as done in CI. |
make deps | Download and tidy Go modules. |
make fmt | Format the code using go fmt .. |
make lint | Run the golangci-lint linter. |
make build-ci | Build the binary with embedded version information. |
Sources: CONTRIBUTING.md:20-28
Logging
- Debug Logs: Use
slog.Debugfor detailed debugging information. - Headless Mode Logs: Use
fmt.Printlnfor runtime logs when the TUI is not active. - TUI Logs: Use
logging.LogToServiceorlogging.LogToCurrentTestto display logs within the interactive TUI.
Sources: CONTRIBUTING.md:29-33
Code Structure
The repository is organized into several key directories.
This diagram shows the high-level directory structure of the project.
Style and Conventions
- Keep pull requests focused on a single purpose and covered by tests.
- Ensure PRs are small and have a clear rationale.
- Update documentation in
docs/architecture.mdordocs/configuration.mdwhen adding flags or configuration options. - Use meaningful fields for
slogmessages and avoid logging sensitive data.
Sources: CONTRIBUTING.md:58-62
Feature Development
Contributions often involve adding functionality to the AI Agent or the Onboarding Wizard.
AI Agent (tusk exp init)
The AI agent orchestrates an AI-powered setup flow using Claude. It guides users through installation, configuration, and testing.
The agent's architecture follows a phase-based execution model, where each phase has specific instructions and available tools.
Sources: internal/agent/README.md:5-24
To add a new phase to the agent:
- Create a prompt file: Add a
prompts/phase_<name>.mdfile with instructions for the AI. - Embed the prompt: Add an
//go:embeddirective ininternal/agent/prompts.go. - Define the phase: Create a phase function in
internal/agent/phases.gothat defines its ID, name, tools, and other properties. - Register the phase: Add the new phase to the
defaultPhases()list ininternal/agent/phases.go. - Update State: If the phase produces results, add fields to the
Statestruct ininternal/agent/types.goand handle them inUpdateState()ininternal/agent/phases.go.
Sources: internal/agent/README.md:37-88
Onboarding Wizard (tusk init)
The tusk init command uses a TUI wizard built with Bubble Tea to guide users through creating the .tusk/config.yaml file.
The wizard is composed of a series of "steps," each implementing the Step interface.
Sources: internal/tui/onboard/README.md:3-16
Each step in the wizard must implement the Step interface:
type Step interface {
ID() onboardStep
InputIndex() int
Question(*Model) string
Description(*Model) string
Default(*Model) string
Validate(*Model, string) error
Apply(*Model, string)
Help(*Model) string
ShouldSkip(*Model) bool
Clear(*Model)
}
Sources: internal/tui/onboard/README.md:18-31
To add a new step:
- Define the step constant in the
onboardStepenum ininternal/tui/onboard/model.go. - Create the step type and implement the
Stepinterface ininternal/tui/onboard/steps.go. - Add state to the model in
internal/tui/onboard/model.goto store the step's data. - Register the step in the
stepsList()function ininternal/tui/onboard/steps.go. - Use the value by updating
getCurrentConfig()ininternal/tui/onboard/config.goif it needs to be saved.
Sources: internal/tui/onboard/README.md:78-132
Releasing (For Maintainers)
Releases are automated using GoReleaser and triggered by pushing a new version tag to the main branch.
Creating a Release
The scripts/release.sh script is used to create and push a new version tag.
Usage:
# Patch release (v1.0.0 → v1.0.1)
./scripts/release.sh patch
# Minor release (v1.0.0 → v1.1.0)
./scripts/release.sh minor
Sources: CONTRIBUTING.md:121-127, scripts/release.sh:4
The release script follows a defined workflow to ensure releases are safe and consistent.
Sources: scripts/release.sh
Supported Platforms
The release workflow builds binaries for the following platforms:
| OS | Architectures |
|---|---|
| Linux | amd64, arm64 |
| macOS (darwin) | amd64, arm64 |
| Windows | amd64, arm64 |
Sources: CONTRIBUTING.md:139-144
Building Locally for Distribution
To mimic the CI build process and embed version information, use the following command:
VERSION=v1.2.3
BUILD_TIME=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
GIT_COMMIT=$(git rev-parse HEAD)
go build \
-ldflags "-X github.com/Use-Tusk/tusk-drift-cli/internal/version.Version=${VERSION} \
-X github.com/Use-Tusk/tusk-drift-cli/internal/version.BuildTime=${BUILD_TIME} \
-X github.com/Use-Tusk/tusk-drift-cli/internal/version.GitCommit=${GIT_COMMIT}" \
-o tusk
Sources: CONTRIBUTING.md:151-163
Security Policy
To report a security vulnerability, please email support@usetusk.ai with a detailed description of the issue. The project follows a 90-day disclosure timeline. This policy applies to the latest version on the main branch.
Sources: SECURITY.md:3-7