Bashful gives your CLI tools a REST API — no code required.
The name is a double meaning: it wraps bashful tools (tools that only speak shell), and it does so quietly, without you having to write a single line of server code. You hand it a command name, and Bashful reads the --help output, figures out the flags, and instantly serves a REST API and a browser UI you can poke at.
Think of it as a shy CLI tool finding its voice over HTTP.
Most command-line tools are only accessible from a terminal. Bashful bridges that gap:
- Reads the tool's
--helpoutput at startup. - Parses every flag — short (
-s), long (--silent), typed (--output <file>), and boolean — into a JSON schema. - Serves a local REST API where each JSON key maps back to a CLI flag.
- Executes the real command when you POST to the endpoint, streaming the output back as plain text.
- Shows a browser UI (Swagger-style) auto-generated from the parsed schema so you can fill in flags and run commands without touching a terminal.
No config files. No code. Starts in milliseconds.
- Bun v1.0+
Install on Linux/macOS:
curl -fsSL https://bun.sh/install | bashInstall on Windows:
powershell -c "irm bun.sh/install.ps1 | iex"1. Install dependencies:
bun install2. Start Bashful wrapping your CLI tool (e.g., curl):
bun run bashful.ts curl3. Explore the dynamic Swagger-like Web UI: Open http://localhost:3000 in your browser to view the auto-generated dashboard where you can interactively run commands.
4. Or interact with the auto-generated endpoints directly:
-
Get the parsed flag schema:
curl http://localhost:3000/curl/schema
-
Execute
curlover HTTP:curl -X POST http://localhost:3000/curl \ -H "Content-Type: application/json" \ -d '{"silent": true, "output": "example.html", "_args": ["http://example.com"]}'
Tip
The POST above translates dynamically to the native CLI invocation:
curl --silent --output example.html http://example.com
Use \| to wrap several tools at once. Each gets its own endpoint and a tab in the UI:
bun run bashful.ts curl \| wget \| pingEndpoints created:
POST /curl— execute curlPOST /wget— execute wgetPOST /ping— execute pingGET /<cmd>/schema— parsed flag schema for each
Direct mode — Bashful appends --help automatically:
bun run bashful.ts curlPipe mode — provide the exact help command yourself (useful when --help fails or outputs to stderr):
bun run bashful.ts curl --help
bun run bashful.ts git log --helpBoth modes can be mixed when using \|:
bun run bashful.ts curl --help \| wget| Payload key | CLI result |
|---|---|
_args: ["http://example.com"] |
positional args, prepended before flags |
"silent": true |
--silent |
"output": "file.html" |
--output file.html |
"v": true |
-v (single-char keys become short flags) |
"silent": false |
(omitted) |
Pass --debug anywhere before the command to log startup time, parsed flag counts, and each execution:
bun run bashful.ts --debug curl \| wgetbun testTests cover the three pure functions at the core of Bashful: splitSegments (arg parsing), parseSchema (regex-based help text parsing), and buildCLIArgs (payload → CLI translation).
Everything lives in a single file: bashful.ts.
splitSegments(args)— splits CLI args on|into per-command segments.parseSchema(helpText)— the "Bashful Regex" extracts short flags, long flags, value types (<val>,[val],ALL_CAPS), and descriptions into a keyed schema object.buildCLIArgs(payload, schema)— translates a JSON payload back into a flat CLI argument array.- Server —
Bun.serveon port 3000. Routes:GET /(UI),GET /<cmd>/schema,POST /<cmd>. - Execution —
Bun.spawnruns the real command and streams stdout directly as the HTTP response.
MIT © Peter Isberg

