ASCIInator - a binary graphic image to text file conversion suite
Go to file
dev 9a4e501be9 fix: jp2a requires --key=value arg format
jp2a 1.3.x does not accept space-separated long option args.
Added _argFormat: 'equals' to jp2a schema so buildArgs emits
--key=value for value flags. Also mirrors chafa's width/height →
--size=WxH combining in runJp2a.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 11:31:37 +00:00
.vscode feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
e2e feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
public feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
server fix: jp2a requires --key=value arg format 2026-04-29 11:31:37 +00:00
src fix: Fastify on 0.0.0.0, remove vueDevTools, nginx API proxy config 2026-04-29 11:26:18 +00:00
.editorconfig feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
.gitattributes feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
.gitignore feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
.oxlintrc.json feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
.prettierrc.json feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
asciinator.conf fix: Fastify on 0.0.0.0, remove vueDevTools, nginx API proxy config 2026-04-29 11:26:18 +00:00
CLAUDE.md feat: full GUI, test API, auto-convert, aspect-ratio sliders 2026-04-29 10:29:45 +00:00
eslint.config.js feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
index.html feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
jsconfig.json feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
package-lock.json feat: full GUI, test API, auto-convert, aspect-ratio sliders 2026-04-29 10:29:45 +00:00
package.json feat: full GUI, test API, auto-convert, aspect-ratio sliders 2026-04-29 10:29:45 +00:00
playwright.config.js feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
postcss.config.js feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
README.md feat: full GUI, test API, auto-convert, aspect-ratio sliders 2026-04-29 10:29:45 +00:00
tailwind.config.js feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00
vite.config.js fix: Fastify on 0.0.0.0, remove vueDevTools, nginx API proxy config 2026-04-29 11:26:18 +00:00
vitest.config.js feat: initial commit — ASCIInator v0.1 2026-04-28 19:47:57 +00:00

ASCIInator

 █████╗ ███████╗ ██████╗██╗██╗███╗   ██╗ █████╗ ████████╗ ██████╗ ██████╗
██╔══██╗██╔════╝██╔════╝██║██║████╗  ██║██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗
███████║███████╗██║     ██║██║██╔██╗ ██║███████║   ██║   ██║   ██║██████╔╝
██╔══██║╚════██║██║     ██║██║██║╚██╗██║██╔══██║   ██║   ██║   ██║██╔══██╗
██║  ██║███████║╚██████╗██║██║██║ ╚████║██║  ██║   ██║   ╚██████╔╝██║  ██║
╚═╝  ╚═╝╚══════╝ ╚═════╝╚═╝╚═╝╚═╝  ╚═══╝╚═╝  ╚═╝   ╚═╝    ╚═════╝ ╚═╝  ╚═╝

Turn any image into ASCII art. Headless Vue 3 front-end for your system's ASCII conversion binaries.


What It Does

ASCIInator is a local-first GUI wrapper around the ASCII conversion tools already on your system. Drop an image in, pick your tool, tune the flags, get plain-text ASCII out. No cloud, no SaaS, no telemetry — just your binaries, a thin Fastify bridge, and a Vue 3 interface.

Built as a test bed for Neovim IDE v2.1.x.


Supported Converters

Tool Notes
chafa Default. Best quality, full flag exposure
jp2a JPEG-focused, classic output
ascii-image-converter Braille support, good for fine detail
img2txt libcaca-based, multiple output formats

All tools must be installed on your system. ASCIInator does not install them for you.


Stack

Layer Tech
Frontend Vue 3 + Vite
Styling Tailwind CSS (no component lib)
API server Fastify
Shell invocation execa
Image processing ImageMagick v7 (magick)

Architecture

┌─────────────────────────────────────────┐
│              Vue 3 Frontend             │
│                                         │
│  ┌─────────────┐   ┌─────────────────┐  │
│  │ ImageInput  │   │  ToolSelector   │  │
│  │             │   │                 │  │
│  │ • Upload    │   │ • chafa         │  │
│  │ • Paste     │   │ • jp2a          │  │
│  │ • Drag-drop │   │ • ascii-i-c     │  │
│  └──────┬──────┘   │ • img2txt       │  │
│         │          └────────┬────────┘  │
│         └────────┬──────────┘           │
│                  ▼                      │
│          ┌───────────────┐              │
│          │  ShellBridge  │ (renderless) │
│          └───────┬───────┘              │
│                  │ POST /convert        │
└──────────────────┼──────────────────────┘
                   │
┌──────────────────┼──────────────────────┐
│    Fastify :3050 │                       │
│                  ▼                      │
│   ImageMagick preprocessing             │
│        ↓                                │
│   execa → binary                        │
│        ↓                                │
│   stdout → response                     │
└─────────────────────────────────────────┘
                   │
┌──────────────────┼──────────────────────┐
│              Vue 3 Frontend             │
│                                         │
│  ┌────────────────────┐  ┌───────────┐  │
│  │   OutputDisplay    │  │ ErrorLog  │  │
│  │                    │  │           │  │
│  │  <pre> ASCII art   │  │ stderr    │  │
│  │  copy / download   │  │ warnings  │  │
│  └────────────────────┘  └───────────┘  │
└─────────────────────────────────────────┘

Prerequisites

System binaries (install via your package manager):

# macOS
brew install chafa jp2a libcaca imagemagick
brew install ascii-image-converter

# Debian/Ubuntu
apt install chafa jp2a caca-utils imagemagick
# ascii-image-converter: see https://github.com/TheZoraiz/ascii-image-converter

# Arch
pacman -S chafa jp2a libcaca imagemagick
yay -S ascii-image-converter   # AUR

Node — v20.19+ or v22.12+ required
Vite — installed via npm


Installation

git clone <repo-url>
cd asciinator
npm install

IDE Setup

Neovim (primary — this is a Neovim v2.1.x test bed):

  • Volar LSP in Takeover mode (disable tsserver for .vue files)
  • tailwindcss-language-server for class intellisense
  • eslint-lsp + prettier for format on save
  • See CLAUDE.md §7 for the full Neovim config checklist

Browser DevTools:


Running

You need two terminals (or one split — you're using Neovim, you know the drill).

# Terminal 1 — Fastify API server
node server/index.js

# Terminal 2 — Vite dev server
npm run dev
Service URL
Vue app http://localhost:5173
Fastify API http://localhost:3050

Project Structure

asciinator/
├── CLAUDE.md               ← Full spec for Claude Code
├── README.md               ← You are here
├── index.html
├── vite.config.js
├── tailwind.config.js
├── src/
│   ├── main.js
│   ├── App.vue
│   ├── assets/
│   │   └── main.css
│   └── components/
│       ├── ImageInput.vue      ← Upload / paste / drag-drop
│       ├── ToolSelector.vue    ← Tool picker + flag controls
│       ├── ShellBridge.vue     ← GUI state → API call (renderless)
│       ├── OutputDisplay.vue   ← Plain-text ASCII result
│       ├── ErrorLog.vue        ← stderr / error surface
│       └── options/
│           ├── ChafaOptions.vue
│           ├── Jp2aOptions.vue
│           ├── AsciiOptions.vue
│           └── ImgTxtOptions.vue
└── server/
    ├── index.js
    ├── routes/
    │   └── convert.js          ← POST /convert handler
    └── lib/
        ├── imagemagick.js      ← Pre/post processing
        └── converters.js       ← Per-tool execa invocations

npm Scripts

npm run dev          # Vite dev server (HMR)
npm run build        # Production build
npm run preview      # Preview production build
npm run server       # Fastify API server
npm run server:dev   # Fastify with --watch (auto-restart)
npm run lint         # oxlint + ESLint (with autofix)
npm run format       # Prettier
npm run test:unit    # Vitest unit tests
npm run test:e2e     # Playwright end-to-end tests

For e2e tests, build first if running on CI:

npm run build
npm run test:e2e
npm run test:e2e -- --project=chromium   # Chromium only
npm run test:e2e -- --debug              # Debug mode

API

POST /convert

Requestmultipart/form-data

Field Type Description
image file Image file to convert
tool string chafa | jp2a | ascii-image-converter | img2txt
flags JSON string Tool-specific flags object

Responsetext/plain — raw ASCII output on success, stderr on 422.

curl example:

curl -s -X POST http://localhost:3050/convert \
  -F "image=@/path/to/photo.jpg" \
  -F "tool=chafa" \
  -F 'flags={"width":"80","colors":"256"}'

Flag Reference

All flags are optional. Omitting a flag lets the binary use its own default.

chafa

Flag Type Values Description
width integer e.g. 80 Output width in characters (combined into --size=WxH)
height integer e.g. 40 Output height in characters (combined into --size=WxH)
colors enum none 2 8 16/8 16 240 256 full Color depth
symbols string e.g. block+border+extra Symbol sets to use
dither enum none ordered diffusion noise Dithering algorithm
threshold float 0.01.0 Alpha threshold
font-ratio float e.g. 0.5 Terminal font width/height ratio

jp2a

Flag Type Values Description
width integer e.g. 80 Output width in characters
height integer e.g. 40 Output height in characters
background enum light dark Assumed terminal background
chars string e.g. .:-=+*#%@ Character ramp to use

ascii-image-converter

Flag Type Values Description
width integer e.g. 80 Output width in characters
height integer e.g. 40 Output height in characters
color boolean true Emit ANSI color codes
braille boolean true Use braille dot patterns
threshold integer 0255 Brightness threshold

img2txt

Flag Type Values Description
width integer e.g. 80 Output width in characters
height integer e.g. 40 Output height in characters
format enum ansi utf8 html Output format
dither string e.g. fstein Dithering mode
gamma float e.g. 1.0 Gamma correction

Troubleshooting

command not found: chafa (or jp2a, img2txt, ascii-image-converter)
The binary isn't on PATH. Install it via your package manager — see Prerequisites above.

convert: command not found
ImageMagick isn't installed. It's required for all conversions regardless of tool.

CORS error in the browser console
The Fastify server isn't running, or it's on a different port. Start it with npm run server and confirm it logs Server listening at http://127.0.0.1:3050.

422 from the server
The binary returned a non-zero exit code. The full stderr is in the response body and shown in the ErrorLog panel.

Blank or truncated output
Some tools default to terminal width detection which may return 0 in a non-TTY context. Set an explicit --width flag.


Design

  • Always dark — light mode not wired (planned)
  • No component library — raw Tailwind only
  • Monospace output: JetBrains Mono
  • UI font: IBM Plex Sans
  • Accent: #39ff14 (neon green — because ASCII)

Neovim v2 Test Bed

This project exists partly to stress-test the Neovim IDE v2.1.x setup across a real Vue 3 + JS project. See CLAUDE.md §7 for the full test checklist covering Volar, Tailwind LSP, ESLint, DAP, and more.


License

MIT