Contributing

This is the canonical contributor and development guide for PinchTab.

System Requirements

Minimum Requirements

RequirementVersionPurpose
Go1.25+Build language
golangci-lintLatestLinting (required for pre-commit hooks)
Chrome/ChromiumLatestBrowser automation
macOS, Linux, or WSL2CurrentOS support

For dashboard work, use Bun 1.2+. Older Bun releases fail on the checked-in dashboard/bun.lock during clean installs with --frozen-lockfile.

  • macOS: Homebrew for package management
  • Linux: apt (Debian/Ubuntu) or yum (RHEL/CentOS)
  • WSL2: Full Linux environment (not WSL1)

Quick Start

Fastest way to get started:

terminal
# 1. Clonegit clone https://github.com/pinchtab/pinchtab.gitcd pinchtab# 2. Run doctor (verifies environment, prompts before installing anything)./dev doctor# 3. Build and rungo build ./cmd/pinchtab./pinchtab
# 1. Clonegit clone https://github.com/pinchtab/pinchtab.gitcd pinchtab# 2. Run doctor (verifies environment, prompts before installing anything)./dev doctor# 3. Build and rungo build ./cmd/pinchtab./pinchtab

Example output:

  🦀 Pinchtab Doctor
  Verifying and setting up development environment...

Go Backend
  ✓ Go 1.26.0
  ✗ golangci-lint
    Required for pre-commit hooks and CI.
    Install golangci-lint via brew? [y/N] y
    ✓ golangci-lint installed
  ✓ Git hooks
  ✓ Go dependencies

Dashboard (React/TypeScript)
  ✓ Node.js 22.15.1
  · Bun not found
    Optional — used for fast dashboard builds.
    Install Bun? [y/N] n
    curl -fsSL https://bun.sh/install | bash

Summary

  · 1 warning(s)

The doctor asks for confirmation before installing anything. If you decline, it shows the manual install command instead.


Part 1: Prerequisites

Install Go

macOS (Homebrew):

terminal
brew install gogo version  # Verify: go version go1.25.0
brew install gogo version  # Verify: go version go1.25.0

Linux (Ubuntu/Debian):

terminal
sudo apt updatesudo apt install -y golang-go git build-essentialgo version
sudo apt updatesudo apt install -y golang-go git build-essentialgo version

Linux (RHEL/CentOS):

terminal
sudo yum install -y golang gitgo version
sudo yum install -y golang gitgo version

Or download from: https://go.dev/dl/

Install golangci-lint (Required)

Required for pre-commit hooks:

macOS/Linux:

terminal
brew install golangci-lint
brew install golangci-lint

Or via Go:

terminal
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

Verify:

terminal
golangci-lint --version
golangci-lint --version

Recommended for the cleaner local unit test output used by ./dev test unit:

terminal
go install gotest.tools/gotestsum@latest
go install gotest.tools/gotestsum@latest

Install Chrome/Chromium

macOS (Homebrew):

terminal
brew install chromium
brew install chromium

Linux (Ubuntu/Debian):

terminal
sudo apt install -y chromium-browser
sudo apt install -y chromium-browser

Linux (RHEL/CentOS):

terminal
sudo yum install -y chromium
sudo yum install -y chromium

Automated Setup

After cloning, run doctor to verify and set up your environment:

terminal
git clone https://github.com/pinchtab/pinchtab.gitcd pinchtab./dev doctor
git clone https://github.com/pinchtab/pinchtab.gitcd pinchtab./dev doctor

Doctor checks your environment and asks before installing anything:

  • Go 1.25+ and golangci-lint (offers brew install or go install)
  • Git hooks (copies pre-commit hook)
  • Go dependencies (go mod download)
  • Node.js, Bun, and dashboard deps (optional, for dashboard development)

Run ./dev doctor anytime to verify or fix your environment.


Part 2: Build the Project

Simple Build

terminal
go build -o pinchtab ./cmd/pinchtab
go build -o pinchtab ./cmd/pinchtab

What it does:

  • Compiles Go source code
  • Produces binary: ./pinchtab
  • Takes ~30-60 seconds

Note: This builds the Go server only. The dashboard will show a “not built” placeholder. To include the full React dashboard, use ./dev build instead — it builds the dashboard, compiles Go, and runs the server in one step. Or run ./scripts/build-dashboard.sh before go build.

Verify:

terminal
ls -la pinchtab./pinchtab --version
ls -la pinchtab./pinchtab --version

Part 3: Run the Server

Start (Headless)

terminal
./pinchtab
./pinchtab

Expected output:

🦀 PINCH! PINCH! port=9867
auth disabled (set PINCHTAB_TOKEN to enable)

Start (Headed Mode)

terminal
BRIDGE_HEADLESS=false ./pinchtab
BRIDGE_HEADLESS=false ./pinchtab

Opens Chrome in the foreground.

Background

terminal
nohup ./pinchtab > pinchtab.log 2>&1 &tail -f pinchtab.log  # Watch logs
nohup ./pinchtab > pinchtab.log 2>&1 &tail -f pinchtab.log  # Watch logs

Part 4: Quick Test

Health Check

terminal
curl http://localhost:9867/health
curl http://localhost:9867/health

Try CLI

terminal
./pinchtab quick https://pinchtab.com./pinchtab nav https://pinchtab.com./pinchtab snap
./pinchtab quick https://pinchtab.com./pinchtab nav https://pinchtab.com./pinchtab snap

Development

Run Tests

terminal
go test ./...                              # Unit tests onlygo test ./... -v                           # Verbosego test ./... -v -coverprofile=coverage.outgo tool cover -html=coverage.out           # View coverage./dev e2e                                 # Run the default E2E release suite./dev e2e docker                          # Build the local image and run Docker smoke./dev e2e pr                              # Run API + CLI + Infra basic tests./dev e2e api                             # Run API basic tests./dev e2e cli                             # Run CLI basic tests./dev e2e infra                           # Run Infra basic tests./dev e2e api-extended                    # Run API extended (multi-instance)./dev e2e cli-extended                    # Run CLI extended tests./dev e2e infra-extended                  # Run Infra extended (multi-instance)
go test ./...                              # Unit tests onlygo test ./... -v                           # Verbosego test ./... -v -coverprofile=coverage.outgo tool cover -html=coverage.out           # View coverage./dev e2e                                 # Run the default E2E release suite./dev e2e docker                          # Build the local image and run Docker smoke./dev e2e pr                              # Run API + CLI + Infra basic tests./dev e2e api                             # Run API basic tests./dev e2e cli                             # Run CLI basic tests./dev e2e infra                           # Run Infra basic tests./dev e2e api-extended                    # Run API extended (multi-instance)./dev e2e cli-extended                    # Run CLI extended tests./dev e2e infra-extended                  # Run Infra extended (multi-instance)

Developer Toolkit (dev)

All dev scripts are accessible through ./dev:

terminal
./dev              # Interactive picker (uses gum if installed, numbered fallback)./dev check        # Run a command directly./dev test unit    # Subcommands supported./dev --help       # List all commands
./dev              # Interactive picker (uses gum if installed, numbered fallback)./dev check        # Run a command directly./dev test unit    # Subcommands supported./dev --help       # List all commands

dev interactive menu

Available commands:

CommandDescription
checkAll checks (Go + Dashboard)
check goGo checks only
check dashboardDashboard checks only
check securityGosec security scan
check docsValidate docs JSON
format dashboardRun Prettier on dashboard sources
testRun all tests
test unitUnit tests only
test dashboardDashboard tests only
e2eRun the default E2E release suite (all extended tests)
e2e dockerBuild the local image and run the Docker smoke test
e2e prRun the PR E2E suite (api + cli + infra basic tests)
e2e apiRun API basic tests
e2e cliRun CLI basic tests
e2e infraRun Infra basic tests
e2e api-extendedRun API extended tests (multi-instance)
e2e cli-extendedRun CLI extended tests
e2e infra-extendedRun Infra extended tests (multi-instance)
e2e releaseRun the release E2E meta-suite (all extended)
buildBuild the application
devBuild and run the application
runRun the application
binaryBuild the local release-style binary
doctorSetup dev environment

For the fancy interactive picker, install gum: brew install gum

Tip: Add this to ~/.zshrc to use dev without ./:

terminal
dev() { if [ -x "./dev" ]; then ./dev "$@"; else echo "dev not found in current directory"; return 1; fi }
dev() { if [ -x "./dev" ]; then ./dev "$@"; else echo "dev not found in current directory"; return 1; fi }

Code Quality

terminal
./dev check              # Full non-test checks (recommended)./dev format dashboard   # Fix dashboard formattinggofmt -w .                # Format codegolangci-lint run         # Lint./dev doctor             # Verify environment
./dev check              # Full non-test checks (recommended)./dev format dashboard   # Fix dashboard formattinggofmt -w .                # Format codegolangci-lint run         # Lint./dev doctor             # Verify environment

Git Hooks

Git hooks are installed by ./dev doctor (or ./scripts/install-hooks.sh). They run on every commit:

  • gofmt — Format check
  • golangci-lint — Linting
  • prettier — Dashboard formatting

To manually reinstall hooks:

terminal
./scripts/install-hooks.sh
./scripts/install-hooks.sh

Development Workflow

terminal
# 1. Setup (first time)./dev doctor# 2. Create feature branchgit checkout -b feat/my-feature# 3. Make changes# ... edit files ...# 4. Run checks before pushing./dev check# 5. Commit (hooks run automatically)git commit -m "feat: description"# 6. Pushgit push origin feat/my-feature
# 1. Setup (first time)./dev doctor# 2. Create feature branchgit checkout -b feat/my-feature# 3. Make changes# ... edit files ...# 4. Run checks before pushing./dev check# 5. Commit (hooks run automatically)git commit -m "feat: description"# 6. Pushgit push origin feat/my-feature

Note: Git hooks will automatically format and lint your code on commit. If checks fail, the commit is blocked.


Continuous Integration

Workflows follow a naming convention:

PrefixPurposeExample
ci-*Automatic checks on PR/pushci-go.ymlCI / Go
reusable-*Building blocks (workflow_call only)reusable-e2e.ymlReusable / E2E
release-*Release pipelinerelease.ymlRelease

CI Checks

Run automatically on pull requests and/or push to main:

WorkflowTriggersWhat it checks
CI / GoPR + pushgofmt, vet, build, tests, coverage, lint, security
CI / DashboardPR + push (dashboard paths)TypeScript, ESLint, Prettier, tests, build
CI / DocsPR + push (docs paths)docs.json reference validation
CI / npmPR (npm paths) + tag pushnpm package verification
CI / E2EPR (fast suites) + manual (full suites)Docker-based end-to-end tests
CI / Branch NamingPRBranch name convention enforcement

Release Pipeline

WorkflowTriggerWhat it does
ReleaseManualRuns all checks + E2E → manual approval gate → creates tag → publishes binaries, npm, Docker, and skill
Release / Manual PublishManualPublishes an existing tag as a recovery path

In Release, E2E and Docker smoke failures are non-blocking — they surface in the approval summary so you can decide whether to proceed. Core checks (Go, Dashboard, Docs, npm, publish dry-run) must pass for the approval gate to appear.


Installation as CLI

From Source

terminal
go build -o ~/go/bin/pinchtab ./cmd/pinchtab
go build -o ~/go/bin/pinchtab ./cmd/pinchtab

Then use anywhere:

terminal
pinchtab helppinchtab --version
pinchtab helppinchtab --version

Via npm (released builds)

terminal
npm install -g pinchtabpinchtab --version
npm install -g pinchtabpinchtab --version

Resources


Troubleshooting

Environment Issues

First step: Run doctor to verify your setup:

terminal
./dev doctor
./dev doctor

This will tell you exactly what’s missing or misconfigured.

Common Issues

“Go version too old”

“golangci-lint: command not found”

  • Install: brew install golangci-lint
  • Or: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

“Git hooks not running on commit”

  • Run: ./scripts/install-hooks.sh
  • Or: ./dev doctor (prompts to install)

“Chrome not found”

  • Install Chromium: brew install chromium (macOS)
  • Or: sudo apt install chromium-browser (Linux)

“Port 9867 already in use”

  • Check: lsof -i :9867
  • Stop other instance or use different port: BRIDGE_PORT=9868 ./pinchtab

Build fails

  1. Verify dependencies: go mod download
  2. Clean cache: go clean -cache
  3. Rebuild: go build ./cmd/pinchtab

Support

Issues? Check:

  1. Run ./dev doctor first
  2. All dependencies installed and correct versions?
  3. Port 9867 available?
  4. Check logs: tail -f pinchtab.log

See docs/ for guides and examples.