Professional Go CLI for StackHawk DAST platform - scan management, security alerts, team/app operations with enterprise-grade testing and CI/CD
A professional-grade Go CLI companion utility for the StackHawk scanner and platform. Provides developers and security teams with streamlined terminal access to StackHawk's dynamic application security testing (DAST) capabilities.
**Language**: Go 1.24
**CLI Framework**: Cobra
**License**: MIT
**Design Pattern**: GitHub `gh` CLI conventions
```
hawkop/
├── main.go # Application entry point
├── cmd/ # Cobra command definitions
│ ├── root.go # Root command setup
│ ├── init.go # API key initialization
│ ├── status.go # Config status
│ ├── version.go # Version info
│ ├── org.go # Organization management
│ ├── user.go # User listing
│ ├── team.go # Team management
│ ├── app.go # Application management
│ └── scan.go # Scan analysis
├── internal/
│ ├── config/ # YAML config + JWT management
│ │ ├── config.go
│ │ └── config_test.go # 35.1% coverage
│ ├── api/ # StackHawk API client
│ │ ├── client.go # HTTP client with JWT refresh
│ │ ├── client_test.go # 34.4% coverage
│ │ └── types.go # API response structs
│ ├── format/ # Output formatting
│ │ ├── table.go
│ │ └── table_test.go # 100% coverage
│ └── version/ # Build-time version info
│ └── version.go
├── Makefile # Build automation
├── .goreleaser.yaml # Multi-platform releases
└── HAWKOPDOC.md # CLI command specifications
```
Stored at `~/.config/hawkop/config.yaml` (permissions 600):
```yaml
api_key: your-api-key
org_id: optional-default-org-id
jwt:
token: jwt-token
expires_at: 2024-12-25T15:30:45Z
```
**Pattern**: `hawkop <command> <subcommand> [flags]`
| Command | Subcommands | Purpose |
|---------|-------------|---------|
| `init` | - | API key setup (encrypted storage) |
| `status` | - | Show configuration state |
| `version` | - | Build version and commit info |
| `org` | `list`, `get`, `set`, `clear` | Organization management |
| `user` | `list` | User listing with role filters |
| `team` | `list` | Team management |
| `app` | `list` | Application listing with status filters |
| `scan` | `list`, `get`, `alerts` | Scan analysis and security alerts |
| Method | Endpoint | Purpose |
|--------|----------|---------|
| `GET` | `/api/v1/auth/login` | JWT authentication (X-ApiKey header) |
| `GET` | `/api/v1/user` | Current user + organizations |
| `GET` | `/api/v1/org/{orgId}/members` | Organization members (max 1000) |
| `GET` | `/api/v1/org/{orgId}/teams` | Organization teams (max 1000) |
| `GET` | `/api/v2/org/{orgId}/apps` | Applications (max 1000) |
| `GET` | `/api/v1/scan/{orgId}` | Scans with metadata (max 1000) |
| `GET` | `/api/v1/scan/{scanId}/alerts` | Security alerts for scan |
```bash
make build # Build with version injection
make test # Run tests with coverage
make lint # Format, vet, golangci-lint
make install # Install to GOPATH/bin
make release-snapshot # Test release build
make clean # Remove artifacts
```
```bash
go run main.go # Run directly
go build # Build binary
go test ./... # All tests
go test ./internal/api/ # API client tests
go test ./cmd/ # Command tests
go vet ./... # Static analysis
go fmt ./... # Format code
go mod tidy # Clean dependencies
```
When working with this codebase:
**Pattern to follow**:
```go
// cmd/newcmd.go
package cmd
import (
"github.com/spf13/cobra"
"hawkop/internal/api"
"hawkop/internal/format"
)
var newCmd = &cobra.Command{
Use: "new [subcommand]",
Short: "Brief description",
Long: "Detailed description",
}
var newListCmd = &cobra.Command{
Use: "list",
Short: "List resources",
RunE: func(cmd *cobra.Command, args []string) error {
// 1. Load config
// 2. Create API client
// 3. Fetch data with pageSize=1000
// 4. Apply filters
// 5. Format output (table or JSON)
return nil
},
}
func init() {
rootCmd.AddCommand(newCmd)
newCmd.AddCommand(newListCmd)
// Add consistent flags
newListCmd.Flags().String("format", "table", "Output format (table|json)")
newListCmd.Flags().String("org", "", "Organization ID")
}
```
**Respect rate limits** (167ms between calls):
```go
client := api.NewClient(cfg.APIKey, cfg.JWT.Token)
time.Sleep(167 * time.Millisecond) // Rate limit compliance
data, err := client.Get(endpoint)
if err != nil {
return fmt.Errorf("❌ API error: %w", err)
}
```
**Handle JWT refresh automatically** - client handles 401 responses.
**All new code must include**:
**Example test structure**:
```go
func TestNewCommand(t *testing.T) {
// Setup mock server
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(mockData)
}))
defer server.Close()
// Test logic
// Assertions with testify
}
```
**Table output** (default):
```go
rows := [][]string{
{"Column1", "Column2", "Column3"},
}
format.PrintTable([]string{"Header1", "Header2", "Header3"}, rows)
```
**JSON output** (--format json):
```go
if formatFlag == "json" {
jsonData, _ := json.MarshalIndent(data, "", " ")
fmt.Println(string(jsonData))
return nil
}
```
```go
// User-facing errors with ❌ prefix
return fmt.Errorf("❌ Failed to load config: %w", err)
// Validation errors
if input == "" {
return fmt.Errorf("❌ Required flag missing: --input")
}
// API errors with context
if resp.StatusCode == 404 {
return fmt.Errorf("❌ Resource not found: %s", resourceID)
}
```
**Immediate Opportunities**:
1. **Scan Deep Dive**: `scan finding`, individual alert analysis
2. **Reporting**: `app summary`, MTTR dashboards, compliance reports
3. **Policy Management**: `policy list`, assignment, configuration
4. **Export Capabilities**: CSV, PDF report generation
5. **Interactive Mode**: Guided workflows for common tasks
**When adding features**:
1. **API Rate Limit**: 360 requests/minute (enforce 167ms intervals)
2. **Pagination**: Always use `pageSize=1000` (API maximum)
3. **Go Version**: 1.24 required
4. **Config Location**: `~/.config/hawkop/` (XDG standard)
5. **Testing**: All new code requires test coverage
6. **Build**: Use Makefile for consistent builds with version injection
7. **Release**: GoReleaser handles multi-platform binaries
Code is ready when:
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/stackhawk-cli-companion-hawkop/raw