Development Guide¶
Library Orientation
This guide covers how to contribute to GTB itself, set up a development environment, run tests, and understand the internal architecture. If you are developing an application using GTB, some sections may differ.
Development Setup¶
Prerequisites¶
- Go 1.26 or later
- Git configured for private repositories
- golangci-lint for code quality checks
- mockery for generating mocks (if modifying interfaces)
- just (for running build scripts)
Clone and Setup¶
git clone https://github.com/phpboyscout/gtb.git
cd gtb
# Install dependencies
go mod download
# Verify setup
just build
# Or manually:
go build ./...
go test ./...
Environment Configuration¶
Set up your environment for private module development:
# Configure Git authentication
git config --global --replace-all url."https://${GITHUB_USERNAME}:${GITHUB_TOKEN}@github.com".insteadOf "https://github.com"
# Set Go private modules
go env -w GOPRIVATE=github.com
Project Structure¶
Understanding the codebase organization:
gtb/
โโโ .github/ # CI/CD workflows and GitHub templates
โโโ .gtb/ # Configuration and manifest for the project
โโโ cmd/ # Built-in shareable command implementations (docs, init, root, update, version)
โโโ docs/ # Project documentation
โโโ internal/ # Internal components used exclusively by the CLI and not intended for public consumption
โ โโโ agent/ # AI Agent components used by the CLI
โ โโโ cmd/ # Cobra command logic use by the CLI
โ โโโ generator/ # Template generation logic use by the CLI to create CLI projects
โโโ pkg/ # Public library packages
โ โโโ chat/ # AI provider integrations (OpenAI, Gemini, Claude)
โ โโโ config/ # Configuration management (Viper wrapper)
โ โโโ controls/ # Service lifecycle management
โ โโโ docs/ # TUI documentation browser and AI Q&A
โ โโโ errorhandling/ # Custom error types and reporting
โ โโโ props/ # Application-wide properties and dependency container
โ โโโ setup/ # Initialization and project setup
โ โโโ utils/ # Common utility functions
โ โโโ vcs/ # Version control (Git) utilities
โโโ main.go # CLI entry point
โโโ justfile # Build and automation tasks
Development Workflow¶
Significant Feature Lifecycle¶
Non-trivial features follow a spec-first, branch-per-feature workflow. The spec and the implementation share a single branch and PR, ensuring the design is reviewed and approved before code is written.
1. Create a Feature Branch¶
2. Draft a Specification¶
Using an AI assistant (Cursor Agent, Claude, etc.), draft a feature spec following the Feature Specifications guide. The spec captures requirements, public API design, internal implementation, testing strategy, and implementation phases.
Save it to docs/development/specs/YYYY-MM-DD-<feature-name>.md with status DRAFT.
3. Push and Raise a PR¶
Push your branch and open a PR containing only the spec. This is the review gate -- no implementation code yet.
Mark the PR as a spec review (e.g. prefix the title with [SPEC]) so reviewers know what to expect.
4. Request SME Review¶
Request review from a Subject Matter Expert (SME). The reviewer should:
- Read the spec and assess feasibility, design decisions, and scope.
- If approved: update the spec's
statustoAPPROVED(in both frontmatter and the document header) and push the change. - If changes are needed: use GitHub's PR commenting facility to communicate required changes. The spec author iterates until the reviewer is satisfied.
- If rejected: update the spec's
statustoREJECTED, add a## Rejection Rationalesection (see Handling Rejections), and merge the PR to preserve the historical record.
Warning
Do not begin implementation until the spec status is APPROVED.
5. Implement the Feature¶
Once approved, develop the feature in the same branch. Use the spec as the primary reference -- it defines the implementation phases, public API, and acceptance criteria. AI agents can read the spec directly from the repository for full context.
Update the spec status to IN PROGRESS when development begins.
6. Code Review, Approval, and Merge¶
Once implementation is complete:
- Update the spec status to
IMPLEMENTED. - Ensure all CI checks pass and the Verification Checklists are satisfied.
- Request code review following standard project conventions.
- Merge the PR once approved.
Tip
Keep the spec and implementation in the same PR. This ensures the design rationale is always co-located with the code it describes in the git history.
Quick Fixes and Minor Changes¶
Not every change needs a spec. For bug fixes, small enhancements, and refactors that don't alter the public API or architecture, follow the standard branch-and-PR workflow without a spec.
Testing¶
The project uses comprehensive testing with mocks:
# Run all tests
go test ./...
# Run tests with coverage
go test -cover ./...
# Run specific package tests
go test ./config -v
# Run tests with race detection
go test -race ./...
3. Mock Generation¶
If you modify interfaces, regenerate mocks:
# Install mockery if not already installed
go install github.com/vektra/mockery/v2@latest
# generate all mocks for the project
mockery
4. Code Quality¶
The project enforces code quality standards:
# Run linter
golangci-lint run
# Apply Go fixes
go fix ./...
# Auto-fix issues where possible
golangci-lint run --fix
# Format code
go fmt ./...
# Check for common issues
go vet ./...
Testing Philosophy¶
Unit Testing¶
- High Coverage: Aim for >90% test coverage
- Mocked Dependencies: Use generated mocks for external dependencies
- Table-Driven Tests: Use table-driven patterns for multiple scenarios
- Parallel Execution: Tests should run in parallel where possible
Example test structure:
func TestLoadEmbed(t *testing.T) {
t.Parallel()
tests := []struct {
name string
paths []string
setup func(*configMocks.MockEmbeddedFileReader)
expectError bool
expectedFiles int
}{
{
name: "successful single file",
paths: []string{"config.yaml"},
setup: func(m *configMocks.MockEmbeddedFileReader) {
m.EXPECT().ReadFile("config.yaml").Return([]byte("test"), nil)
},
expectError: false,
expectedFiles: 1,
},
// ... more test cases
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
// Test implementation
})
}
}
Integration Testing¶
- Test command execution end-to-end
- Verify configuration loading and merging
- Test error handling paths
Architecture Principles¶
For a visual overview of component relationships and core workflows, see the Architectural Overview.
1. Dependency Injection¶
All components receive their dependencies via constructor functions:
func NewCmdRoot(ver string, commit string, date string) *cobra.Command {
// Dependencies are injected, and root initialization handles built-in commands
}
2. Interface Segregation¶
Small, focused interfaces for better testability:
3. Error Wrapping¶
Consistent error handling with context:
4. Configuration Abstraction¶
Flexible configuration system supporting multiple sources:
- File-based configuration
- Embedded configuration
- Environment variables
- Command-line flags
Adding New Components¶
1. Creating a New Package¶
When adding a new package:
interface.go:
package newpackage
// Define interfaces first
type NewService interface {
DoSomething(ctx context.Context, input string) error
}
implementation.go:
package newpackage
import "context"
type service struct {
logger *log.Logger
config Configurable
}
func NewService(logger *log.Logger, config Configurable) NewService {
return &service{
logger: logger,
config: config,
}
}
func (s *service) DoSomething(ctx context.Context, input string) error {
s.logger.Debug("doing something", "input", input)
// Implementation
return nil
}
2. Adding Tests¶
implementation_test.go:
package newpackage_test
import (
"context"
"testing"
"github.com/phpboyscout/gtb/newpackage"
"github.com/phpboyscout/gtb/mocks/pkg/config"
"github.com/charmbracelet/log"
"github.com/stretchr/testify/assert"
)
func TestService_DoSomething(t *testing.T) {
t.Parallel()
logger := log.New(io.Discard)
mockConfig := configMocks.NewMockConfigurable(t)
service := newpackage.NewService(logger, mockConfig)
err := service.DoSomething(context.Background(), "test")
assert.NoError(t, err)
}
3. Generate Mocks¶
Add mockery directive to interface:
Debugging Tips¶
1. Verbose Logging¶
Enable debug logging during development:
2. Test Debugging¶
Run specific tests with verbose output:
3. Race Condition Detection¶
Run tests with race detection:
Contributing Guidelines¶
Pull Requests¶
For significant features, follow the full Significant Feature Lifecycle above. For all PRs:
- Create a feature branch from
main. - Add comprehensive tests.
- Update documentation.
- Ensure all CI checks pass.
- Submit PR with a clear description of the impact, linking to the spec if applicable.
Code Review Checklist¶
- Feature spec exists and is
APPROVED(for non-trivial features) - Spec status updated to reflect current state (
IN PROGRESS/IMPLEMENTED) - Tests added/updated
- Documentation updated
- Code follows project conventions
- No breaking changes (or properly documented)
- Error handling follows project patterns
- Interfaces are properly mocked
Release Process¶
Releases are automated via CI/CD, but follow semantic versioning:
- Major: Breaking changes
- Minor: New features, backward compatible
- Patch: Bug fixes, backward compatible
Common Development Tasks¶
Adding a New Built-in Command¶
- Create package in
cmd/ - Implement command following existing patterns
- Add to root command registration in
pkg/cmd/root/root.go: - Add comprehensive tests
- Update documentation
Modifying Configuration System¶
- Update interfaces in
config/ - Regenerate mocks
- Update tests
- Verify backward compatibility
- Update examples
Detailed Development Guides¶
For specialized information on library-level development and architectural standards, see:
- Feature Specifications: Spec-first workflow for designing new features.
- IDE & Tooling Setup: Standard configuration for library contributors.
- AI Integration Layer: Deep dive into the
chatpackage and provider abstraction. - Error Handling: Patterns for library errors and wrapping.
- Environment Variables & .env: Local configuration and secret management.
- Dependency Management: Versioning policy and internal modules.
- Verification Checklists: Library and generator verification protocols.
- Glossary: Common terms used in the project.
- Security: Policies on secret management and vulnerability reporting.
- AI Collaboration: How to leverage project skills and workflows.
This development guide should help you contribute effectively to GTB!