██████╗ ██████╗ ██████╗ ██████╗
██╔══██╗██╔══██╗██╔══██╗██╔════╝
███████║███████║██║ ██║██║
██╔══██║██╔══██║██║ ██║██║
██║ ██║██║ ██║██████╔╝╚██████╗
╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ╚═════╝
Fix misaligned right borders in ASCII diagrams with a single command
Install • Quick Start • How It Works • Commands
The Problem: You spend 10 minutes crafting a beautiful ASCII diagram, then edit the content and now all the right borders are misaligned. Manual fixing is tedious and error-prone.
BEFORE AFTER
+------------------+ +------------------+
| Short| | Short |
| Much longer text | → | Much longer text |
| Medium| | Medium |
+------------------+ +------------------+
The Solution: aadc automatically detects ASCII diagram blocks and aligns their right borders by adding padding—never removing content.
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/aadc/main/install.sh?$(date +%s)" | bashOr via Cargo:
cargo install aadcWorks on Linux and macOS. Auto-detects your platform and downloads the right binary.
Then run:
cat diagram.txt | aadc > fixed.txt| Feature | Description |
|---|---|
| Automatic Detection | Finds diagram blocks heuristically—no markers needed |
| Safe Edits | Only adds padding, never removes characters |
| Unicode Support | Handles │ ─ ┌ ┐ └ ┘ ╔ ╗ ╚ ╝ and ASCII + - | |
| Iterative Correction | Runs multiple passes until alignment converges |
| Confidence Scoring | Skips ambiguous blocks unless you force them with --all |
| Stdin/Stdout | Plays nice with pipes and shell scripts |
# Create a misaligned diagram
cat << 'EOF' > diagram.txt
Here's my architecture:
┌────────────────┐
│ API Gateway|
│ Authentication │
│ Rate Limiting|
└────────────────┘
And here's the flow:
+--------+ +----------+
| Client| → | Server|
+--------+ +----------+
EOF
# Fix it
aadc diagram.txt
# Or fix in place
aadc -i diagram.txt
# See what's happening
aadc -v diagram.txtOutput with -v (verbose):
Processing 15 lines...
Found 2 diagram block(s)
Block 1: lines 3-7 (confidence: 100%)
Iteration 1: applied 2 revision(s)
Converged after 1 iteration(s)
Block 2: lines 11-13 (confidence: 100%)
Iteration 1: applied 2 revision(s)
Processed 2 block(s), 4 revision(s) applied
Verbose mode ends with a concise statistics summary:
─── Summary ───
Blocks: 2 found, 2 processed, 0 skipped
Revisions: 4 applied, 0 skipped
Time: 1.23ms (12345 lines/sec)
When processing multiple files (or recursive mode), a file summary is included:
─── Summary ───
Files: 3 processed, 2 modified, 1 unchanged
Blocks: 5 found, 4 processed, 1 skipped
Revisions: 9 applied, 2 skipped
Time: 6.40ms (7800 lines/sec)
For machine-readable output, --json includes the same metrics in the input,
processing, and output fields.
-
Detection Over Markers: No special comments or tags required. aadc recognizes box-drawing patterns automatically.
-
Conservative by Default: Only modifies lines it's confident about. Use
--allto force processing of ambiguous blocks. -
Monotone Edits: Only adds whitespace padding—never deletes characters. Your content is safe.
-
Iterative Refinement: Runs multiple correction passes until the alignment stabilizes or hits
--max-iters. -
Scoring System: Each proposed edit gets a confidence score. Edits below
--min-scoreare skipped.
┌─────────────────────────────────────────────────────────────────┐
│ INPUT │
│ (file or stdin) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ TAB EXPANSION │
│ Converts tabs to spaces (--tab-width) │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ BLOCK DETECTION │
│ Scans for lines with box-drawing characters │
│ Groups consecutive "boxy" lines into blocks │
│ Calculates confidence score per block │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ ITERATIVE CORRECTION (per block) │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 1. Analyze lines: find right borders │ │
│ │ 2. Find target column (rightmost border position) │ │
│ │ 3. Generate revision candidates │ │
│ │ 4. Score each revision │ │
│ │ 5. Apply revisions above --min-score │ │
│ │ 6. Repeat until converged or --max-iters reached │ │
│ └────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ OUTPUT │
│ (stdout or --in-place) │
└─────────────────────────────────────────────────────────────────┘
Corners:
ASCII: +
Unicode: ┌ ┐ └ ┘ ╔ ╗ ╚ ╝ ╭ ╮ ╯ ╰
Horizontal borders:
ASCII: - = ~
Unicode: ─ ━ ═ ╌ ╍ ┄ ┅ ┈ ┉
Vertical borders:
ASCII: |
Unicode: │ ┃ ║ ╎ ╏ ┆ ┇ ┊ ┋
Junctions:
Unicode: ┬ ┴ ├ ┤ ┼ ╦ ╩ ╠ ╣ ╬ ╤ ╧ ╟ ╢ ╫ ╪
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/aadc/main/install.sh?$(date +%s)" | bashOptions:
# Install to /usr/local/bin (requires sudo)
curl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/aadc/main/install.sh | bash -s -- --system
# Auto-update PATH in shell rc files
curl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/aadc/main/install.sh | bash -s -- --easy-mode
# Install specific version
curl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/aadc/main/install.sh | bash -s -- --version v0.1.0
# Build from source instead of downloading binary
curl -fsSL https://raw.githubusercontent.com/Dicklesworthstone/aadc/main/install.sh | bash -s -- --from-sourcecargo install aadcgit clone https://github.com/Dicklesworthstone/aadc
cd aadc
cargo install --path .cargo build --release
# Binary at target/release/aadcRequirements:
- Rust nightly (Edition 2024)
- See
rust-toolchain.tomlfor exact version
aadc [OPTIONS] [FILE]
| Argument | Description |
|---|---|
[FILE] |
Input file or directory. Reads from stdin if not provided (directories require --recursive). |
| Option | Short | Default | Description |
|---|---|---|---|
--in-place |
-i |
false | Edit file in place (requires FILE) |
--recursive |
-r |
false | Process files recursively in directories |
--glob |
*.txt,*.md |
Glob pattern for recursive mode (comma-separated) | |
--no-gitignore |
false | Do not respect .gitignore when recursing |
|
--max-depth |
0 | Maximum directory depth (0 = unlimited) | |
--max-iters |
-m |
10 | Maximum correction iterations per block |
--min-score |
-s |
0.5 | Minimum confidence score (0.0-1.0) for applying edits |
--tab-width |
-t |
4 | Tab expansion width in spaces |
--all |
-a |
false | Process all diagram-like blocks, even low-confidence ones |
--verbose |
-v |
false | Show correction progress |
--diff |
-d |
false | Show unified diff instead of full output |
--dry-run |
-n |
false | Preview changes without modifying files (exit 3 if changes would be made) |
--watch |
-w |
false | Watch file for changes and auto-correct |
--debounce-ms |
500 | Debounce interval in milliseconds (for --watch mode) |
|
--backup |
false | Create backup file before in-place editing (requires --in-place) |
|
--backup-ext |
.bak |
Extension for backup files (requires --backup) |
|
--json |
false | Output results as JSON (conflicts with --verbose/--diff) |
|
--help |
-h |
Print help | |
--version |
-V |
Print version |
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error (file not found, permission denied, I/O error) |
| 2 | Invalid command-line arguments |
| 3 | Dry-run mode: changes would be made |
| 4 | Parse error (invalid UTF-8 or binary input) |
# Basic: stdin to stdout
cat file.txt | aadc
# File to stdout
aadc diagram.txt
# Edit in place
aadc -i diagram.txt
# Verbose mode
aadc -v diagram.txt
# More aggressive (lower threshold)
aadc --min-score 0.3 diagram.txt
# Process everything
aadc --all diagram.txt
# Custom tab width
aadc --tab-width 2 diagram.txt
# Combine options
aadc -i -v --max-iters 20 --min-score 0.4 diagram.txtProcess entire directory trees:
# All .txt and .md files (default patterns)
aadc -r docs/
# Custom glob patterns
aadc -r --glob "*.md" docs/
aadc -r --glob "*.txt,*.md,*.rst" .
# In-place recursive edit
aadc -ri docs/
# Limit depth
aadc -r --max-depth 2 docs/
# Include gitignored files
aadc -r --no-gitignore vendor/Automatically re-correct files when they change:
# Start watching a file
aadc --watch diagram.txt
# With custom debounce (default 500ms)
aadc --watch --debounce-ms 1000 diagram.txt
# Watch with verbose output
aadc -v --watch diagram.txtWatch mode is ideal for iterative diagram editing workflows. Press Ctrl+C to stop watching.
| Tool | Auto-Detect | Safe Edits | Unicode | Iterative | CLI |
|---|---|---|---|---|---|
| aadc | Yes | Yes | Yes | Yes | Yes |
| Manual editing | N/A | No | Yes | N/A | N/A |
| sed/awk scripts | No | No | Partial | No | Yes |
| Editor plugins | Varies | Varies | Varies | No | No |
Why not just use sed?
- sed requires you to know the exact column positions
- sed can easily delete content if the pattern is wrong
- sed doesn't understand diagram structure
Why not use an editor plugin?
- Not scriptable
- Doesn't batch process files
- Many don't detect diagram boundaries automatically
Cause: Your diagram doesn't have recognizable box-drawing characters on both sides of lines.
Fix: Ensure lines have border characters (|, │, +, ┌, etc.) at both start and end:
| This is detected |
This is not detected
Or use --all to force processing:
aadc --all diagram.txtCause: The confidence score for proposed edits is below --min-score.
Fix: Lower the threshold:
aadc --min-score 0.3 diagram.txtCause: Tabs in the input might be confusing the column calculations.
Fix: Adjust tab width to match your editor:
aadc --tab-width 2 diagram.txt # For 2-space tabs
aadc --tab-width 8 diagram.txt # For 8-space tabsCause: CJK characters and emoji are double-width, but some terminals render them inconsistently.
Fix: This is a terminal rendering issue, not aadc. The tool assumes standard Unicode width rules.
Cause: No input file was provided with -i.
Fix: Provide a file path:
aadc -i diagram.txt # Correct
cat diagram.txt | aadc -i # Wrong: no file to editFor pipeline efficiency, aadc performs a quick scan before full processing:
- If less than 1% of lines contain box-drawing characters, the input passes through unchanged
- This makes piping large text files through aadc essentially free
- Use
--allto force processing regardless of content
# Fast: essays, code, logs pass through instantly
cat large_logfile.txt | aadc
# Verbose shows the decision
cat file.txt | aadc -v
# Force processing
cat ambiguous.txt | aadc --all- Right borders only: Currently only aligns right-side borders. Left alignment is assumed correct.
- Single-character borders: Expects borders to be single characters, not multi-character sequences.
- No nested box detection: Treats all box characters equally; doesn't understand nested structures.
- Heuristic detection: May misidentify some content as diagrams or miss unusual diagram styles.
- No undo: When using
--in-place, keep backups or use version control.
Q: Will it mess up my code?
A: No. aadc only modifies lines it confidently identifies as part of ASCII diagrams. Regular code, prose, and other content are passed through unchanged.
Q: Can I use it in a CI pipeline?
A: Yes. Use stdin/stdout mode:
cat diagram.md | aadc > diagram-fixed.md
diff diagram.md diagram-fixed.md # Check for changesQ: Does it work with Markdown code blocks?
A: Yes. The tool processes the entire file and finds diagram blocks within any context.
Q: What about really complex diagrams?
A: Increase --max-iters for complex diagrams that need multiple passes:
aadc --max-iters 50 complex.txtQ: Can I make it more aggressive?
A: Use --all to process all detected blocks and --min-score 0.1 to accept almost any edit:
aadc --all --min-score 0.1 diagram.txtQ: How do I see what it's doing?
A: Use verbose mode:
aadc -v diagram.txtThe project has comprehensive test coverage with unit tests, integration tests, and E2E tests.
# Run all tests
cargo test
# Run unit tests only
cargo test --lib
# Run integration tests
cargo test --test integration
# Run E2E bash test suites
./tests/e2e_basic_cli.sh # Stdin/stdout, file I/O, exit codes
./tests/e2e_cli_options.sh # CLI flags and options
./tests/e2e_fixtures.sh # Fixture-based tests with expected outputs
# Run comprehensive E2E runner with logging
./tests/e2e_runner.sh # All suites with detailed log
./tests/e2e_runner.sh -v # Verbose mode
./tests/e2e_runner.sh -f cli # Filter by pattern
# Check code quality
cargo clippy --all-targets -- -D warnings
cargo fmt --check| Category | Command | Description |
|---|---|---|
| Unit Tests | cargo test |
138 tests covering core logic |
| Integration | cargo test --test integration |
20 E2E Rust tests |
| E2E Basic | ./tests/e2e_basic_cli.sh |
Stdin, files, exit codes |
| E2E Options | ./tests/e2e_cli_options.sh |
CLI flags |
| E2E Fixtures | ./tests/e2e_fixtures.sh |
Input/expected pairs |
Coverage reports are generated in CI and uploaded to Codecov. The minimum threshold is 80% line coverage.
# Generate local coverage report (requires cargo-llvm-cov)
cargo llvm-cov --html
open target/llvm-cov/html/index.htmlPlease don't take this the wrong way, but I do not accept outside contributions for any of my projects. I simply don't have the mental bandwidth to review anything, and it's my name on the thing, so I'm responsible for any problems it causes; thus, the risk-reward is highly asymmetric from my perspective. I'd also have to worry about other "stakeholders," which seems unwise for tools I mostly make for myself for free. Feel free to submit issues, and even PRs if you want to illustrate a proposed fix, but know I won't merge them directly. Instead, I'll have Claude or Codex review submissions via gh and independently decide whether and how to address them. Bug reports in particular are welcome. Sorry if this offends, but I want to avoid wasted time and hurt feelings. I understand this isn't in sync with the prevailing open-source ethos that seeks community contributions, but it's the only way I can move at this velocity and keep my sanity.
MIT License (with OpenAI/Anthropic Rider). See LICENSE for details.
