stout 0.2.0

A fast, Rust-based Homebrew-compatible package manager
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
# stout

A fast, Rust-based Homebrew-compatible package manager.

[![Build](https://github.com/neul-labs/stout/actions/workflows/ci.yml/badge.svg)](https://github.com/neul-labs/stout/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Documentation](https://img.shields.io/badge/docs-docs.neullabs.com-blue)](https://docs.neullabs.com/stout)

## Why stout?

stout is a drop-in replacement for the Homebrew CLI that's **10-100x faster** for common operations:

| Operation | brew | stout | Speedup |
|-----------|------|-------|---------|
| `--version` | 500ms | 5ms | **100x** |
| `search json` | 2-5s | <50ms | **40-100x** |
| `info wget` | 1-2s | <100ms | **10-20x** |
| `update` | 10-60s | 1-3s | **10-20x** |

The secret? stout eliminates Ruby entirely. It uses a pre-computed SQLite index with FTS5 full-text search, fetches only what it needs, and downloads bottles in parallel.

### Key Features

Beyond speed, stout is designed for real-world workflows:

- **Offline & Air-Gapped Support** - Create local mirrors for environments without internet access
- **Private Index Hosting** - Host your own package index at [neul-labs/stout-index]https://github.com/neul-labs/stout-index or fork it for internal use
- **Multi-Prefix Environments** - Isolated package installations per project, no conflicts
- **Signed Index Updates** - Ed25519 cryptographic signatures on all index data
- **Vulnerability Scanning** - Built-in `stout audit` checks packages against known CVEs
- **Full Homebrew Compatibility** - Drop-in replacement, works alongside existing brew installations

## Installation

### Quick Install (Recommended)

Install stout with a single command:

```bash
curl -fsSL https://raw.githubusercontent.com/neul-labs/stout/main/install.sh | bash
```

This will:
- Detect your OS and architecture
- Download the appropriate binary
- Verify the checksum
- Install to `~/.local/bin` (or `/usr/local/bin` if writable)
- Add to your PATH if needed

#### Installation Options

```bash
# Install to a custom directory
STOUT_INSTALL_DIR=/opt/bin curl -fsSL https://raw.githubusercontent.com/neul-labs/stout/main/install.sh | bash

# Install a specific version
STOUT_VERSION=v0.1.0 curl -fsSL https://raw.githubusercontent.com/neul-labs/stout/main/install.sh | bash

# Skip PATH modification
STOUT_NO_MODIFY_PATH=1 curl -fsSL https://raw.githubusercontent.com/neul-labs/stout/main/install.sh | bash
```

### Manual Download

Download pre-built binaries from the [releases page](https://github.com/neul-labs/stout/releases):

| Platform | Architecture | Download |
|----------|-------------|----------|
| macOS | Apple Silicon (M1/M2/M3) | `stout-aarch64-apple-darwin.tar.gz` |
| macOS | Intel | `stout-x86_64-apple-darwin.tar.gz` |
| Linux | x86_64 | `stout-x86_64-unknown-linux-gnu.tar.gz` |
| Linux | ARM64 | `stout-aarch64-unknown-linux-gnu.tar.gz` |

```bash
# Example for macOS ARM
curl -LO https://github.com/neul-labs/stout/releases/latest/download/stout-aarch64-apple-darwin.tar.gz
tar -xzf stout-aarch64-apple-darwin.tar.gz
sudo mv stout /usr/local/bin/
```

### From Source

```bash
# Clone the repository
git clone https://github.com/neul-labs/stout.git
cd stout

# Build release binary
cargo build --release

# Install to PATH
cp target/release/stout ~/.local/bin/
# or
sudo cp target/release/stout /usr/local/bin/
```

### Shell Completions

```bash
# Bash (add to ~/.bashrc)
eval "$(stout completions bash)"

# Zsh (add to ~/.zshrc)
eval "$(stout completions zsh)"

# Fish
stout completions fish > ~/.config/fish/completions/stout.fish
```

## Quick Start

```bash
# Update the formula index
stout update

# Search for packages
stout search json

# Get package info
stout info jq

# Install a package
stout install jq

# List installed packages
stout list

# Check system health
stout doctor
```

### Cask Support (Applications)

stout can also install macOS applications (casks) and Linux apps (AppImage, Flatpak):

```bash
# Search for applications
stout cask search firefox

# Install an application
stout cask install firefox

# List installed applications
stout cask list

# Get application info
stout cask info visual-studio-code

# Uninstall an application
stout cask uninstall firefox

# Upgrade applications
stout cask upgrade
```

## Commands

stout implements 35+ commands with full Homebrew CLI compatibility:

### Package Management

| Command | brew Equivalent | Description |
|---------|-----------------|-------------|
| `stout install <pkg>` | `brew install` | Install packages |
| `stout uninstall <pkg>` | `brew uninstall` | Uninstall packages |
| `stout reinstall <pkg>` | `brew reinstall` | Reinstall packages |
| `stout upgrade [pkg]` | `brew upgrade` | Upgrade installed packages |
| `stout update` | `brew update` | Update the formula index |
| `stout outdated` | `brew outdated` | Show packages with available updates |
| `stout autoremove` | `brew autoremove` | Remove unused dependencies |

### Discovery & Information

| Command | brew Equivalent | Description |
|---------|-----------------|-------------|
| `stout search <query>` | `brew search` | Search for packages |
| `stout info <pkg>` | `brew info` | Show package information |
| `stout list` | `brew list` | List installed packages |
| `stout deps <pkg>` | `brew deps` | Show package dependencies |
| `stout uses <pkg>` | `brew uses` | Show packages that depend on a package |
| `stout why <pkg>` | `brew why` | Show why a package is installed |
| `stout home <pkg>` | `brew home` | Open package homepage in browser |

### Package Control

| Command | brew Equivalent | Description |
|---------|-----------------|-------------|
| `stout pin <pkg>` | `brew pin` | Pin packages to prevent upgrades |
| `stout unpin <pkg>` | `brew unpin` | Unpin packages to allow upgrades |
| `stout link <pkg>` | `brew link` | Create symlinks for a package |
| `stout unlink <pkg>` | `brew unlink` | Remove symlinks (keep package) |
| `stout switch <pkg> <ver>` | `brew switch` | Switch between installed versions |
| `stout rollback <pkg>` | - | Rollback to previous version |

### System & Maintenance

| Command | brew Equivalent | Description |
|---------|-----------------|-------------|
| `stout cleanup` | `brew cleanup` | Remove old downloads and cache files |
| `stout doctor` | `brew doctor` | Check system health |
| `stout config` | `brew config` | Show stout configuration |
| `stout services` | `brew services` | Manage background services |
| `stout tap` | `brew tap` | Manage custom formula repositories |
| `stout lock` | - | Manage lockfiles for reproducible environments |
| `stout history [pkg]` | - | Show package version history |
| `stout completions <shell>` | - | Generate shell completions |

### Cask (Application) Management

| Command | brew Equivalent | Description |
|---------|-----------------|-------------|
| `stout cask install <app>` | `brew install --cask` | Install applications |
| `stout cask uninstall <app>` | `brew uninstall --cask` | Uninstall applications |
| `stout cask search <query>` | `brew search --cask` | Search for applications |
| `stout cask info <app>` | `brew info --cask` | Show application information |
| `stout cask list` | `brew list --cask` | List installed applications |
| `stout cask outdated` | `brew outdated --cask` | Show outdated applications |
| `stout cask upgrade [app]` | `brew upgrade --cask` | Upgrade applications |

### Bundle & Snapshot

| Command | brew Equivalent | Description |
|---------|-----------------|-------------|
| `stout bundle` | `brew bundle` | Install from Brewfile |
| `stout bundle dump` | `brew bundle dump` | Generate Brewfile from installed |
| `stout bundle check` | `brew bundle check` | Check if Brewfile satisfied |
| `stout bundle list` | `brew bundle list` | List Brewfile entries |
| `stout bundle cleanup` | `brew bundle cleanup` | Remove packages not in Brewfile |
| `stout snapshot create <name>` | - | Create named snapshot |
| `stout snapshot list` | - | List all snapshots |
| `stout snapshot restore <name>` | - | Restore snapshot |

### Security & Audit

| Command | brew Equivalent | Description |
|---------|-----------------|-------------|
| `stout audit` | `brew audit` | Scan packages for known vulnerabilities |
| `stout audit <pkg>` | - | Audit specific package |
| `stout audit --update` | - | Update vulnerability database |

### Offline & Mirroring

| Command | brew Equivalent | Description |
|---------|-----------------|-------------|
| `stout mirror create <dir> <pkgs>` | - | Create offline mirror |
| `stout mirror serve <dir>` | - | Serve mirror via HTTP |
| `stout mirror info <dir>` | - | Show mirror information |
| `stout mirror verify <dir>` | - | Verify mirror integrity |

### Developer Tools

| Command | brew Equivalent | Description |
|---------|-----------------|-------------|
| `stout install -s --jobs=8` | `brew install -s` | Build from source with parallel jobs |
| `stout install -s --cc=clang` | `brew install --cc` | Build with custom compiler |
| `stout bottle create <pkg>` | `brew bottle` | Create bottle from installed package |
| `stout create <url>` | `brew create` | Create formula from URL |
| `stout create --cask <url>` | `brew create --cask` | Create cask from URL |
| `stout test <pkg>` | `brew test` | Test installed packages |
| `stout analytics on\|off\|status` | `brew analytics` | Manage opt-in analytics |

### Multi-prefix Support

stout supports multiple installation prefixes for isolated environments:

| Command | Description |
|---------|-------------|
| `stout prefix create <path>` | Create a new prefix directory structure |
| `stout prefix list` | List all known prefixes |
| `stout prefix info [path]` | Show prefix information and disk usage |
| `stout prefix default <path>` | Set the default prefix |
| `stout prefix remove <path>` | Remove a prefix |
| `stout --prefix=<path> install <pkg>` | Install to a specific prefix |
| `stout --prefix=<path> list` | List packages in a specific prefix |

#### Example: Project-specific Dependencies

```bash
# Create an isolated prefix for a project
stout prefix create ~/projects/myapp/.stout

# Install packages to that prefix
stout --prefix=~/projects/myapp/.stout install python@3.11 node@20

# Add to project-specific PATH
export PATH="$HOME/projects/myapp/.stout/bin:$PATH"

# List packages in the prefix
stout --prefix=~/projects/myapp/.stout list
```

#### Environment Variable

You can also set the default prefix via environment variable:

```bash
export STOUT_PREFIX=~/projects/myapp/.stout
stout install jq  # Installs to custom prefix
```

## How It Works

stout uses a hybrid architecture:

1. **SQLite Index** (~3MB): Contains formula metadata for fast queries
2. **Compressed JSON**: Individual formula details fetched on-demand
3. **Homebrew Bottles**: Uses existing Homebrew bottle infrastructure

```
┌─────────────────────────────────────────────────────────────────┐
│                         stout Architecture                       │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   User ──▶ stout CLI ──▶ SQLite Index ──▶ Homebrew Bottles      │
│                │              │                   │              │
│                │         FTS5 Search         ghcr.io CDN        │
│                │              │                   │              │
│                └──────────────┴───────────────────┘              │
│                                                                  │
│   Index sync: GitHub raw (stout-index repo)                      │
│   Bottle download: Homebrew's existing infrastructure            │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
```

## Compatibility

stout is designed to work alongside existing Homebrew installations:

- Uses the same Cellar structure (`/opt/homebrew/Cellar`)
- Creates compatible `INSTALL_RECEIPT.json` files
- Symlinks to the same prefix (`/opt/homebrew/bin`, etc.)
- Packages installed by either tool are visible to both

## Configuration

Configuration is stored in `~/.stout/config.toml`:

```toml
[index]
base_url = "https://raw.githubusercontent.com/neul-labs/stout-index/main"
auto_update = true
update_interval = 1800  # 30 minutes

[install]
cellar = "/opt/homebrew/Cellar"
prefix = "/opt/homebrew"
parallel_downloads = 4

[cache]
max_size = "2GB"
formula_ttl = 86400      # 1 day
download_ttl = 604800    # 7 days
```

## Project Structure

```
stout/
├── src/                    # CLI application
│   ├── main.rs
│   └── cli/               # Command implementations
├── crates/
│   ├── stout-index/       # SQLite index management
│   ├── stout-resolve/     # Dependency resolution
│   ├── stout-fetch/       # Download management
│   ├── stout-install/     # Package installation
│   ├── stout-state/       # Local state management
│   ├── stout-cask/        # Cask (application) management
│   ├── stout-bundle/      # Brewfile parsing and snapshots
│   ├── stout-audit/       # Vulnerability auditing
│   └── stout-mirror/      # Offline mirror support
├── scripts/
│   ├── sync.py            # Formula index sync script
│   ├── sync_casks.py      # Cask index sync script
│   ├── sync_linux_apps.py # Linux apps sync script
│   └── sync_vulns.py      # Vulnerability index sync script
├── packaging/             # Package manager distribution
│   ├── homebrew/          # Homebrew formula
│   ├── aur/               # Arch Linux PKGBUILD
│   └── nix/               # Nix flake
├── completions/           # Shell completions
└── docs/                  # Documentation
```

## Security

stout implements a defense-in-depth security model:

- **Ed25519 Signatures**: All index updates are cryptographically signed
- **HTTPS Required**: TLS 1.2+ enforced for all connections
- **SHA256 Verification**: Every download is checksum-verified
- **Vulnerability Scanning**: Built-in `stout audit` command

```bash
# Check security configuration
stout config

# Scan for vulnerabilities
stout audit

# Update vulnerability database
stout audit --update
```

See [Security Model](docs/SECURITY.md) for full details.

## Enterprise Features

stout is designed for enterprise environments:

- **Private Index Hosting**: Host your own curated package index
- **Custom Signing Keys**: Use your own Ed25519 keys for trust chain control
- **Air-Gapped Support**: Full offline operation with mirror support
- **CI/CD Integration**: GitHub Actions, GitLab CI, Jenkins examples
- **Multi-Prefix**: Isolated environments per project or team
- **Audit Logging**: Track all package operations for compliance

```bash
# Create offline mirror
stout mirror create /path/to/mirror jq curl python@3.11

# Project-specific prefix
stout prefix create ~/project/.stout
stout --prefix=~/project/.stout install node@20

# Reproducible builds with lock files
stout lock generate
stout lock install
```

See [Enterprise Guide](docs/ENTERPRISE.md) for deployment options.

## Documentation

- [Installation Guide]docs/INSTALL.md
- [Usage Guide]docs/USAGE.md
- [Security Model]docs/SECURITY.md
- [Enterprise Guide]docs/ENTERPRISE.md
- [Architecture]docs/ARCHITECTURE.md
- [Technical Specification]docs/SPEC.md
- [Contributing]docs/CONTRIBUTING.md
- [Packaging Guide]docs/PACKAGING.md
- [Roadmap]docs/ROADMAP.md

## Development

```bash
# Run tests
cargo test --workspace

# Run with verbose logging
RUST_LOG=debug cargo run -- search json

# Build release binary
cargo build --release

# Sync index from Homebrew API (requires Python + uv)
cd scripts && uv run python sync.py --output ../dist
```

## Performance

stout achieves its speed through several optimizations:

1. **Native binary**: No interpreter startup overhead
2. **SQLite + FTS5**: Instant full-text search
3. **Compressed index**: ~3MB download vs 700MB+ git repo
4. **Parallel downloads**: Concurrent bottle fetching with Tokio
5. **On-demand fetching**: Only download what you need

## License

MIT License - see [LICENSE](LICENSE) for details.

## Acknowledgments

- [Homebrew]https://brew.sh - The package manager stout is compatible with
- [uv]https://github.com/astral-sh/uv - Inspiration for CLI UX design