Initial project documentation for workflow-miner — a Rust CLI + zsh plugin that mines recurring command workflows from Atuin shell history.
119 lines
4.0 KiB
Markdown
119 lines
4.0 KiB
Markdown
# Research: Rust Ecosystem & Dependencies
|
|
|
|
## SQLite Access: rusqlite
|
|
|
|
**Winner: [rusqlite](https://docs.rs/rusqlite/0.38) v0.38**
|
|
|
|
| Feature | rusqlite | sqlx |
|
|
|---------|----------|------|
|
|
| Async | No (sync) | Yes |
|
|
| SQLite-only | Yes | No (multi-DB) |
|
|
| Bundled SQLite | Yes (feature flag) | No |
|
|
| Read-only support | Yes (`SQLITE_OPEN_READ_ONLY`) | Yes |
|
|
|
|
Why rusqlite:
|
|
- Synchronous is fine for a CLI reading a local file
|
|
- `Connection::open_with_flags(path, OpenFlags::SQLITE_OPEN_READ_ONLY)` ensures safety
|
|
- `features = ["bundled"]` includes SQLite 3.49.2 — no system dependency
|
|
- Simpler dependency tree than sqlx
|
|
- WAL-safe: reading an Atuin DB in WAL mode from a separate process is safe
|
|
|
|
```rust
|
|
use rusqlite::{Connection, OpenFlags};
|
|
|
|
let db = Connection::open_with_flags(
|
|
"~/.local/share/atuin/history.db",
|
|
OpenFlags::SQLITE_OPEN_READ_ONLY | OpenFlags::SQLITE_OPEN_NO_MUTEX,
|
|
)?;
|
|
```
|
|
|
|
## Shell Command Parsing
|
|
|
|
### Level 1: Word splitting — shell-words
|
|
|
|
[shell-words](https://docs.rs/shell-words) v1 — POSIX shell word splitting.
|
|
|
|
```rust
|
|
shell_words::split("git commit -m \"fix typo\"")
|
|
// → ["git", "commit", "-m", "fix typo"]
|
|
```
|
|
|
|
Simple, correct, well-maintained. Exactly what we need for command abstraction.
|
|
|
|
### Level 2: Full AST parsing (optional)
|
|
|
|
| Crate | Version | Description | Maturity |
|
|
|-------|---------|-------------|----------|
|
|
| [brush-parser](https://docs.rs/brush-parser) | 0.3.0 | Full POSIX/bash tokenizer + parser with AST | Active, part of brush-shell |
|
|
| [conch-parser](https://github.com/ipetkov/conch-parser) | 0.1.1 | Shell parser with AST builder | Stale |
|
|
| [mystsh](https://crates.io/crates/mystsh) | Early | POSIX/bash parser | Newer, active |
|
|
|
|
### Level 3: Variable expansion
|
|
|
|
[shellexpand](https://docs.rs/shellexpand) v3.1.1 — tilde and `$VAR` expansion. 10M+ downloads.
|
|
|
|
## TUI: ratatui
|
|
|
|
**Winner: [ratatui](https://github.com/ratatui/ratatui) v0.30**
|
|
|
|
| Library | Stars | Status |
|
|
|---------|-------|--------|
|
|
| **ratatui** | 18.6k | Active, community standard |
|
|
| cursive | ~3.8k | Maintained, less active |
|
|
| tui-rs | ~10k | **Unmaintained** (ratatui is the fork) |
|
|
|
|
Why ratatui:
|
|
- Immediate-mode rendering (you own the render loop)
|
|
- Widgets: Block, Paragraph, List, Table, Chart, BarChart, Tabs, etc.
|
|
- Backends: crossterm (default), termion, termwiz
|
|
- 100+ third-party widgets via [awesome-ratatui](https://github.com/ratatui/awesome-ratatui)
|
|
- 60+ FPS with complex layouts
|
|
- Since 0.30.0: modular architecture (ratatui-core, ratatui-widgets, ratatui-crossterm)
|
|
|
|
Relevant widgets for workflow dashboard:
|
|
- `Table` — displaying discovered patterns
|
|
- `List` — navigating workflows
|
|
- `BarChart` / `Sparkline` — frequency visualization
|
|
- `Tabs` — switching views
|
|
|
|
## CLI Framework: clap
|
|
|
|
[clap](https://docs.rs/clap/4) v4 with derive feature — standard, ergonomic.
|
|
|
|
## Sequential Pattern Mining
|
|
|
|
**No mature Rust crate exists.** Zero repos in Rust on the [sequential-pattern-mining GitHub topic](https://github.com/topics/sequential-pattern-mining).
|
|
|
|
Recommended: Implement PrefixSpan directly, porting from [PrefixSpan-py](https://github.com/chuanconggao/PrefixSpan-py). ~300-500 lines of Rust.
|
|
|
|
## Justfile Generation
|
|
|
|
No Rust crate for generating Justfiles. Format is simple enough for string formatting.
|
|
|
|
Key syntax rules:
|
|
- Recipe bodies use spaces (with `set indent`) or tabs
|
|
- Recipe names: lowercase, hyphens allowed
|
|
- Variables: `name := "value"`, interpolated with `{{name}}`
|
|
- Dependencies: `test: build lint`
|
|
- Parameters: `deploy target="default":`
|
|
- Shebang recipes: first line `#!`
|
|
- `@` prefix suppresses echo
|
|
- Validate with `just --fmt --check --unstable -f <file>`
|
|
|
|
## Recommended Cargo.toml
|
|
|
|
```toml
|
|
[workspace.dependencies]
|
|
rusqlite = { version = "0.38", features = ["bundled"] }
|
|
shell-words = "1"
|
|
ratatui = "0.30"
|
|
crossterm = "0.28"
|
|
chrono = { version = "0.4", features = ["serde"] }
|
|
clap = { version = "4", features = ["derive"] }
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
serde_yaml = "0.9"
|
|
anyhow = "1"
|
|
dirs = "6"
|
|
```
|