Skip to main content

Development Setup

This guide covers setting up a local development environment for contributing to Station.

Prerequisites

RequirementVersionPurpose
Go1.21+Core language
DockerLatestJaeger, sandbox, integration tests
MakeAnyBuild automation
GitAnyVersion control

Optional

RequirementPurpose
Node.js 18+Building documentation
SQLite CLIDatabase debugging
JaegerDistributed tracing

Clone and Build

# Clone the repository
git clone https://github.com/cloudshipai/station.git
cd station

# Build the binary
make build

# Or build and install to $GOPATH/bin
make install

# Verify installation
stn version

Project Structure

station/
├── cmd/main/              # CLI entry point
│   ├── main.go            # Application bootstrap
│   └── handlers/          # CLI command handlers
│       ├── agent/         # Agent commands
│       ├── env/           # Environment commands
│       ├── bundle/        # Bundle commands
│       └── ...
├── internal/
│   ├── api/v1/            # REST API handlers
│   ├── config/            # Configuration loading
│   ├── db/                # Database layer
│   │   ├── repositories/  # Data access layer
│   │   └── schema.sql     # SQLite schema
│   ├── mcp/               # MCP server implementation
│   ├── services/          # Business logic (43+ modules)
│   └── workflows/         # Workflow engine
├── pkg/                   # Public packages (reusable)
├── bundles/               # Example agent bundles
├── docs/                  # Internal documentation
│   └── architecture/      # Architecture diagrams
└── Makefile               # Build automation

Running Locally

Start the Server

# Start with default configuration
stn serve

# Start with custom configuration
stn serve --config path/to/config.yaml

# Start with API + MCP server
stn serve --api-port 8585 --mcp-port 8586

Create a Test Environment

# Create a new environment
stn env create dev

# Sync environment (loads agents and MCP servers)
stn sync dev

# List environments
stn env list

Run an Agent

# Run an agent with a task
stn agent run my-agent "Hello, what can you do?"

# Run with variables
stn agent run my-agent "Analyze this" --var file=./data.json

# Run with streaming output
stn agent run my-agent "Process data" --stream

Configuration

Default Paths

PlatformConfig Directory
Linux/macOS~/.config/station/
Windows%APPDATA%\station\

Configuration File

Create config.yaml:
# AI Provider Configuration
ai_provider: openai
ai_model: gpt-5-mini

# API Server
api_port: 8585
mcp_port: 8586

# Database
database_url: ~/.config/station/station.db

# Workspace (for environments)
workspace: ~/.config/station/environments

# Telemetry (optional)
telemetry:
  enabled: true
  jaeger_endpoint: http://localhost:4317

Environment Variables

VariableDescriptionDefault
OPENAI_API_KEYOpenAI API key-
GOOGLE_API_KEYGoogle AI API key-
STN_AI_PROVIDERAI provider overrideopenai
STN_AI_MODELAI model overridegpt-5-mini
STN_DATABASE_URLDatabase path~/.config/station/station.db
STN_WORKSPACEEnvironments path~/.config/station/environments
STN_API_PORTAPI server port8585
STN_MCP_PORTMCP server port8586

Starting Infrastructure

Jaeger (Distributed Tracing)

# Start Jaeger with Docker
docker run -d --name jaeger \
  -p 16686:16686 \
  -p 4317:4317 \
  -p 4318:4318 \
  jaegertracing/jaeger:latest

# View traces at http://localhost:16686

libsql (Optional Cloud Database)

For cloud database development:
# Install libsql CLI
curl -fsSL https://github.com/libsql/libsql/releases/download/latest/libsql-linux-x64.tar.gz | tar xz

# Start local libsql server
libsql server --db-path ./station.db

IDE Setup

VS Code

Recommended extensions:
{
  "recommendations": [
    "golang.go",
    "ms-azuretools.vscode-docker",
    "mtxr.sqltools",
    "humao.rest-client"
  ]
}
Settings for Go:
{
  "go.useLanguageServer": true,
  "go.lintTool": "golangci-lint",
  "go.lintOnSave": "package",
  "go.formatTool": "goimports",
  "editor.formatOnSave": true
}

GoLand / IntelliJ

  1. Open the station/ directory as a Go project
  2. Enable “Go Modules integration”
  3. Configure GOROOT to Go 1.21+

Makefile Targets

# Build the binary
make build

# Run tests
make test

# Run tests with coverage
make test-coverage

# Run linter
make lint

# Format code
make fmt

# Clean build artifacts
make clean

# Build and install
make install

# Generate mocks (for testing)
make mocks

# Run all checks (lint + test)
make check

Common Development Tasks

Adding a New CLI Command

  1. Create handler in cmd/main/handlers/<domain>/
  2. Register command in cmd/main/main.go
  3. Add tests in cmd/main/handlers/<domain>/*_test.go

Adding a New Service

  1. Create service in internal/services/<name>.go
  2. Define interface if needed
  3. Add to service registry if applicable
  4. Write tests in internal/services/<name>_test.go

Adding a New API Endpoint

  1. Add handler in internal/api/v1/<resource>.go
  2. Register route in internal/api/v1/routes.go
  3. Add tests in internal/api/v1/<resource>_test.go

Adding a New MCP Tool

  1. Add handler in internal/mcp/handlers/
  2. Register in internal/mcp/server.go
  3. Update tool discovery if needed

Debugging

Enable Debug Logging

# Via environment variable
export STN_LOG_LEVEL=debug
stn serve

# Via flag
stn serve --log-level debug

Database Inspection

# Open SQLite shell
sqlite3 ~/.config/station/station.db

# Common queries
.tables                           # List tables
.schema agents                    # Show agent schema
SELECT * FROM agents LIMIT 10;   # View agents
SELECT * FROM agent_runs ORDER BY created_at DESC LIMIT 5;  # Recent runs

Tracing with Jaeger

  1. Start Jaeger (see above)
  2. Configure telemetry in config.yaml
  3. Run agents and view traces at http://localhost:16686

Station Lattice Development

Station Lattice enables multi-station mesh networking. This section covers development-specific workflows.

Running Lattice Locally

# Terminal 1: Start orchestrator station
stn serve --orchestration --workspace ./orchestrator

# Terminal 2: Start member station (connects to orchestrator)
stn serve --lattice nats://localhost:4222 --workspace ./member

# Verify connection
stn lattice stations list
stn lattice agents list

Key Lattice Directories

DirectoryPurpose
internal/lattice/Core lattice implementation
internal/lattice/work/JetStream work tracking
cmd/main/lattice_commands.goCLI commands
bundles/demo/Demo bundles for testing

NATS Subject Conventions

Subject PatternPurpose
lattice.station.{id}.heartbeatStation presence heartbeats
lattice.agent.invoke.{agent}Request-reply agent invocation
lattice.work.assign.{station}Async work assignment
lattice.work.result.{work_id}Work completion results

Adding New Message Types

  1. Define the message struct in internal/lattice/messages.go:
type MyNewMessage struct {
    Type      string    `json:"type"`
    StationID string    `json:"station_id"`
    Payload   string    `json:"payload"`
    Timestamp time.Time `json:"timestamp"`
}
  1. Add publisher function in appropriate file:
func (c *Client) PublishMyNewMessage(msg *MyNewMessage) error {
    data, err := json.Marshal(msg)
    if err != nil {
        return fmt.Errorf("marshal message: %w", err)
    }
    return c.nc.Publish("lattice.my.subject", data)
}

Testing Lattice Code

# Run all lattice tests
go test ./internal/lattice/... -v

# Run E2E lattice tests (requires clean environment)
go test ./internal/lattice/e2e/... -v -timeout 5m

# Test with race detection
go test ./internal/lattice/... -race -v

Common Gotchas

  1. Always close NATS connections - Use defer client.Close() to prevent resource leaks
  2. JetStream KV eventual consistency - Allow small delays when testing KV operations
  3. Port conflicts - Use unique ports in tests to avoid conflicts with running stations
  4. Heartbeat timing - Default heartbeat is 5s; tests may need shorter intervals

Next Steps