Awesome Go

stacktower

CategoryUtilities
SubcategoryUtilities
Stars522

Visualize dependency graphs as physical tower structures, inspired by XKCD #2347

About stacktower

This large README is shown as a plain-text preview. Read the full README at the source

# Stacktower

[![Deps](https://api.stacktower.io/v1/badge/github/stacktower-io/stacktower)](https://app.stacktower.io/github/stacktower-io/stacktower)
[![CI](https://github.com/stacktower-io/stacktower/actions/workflows/ci.yml/badge.svg)](https://github.com/stacktower-io/stacktower/actions/workflows/ci.yml)
[![codecov](https://codecov.io/gh/stacktower-io/stacktower/graph/badge.svg)](https://codecov.io/gh/stacktower-io/stacktower)
[![Go Report Card](https://goreportcard.com/badge/github.com/stacktower-io/stacktower)](https://goreportcard.com/report/github.com/stacktower-io/stacktower)
[![Go Reference](https://pkg.go.dev/badge/github.com/stacktower-io/stacktower.svg)](https://pkg.go.dev/github.com/stacktower-io/stacktower)
[![Release](https://img.shields.io/github/v/release/stacktower-io/stacktower)](https://github.com/stacktower-io/stacktower/releases)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

Inspired by [XKCD #2347](https://xkcd.com/2347/), Stacktower renders dependency graphs as **physical towers** where blocks rest on what they depend on. Your application sits at the top, supported by libraries below—all the way down to that one critical package maintained by _some dude in Nebraska_.

[![Dependency Tower](https://api.stacktower.io/v1/embed/github/stacktower-io/stacktower?v=2)](https://app.stacktower.io/github/stacktower-io/stacktower)

---

<p align="center">
  <a href="https://app.stacktower.io"><strong>🚀 Try the Web App</strong></a> · <a href="https://www.stacktower.io"><strong>📖 Read the Story</strong></a>
</p>

---

## Installation

### Homebrew (recommended)

The Homebrew install includes everything out of the box — GitHub authentication, private repo access, and all CLI features work without extra configuration.

```bash
brew tap stacktower-io/homebrew-tap
brew install --cask stacktower
```

### Alternative: build from source

> **⚠️ Important:** Building from source (or `go install`) does **not** embed the GitHub App credentials needed for `stacktower github login`, `stacktower github install`, and `stacktower parse github`. These commands will fail unless you manually set `STACKTOWER_GITHUB_APP_CLIENT_ID` and `STACKTOWER_GITHUB_APP_SLUG`. All other commands (parse, render, resolve, etc.) work fine without these.

**Go install:**

```bash
go install github.com/stacktower-io/stacktower/cmd/stacktower@latest
```

**Clone & build:**

```bash
git clone https://github.com/stacktower-io/stacktower.git
cd stacktower
make build
```

## Quick Start

```bash
# Render the included Flask example (XKCD-style tower is the default)
stacktower render examples/real/flask.json -o flask.svg

# Parse a package from a registry, then render it
stacktower parse python fastapi -o fastapi.json
stacktower render fastapi.json -o fastapi.svg

# Or pipe parse straight into render
stacktower parse python flask | stacktower render - -o flask.svg
```

> **Want more?** The CLI generates static SVGs locally. [**Stacktower Cloud**](https://app.stacktower.io) adds interactive towers, dependency history tracking, automated PR diffs via the [GitHub Action](https://github.com/stacktower-io/stacktower-action), AI-powered health grading, and team dashboards — all from the same `parse` output.

## Global Options

These flags apply to all commands:

| Flag              | Description                                                |
| ----------------- | ---------------------------------------------------------- |
| `-v`, `--verbose` | Enable debug logging (search space info, timing details)   |
| `-q`, `--quiet`   | Suppress non-essential output (success messages, stats)    |
| `-h`, `--help`    | Show help for any command                                  |
| `--version`       | Show version information                                   |

---

## `stacktower parse`

Parse dependency graphs from package registries or local manifest files.

```bash
stacktower parse <language> <package-or-file> [flags]
stacktower parse <manifest-file>                       # Auto-detect language from filename
stacktower parse github [owner/repo]                   # Parse from a GitHub repository
```

**Supported languages:** `python`, `rust`, `javascript`, `ruby`, `php`, `java`, `go`

### Parse Options

| Flag                    | Description                                                                          |
| ----------------------- | ------------------------------------------------------------------------------------ |
| `-o`, `--output`        | Output file (if omitted: TTY shows summary/tree, piped stdout emits JSON)            |
| `-n`, `--name`          | Project name for manifest parsing (auto-detected if not set)                         |
| `--max-depth N`         | Maximum dependency depth (default: 10, max: 100)                                     |
| `--max-nodes N`         | Maximum packages to fetch (default: 5000, max: 50000)                                |
| `--workers N`           | Concurrent fetch workers (default: 20)                                               |
| `--enrich`              | Enrich with GitHub metadata — stars, maintainers (default: true)                     |
| `--contributors`        | Fetch GitHub contributors for Nebraska rankings (slower API calls)                   |
| `--security-scan`       | Best-effort scan for known vulnerabilities via OSV.dev                               |
| `--dependency-scope`    | Dependency scope: `prod_only` (default) or `all` (includes dev dependencies)         |
| `--include-prerelease`  | Include prerelease versions (alpha/beta/rc/dev) in resolution                        |
| `--runtime-version`     | Target runtime version for marker evaluation (e.g., `3.11` for Python)               |
| `--no-cache`            | Disable caching                                                                      |

### From Package Registries

```bash
stacktower parse python fastapi -o fastapi.json                  # PyPI
stacktower parse rust serde -o serde.json                        # crates.io
stacktower parse javascript yargs -o yargs.json                  # npm
stacktower parse ruby rails -o rails.json                        # RubyGems
stacktower parse php monolog/monolog -o monolog.json             # Packagist
stacktower parse java com.google.guava:guava -o guava.json       # Maven Central
stacktower parse go github.com/gin-gonic/gin -o gin.json         # Go Module Proxy
```

Use `package@version` to pin a specific version. Without it, the latest version is resolved:

```bash
stacktower parse python [email protected] -o fastapi.json
stacktower parse rust [email protected] -o serde.json
stacktower parse javascript @angular/[email protected] -o angular.json  # scoped packages work too
```

### From Manifest Files

```bash
stacktower parse python poetry.lock -o deps.json
stacktower parse python requirements.txt -o deps.json
stacktower parse rust Cargo.toml -o deps.json
stacktower parse javascript package.json -o deps.json
stacktower parse ruby Gemfile -o deps.json
stacktower parse php composer.json -o deps.json
stacktower parse java pom.xml -o deps.json
stacktower parse go go.mod -o deps.json
```

When the argument exists on disk or matches a known manifest filename, Stacktower auto-detects the language from the filename so you can omit the language subcommand:

```bash
stacktower parse poetry.lock -o deps.json
stacktower parse package-lock.json -o deps.json
stacktower parse Cargo.lock -o deps.json
```

The project name (root node) is auto-detected from the manifest or a sibling file:

- **Cargo.toml**: `[package].name`
- **go.mod**: `module` directive
- **package.json**: `name` field
- **composer.json**: `name` field
- **pom.xml**: `groupId:artifactId`
- **poetry.lock / requirements.txt**: `pyproject.toml` (sibling)
- **Gemfile**: `*.gemspec` (sibling)

Use `--name` to override:

```bash
stacktower parse python requirements.txt --name="my-project" -o deps.json
```

### Metadata Enrichment

By default, `parse` enriches packages with GitHub metadata (stars, maintainers, last commit) for richer visualizations. Set `GITHUB_TOKEN` for higher rate limits:

```bash
export GITHUB_TOKEN=your_token
stacktower parse python fastapi -o fastapi.json

# Skip enrichment if you don't need it
stacktower parse python fastapi --enrich=false -o fastapi.json
```

### Vulnerability Scanning

Add the `--security-scan` flag to annotate every package with its highest vulnerability severity via [OSV.dev](https://osv.dev/):

```bash
stacktower parse python fastapi --security-scan -o fastapi.json
stacktower parse javascript package.json --security-scan -o deps.json
```

When `--security-scan` is enabled, Stacktower performs a best-effort query to OSV.dev in a single batch request and writes severity data (`critical`, `high`, `medium`, `low`) into each node's metadata when available. The scanned graph is cached separately from non-scanned graphs, so subsequent runs are instant.

During rendering, vulnerable packages are automatically colour-coded by severity. Use `--show-vulns=false` to suppress the colours while keeping the data in the graph:

```bash
stacktower render fastapi.json --show-vulns=false -o fastapi.svg
```

### Parse from GitHub

Parse dependencies directly from a GitHub repository with interactive selection:

```bash
stacktower parse github                              # Full interactive flow
stacktower parse github owner/repo                   # Select ref + manifest
stacktower parse github owner/repo --ref v2.0.0      # Parse at specific tag
stacktower parse github owner/repo --ref main         # Explicit branch
stacktower parse github owner/repo --timeout 10m      # Custom timeout
```

| Flag            | Description                                         |
| --------------- | --------------------------------------------------- |
| `--ref`         | Git ref (branch, tag, or commit SHA)                |
| `--timeout`     | Timeout for GitHub operations (default: 5m)         |
| `--public-only` | Show only public repositories in interactive picker |

> **Private repos:** Install the GitHub App with `stacktower github install` and grant access to the repos you need.

### Piping

When `parse` detects that stdout is piped, it emits clean JSON with no chrome — making it composable with other tools:

```bash
# Pipe directly into render
stacktower parse python flask | stacktower render - -o flask.svg

# Pipe into jq for analysis
stacktower parse python requests | jq '.nodes | length'

# Combine with security scan
stacktower parse python django --security-scan | stacktower render - --show-vulns -o django.svg
```

Progress indicators and summary messages always go to stderr, so they never corrupt piped JSON.

### Terminal Output

A typical `parse` run looks like this:

```
⠙ Resolving python/flask...  [42/5000]
  starlette  jinja2  markupsafe  click

✓ Resolved flask (python)
  42 packages · 67 edges · depth 5 · fresh · 2.3s
  → flask.json
Render: stacktower render flask.json
```

---

## `stacktower resolve`

Lightweight alternative to `parse` for quickly testing dependency resolution. Auto-detects the language from manifest filenames and prints a human-readable dependency tree.

```bash
stacktower resolve <manifest-file>
stacktower resolve <language> <package[@version]>
```

### Resolve Options

| Flag                   | Description                                                                  |
| ---------------------- | ---------------------------------------------------------------------------- |
| `-o`, `--output`       | Write JSON to file (resolve tree still prints to stdout)                     |
| `-n`, `--name`         | Project name (for manifest parsing)                                          |
| `--max-depth N`        | Maximum dependency depth (default: 10)                                       |
| `--max-nodes N`        | Maximum packages to fetch (default: 5000)                                    |
| `--enrich`             | Enrich with GitHub metadata (off by default, unlike `parse`)                 |
| `--dependency-scope`   | Dependency scope: `prod_only` (default) or `all`                             |
| `--include-prerelease` | Include prerelease versions in resolution                                    |
| `--runtime-version`    | Target runtime version for marker evaluation                                 |
| `--no-cache`           | Disable caching                                                              |

### Resolve Examples

```bash
# Auto-detect language from filename
stacktower resolve poetry.lock
stacktower resolve Cargo.lock
stacktower resolve package-lock.json
stacktower resolve go.mod

# Resolve from registry
stacktower resolve python fastapi
stacktower resolve rust [email protected]

# Save resolution as JSON for rendering
stacktower resolve poetry.lock -o deps.json
stacktower render deps.json -o deps.svg
```

**Output:**

```
fastapi 0.104.1
  starlette 0.27.0
    anyio 4.0.0
      sniffio 1.3.0
  pydantic 2.5.2
    pydantic-core 2.14.5
    typing-extensions 4.8.0

Resolved 7 packages (max depth: 3, direct: 2)
```

### resolve vs parse

| | `resolve` | `parse` |
| --- | --- | --- |
| Language detection | Auto-detected from filename | Auto-detected from filename (or explicit language subcommand) |
| Default output | Human-readable tree | TTY: summary/tree, piped stdout: graph JSON |
| Metadata enrichment | Off (opt-in with `--enrich`) | On by default (`--enrich=false` to skip) |
| Best for | Local testing, inspecting deps | Rendering pipeline, CI |

---

## `stacktower list`

List all available versions of a package from its registry. Requires a language subcommand:

```bash
stacktower list <language> <package> [flags]
```

### List Options

| Flag                   | Description                                                           |
| ---------------------- | --------------------------------------------------------------------- |
| `--all`                | Show all versions (default: newest 20)                                |
| `--limit N`            | Show the newest N versions (default: 20; ignored when `--all` is set) |
| `--runtime-version`    | Filter versions compatible with a specific runtime (e.g., `3.8`)      |
| `--supported-runtimes` | Display runtime constraint for each version                           |
| `--no-cache`           | Bypass cached version data                                            |

### List Examples

```bash
stacktower list python fastapi
stacktower list rust serde
stacktower list javascript react
stacktower list go github.com/gin-gonic/gin

# Show all versions
stacktower list python django --all

# Filter by Python version compatibility
stacktower list python fastapi --runtime-version 3.8

# Show runtime requirements for each version
stacktower list python fastapi --supported-runtimes
```

**Output:**

```
  fastapi  python · 277 versions
  latest   0.129.2

  0.129.1   0.129.0   0.128.8   0.128.7   0.128.6   0.128.5   0.128.4
  0.128.3   0.128.2   0.128.1   0.128.0   0.127.1   0.127.0   0.126.0
  0.125.0   0.124.4   0.124.3   0.124.2   0.124.1   0.124.0

  … 256 older versions not shown (use --all to list all)
```

---

## `stacktower render`

Generate visualizations from parsed JSON graphs. This is a shortcut that combines `layout` and `visualize` in one step.

```bash
stacktower render <graph.json|-> [flags]
```

Use `-` to read graph JSON from stdin.

### Render Options

| Flag               | Description                                                              |
| ------------------ | ------------------------------------------------------------------------ |
| `-o`, `--output`   | Output file or base path for multiple formats                            |
| `-t`, `--type`     | Visualization type: `tower` (default), `nodelink`                        |
| `-f`, `--format`   | Output format(s): `svg` (default), `json`, `pdf`, `png` (comma-separated)|
| `--normalize`      | Apply graph normalization (default: true)                                |
| `--show-vulns`     | Show vulnerability severity colours (default: true)                      |
| `--show-licenses`  | Show license compliance indicators — copyleft/unknown borders (default: true) |
| `--flags-on-top`   | Render security flags on top of all blocks (default: true)               |
| `--no-cache`       | Disable caching                                                          |

### Tower-Specific Options

| Flag                              | Description                                                           |
| --------------------------------- | --------------------------------------------------------------------- |
| `--width N`                       | Frame width in pixels (default: 800)                                  |
| `--height N`                      | Frame height in pixels (default: 600)                                 |
| `--style handdrawn\|simple`       | Visual style (default: handdrawn)                                     |
| `--randomize`                     | Vary block widths to visualize load-bearing structure (default: true) |
| `--merge`                         | Merge subdivider blocks into continuous towers (default: true)        |
| `--popups`                        | Enable hover popups with package metadata (default: true)             |
| `--nebraska`                      | Show "Nebraska guy" maintainer ranking panel                          |
| `--edges`                         | Show dependency edges as dashed lines                                 |
| `--ordering optimal\|barycentric` | Crossing minimization algorithm (default: optimal)                    |
| `--ordering-timeout N`            | Timeout for optimal search in seconds (default: 60)                   |

### Render Examples

```bash
# Basic tower rendering (XKCD-style)
stacktower render flask.json -o flask.svg

# Clean style without hand-drawn effects
stacktower render serde.json --style simple --randomize=false --popups=false -o serde.svg

# Node-link diagram (uses Graphviz DOT layout)
stacktower render yargs.json -t nodelink -o yargs.svg

# With Nebraska maintainer rankings
stacktower render flask.json --nebraska -o flask.svg

# Multiple output formats
stacktower render flask.json -f svg,pdf,png -o flask

# Large graph with faster ordering
stacktower render big-project.json --ordering barycentric -o big.svg

# Custom dimensions
stacktower render flask.json --width 1200 --height 900 -o flask-large.svg

# Show dependency edges
stacktower render flask.json --edges -o flask-edges.svg

# Disable vulnerability colours
stacktower render scanned.json --show-vulns=false -o clean.svg
```

### Output Formats

Output path behavior:

- **No `-o`**: Derives from input (`input.json` → `input.<format>`)
- **Single format**: Uses exact path (`-o out.svg` → `out.svg`)
- **Multiple formats**: Strips extension, adds format (`-o out -f svg,json` → `out.svg`, `out.json`)

> **Note:** PDF and PNG output requires [librsvg](https://wiki.gnome.org/Projects/LibRsvg):
>
> - macOS: `brew install librsvg`
> - Linux: `apt install librsvg2-bin`

### Two-Step Workflow

For more control, run `layout` and `visualize` separately:

```bash
stacktower layout flask.json -o flask.layout.json
stacktower visualize flask.layout.json -o flask.svg
```

---

## `stacktower layout`

Compute visualization layout from a dependency graph. Outputs a layout JSON that can be rendered separately with `visualize`.

```bash
stacktower layout <graph.json> [flags]
```

### Layout Options

| Flag                              | Description                                                           |
| --------------------------------- | --------------------------------------------------------------------- |
| `-o`, `--output`                  | Output file (default: `<input>.layout.json`)                          |

Frequently Asked Questions

What is stacktower?

stacktower is a Utilities library for the Go programming language. Visualize dependency graphs as physical tower structures, inspired by XKCD #2347

How do I install stacktower?

Install stacktower with the Go module system using `go get stacktower-io/stacktower`. Check the repository for the current installation instructions.

What category does stacktower belong to?

stacktower is listed under Utilities, specifically Utilities.

← Back to Utilities