This file provides guidance to various AI agents when working with code in this repository.
# Build with version info (recommended)
make build
# Or install to $GOPATH/bin
make install
# Build without make
go build -o pinner ./cmd/pinner
# Cross-compile for different platforms
GOOS=linux GOARCH=amd64 go build -o pinner-linux-amd64 ./cmd/pinner
GOOS=darwin GOARCH=arm64 go build -o pinner-darwin-arm64 ./cmd/pinner
GOOS=windows GOARCH=amd64 go build -o pinner-windows-amd64.exe ./cmd/pinner# Run all tests
go test ./...
# Run with coverage
go test -cover ./...
# Run tests for a specific package
go test ./pkg/cli
# Run tests with verbose output
go test -v ./...
# Run specific test functions
go test ./pkg/cli -run TestUploadThe project uses mockery for generating mocks. See the official documentation for installation instructions.
# Generate all mocks
mockery
# Generate mocks for specific interfaces
mockery --name=PinningService
mockery --name=UploadService
mockery --name=AuthService# Run from source
go run ./cmd/pinner
# Or use built binary
./pinner <command>Pinner.xyz CLI is a Go-based command-line tool for managing IPFS content via the Pinner.xyz service. Beyond pinning, it supports website hosting, DNS management, IPNS publishing, downloading, benchmarking, and admin operations. It uses a layered architecture with clear separation of concerns between CLI presentation, business logic, and external service integration.
-
cmd/pinner/: Entry point for the CLI application. Minimal main.go that delegates topkg/cli.Run(). -
pkg/cli/: Primary CLI command implementations and orchestration logic.- Contains all command handlers:
auth.go,account.go,account_api_keys.go,register.go,confirm_email.go,upload.go,download.go,pin.go,pins.go+pins_*.go(add/ls/rm/status/update),list.go,status.go,unpin.go,unpin_all.go,metadata.go(removed command),meta.go(metadata flag helpers),operations.go,dns.go,ipns.go,websites.go,bench.go,config.go,doctor.go,setup.go,admin.go,version.go,root.go - Defines service interfaces:
PinningService,StatusService,UploadService,AuthService,DownloadService,BenchService,OperationsService,DNSService,IPNSService,WebsitesService,QuotaAdminService,BillingAdminService,WebsiteAdminService,AdminTokenProvider - Output formatting system with human-readable and JSON modes
- Global flags and command registration in
flags.goandregister.go - Shell completion support for bash, zsh, fish, and PowerShell
- Generic wizard framework in
wizard/using Go generics (Step[S any],Run[S]()) - Structured error types:
BenchError,HTTPError,FormatError
- Contains all command handlers:
-
pkg/cli/internal/: Internal implementations of service interfaces.PinningClientinterface wraps boxo's remote pinning clientBoxoPinningClientprovides the actual implementation with retry logic- HTTP client with configurable retry behavior
-
pkg/internal/: Internal shared utilities.car.go- CAR file root reading (GetCarRoots)io/stdinfs.go- Implementsfs.FSfor stdin (pipe) input
-
pkg/config/: Configuration management.- Extends
go.lumeweb.com/configmanagerfor CLI-specific config - Default config location:
~/.config/pinner/config.yaml - Config keys:
auth_token,base_endpoint,max_retries,memory_limit,secure,gateway_endpoint - Methods for managing auth tokens, endpoints, retries, and secure flags
- Extends
-
build/: Build-time information.build.go- Variables populated at build time via ldflagsbuild_info.go- BuildInfo interface and Info struct for version tracking
Service Layer Pattern: Each major feature has a service interface with default implementation:
PinningService- Pin/unpin/list/status/batch/update operations on existing CIDsStatusService- Extended status checking with operation trackingUploadService- Upload files/directories to IPFSAuthService- Authentication, registration, OTP, token managementDownloadService- Download, cat, and directory listing from IPFSBenchService- Benchmark upload and pinning performanceOperationsService- List and inspect account operationsDNSService- DNS zone and record CRUD operationsIPNSService- IPNS key management, publish, republish, resolveWebsitesService- Website CRUD, SSL status, configQuotaAdminService- Admin quota plans, allowances, user configs, statsBillingAdminService- Admin credits, price lines, pricing plans, subscribersWebsiteAdminService- Admin website block/unblockManager- Configuration management
These interfaces enable dependency injection for testing. Factory functions create service instances (defaultPinningServiceFactory, defaultUploadServiceFactory, etc.).
Output Formatting: The Output interface provides methods for formatted output:
Print,Printf,Printflnfor text outputPrintJSONfor structured dataPrintTable,PrintListfor tabular/list dataMaskSensitiveto hide tokens/passwordsWatchfor monitoring long-running operations
Two implementations: humanFormatter and jsonFormatter, selected based on global --json flag.
CAR Generation Flow:
- Upload uses IPFS boxo libraries for DAG building and CAR format handling
- CAR root reading via
GetCarRootsinpkg/internal/car.go - Memory usage limited by
--memory-limitflag (default: 100MB)
CLI Command Pattern:
- Each command has a
newXxxCommand()function returning acli.Command - Commands use
commandGetterinterface for flag access (enables testing) - Command handlers accept factory functions for dependency injection
cliCommandWrapperadaptscli.CommandtocommandGetter- The
pinscommand group (pins add/rm/ls/status/update) is the canonical interface;pin,unpin,list,statusare first-class root shortcuts - Help categories (Setup, Content, Pinning, Management, System, Admin) are set via urfave/cli
Categoryfield
Mockery Configuration:
- Mocks are generated using mockery
- Configuration in
.mockery.yamldefines which interfaces to mock - Mocks are placed alongside source files or in
mocks/subdirectories
Build Information Injection:
- Version, commit, and build time are injected at build time via ldflags
build.Defaultprovides access to build info throughout the application- Used in diagnostics (
pinner doctor) and version display
Command Structure:
pinsis the canonical command group with subcommands:add,rm,ls,status,update- Root shortcuts (
pin,unpin,list,status) delegate to pins subcommands — first-class, no deprecation metadatacommand removed;pins updatereplaces it (hidden error command with suggestion)- Upload and pins add wait by default for pinning to complete;
--no-waitto detach --meta key=valueflag on pins add and upload for metadata at pin creation time--forceconsolidates--confirm/--yesas the primary skip-confirmation flag
All commands support these global flags:
--json- Output JSON instead of human-readable text--verbose, -v- Show detailed output--quiet, -q- Suppress non-error output--unmask- Show sensitive data (tokens, passwords) unmasked--auth-token- Override auth token (also reads fromPINNER_AUTH_TOKENenv var)--secure- Use HTTPS instead of HTTP for endpoints (default: true, env:PINNER_SECURE)
github.com/urfave/cli/v3- CLI frameworkgithub.com/ipfs/boxo- IPFS libraries (pinning, DAG, blockstore)go.lumeweb.com/configmanager- Configuration managementgo.lumeweb.com/portal-sdk- Portal SDK (local replace in go.mod)github.com/pterm/pterm- Terminal UI for setup wizardgithub.com/stretchr/testify- Testing frameworkgithub.com/vektra/mockery- Mock generation