I built Inklin because I wanted a better terminal styling experience for Node.js
When working on CLI tools, I kept running into the same limitations with existing styling libraries.
They were good—but once you start building more complex terminal output, a few problems start to show up:
- nested styles don’t behave predictably
- module system support can get messy (ESM vs CommonJS)
- some libraries feel heavier than they should for simple styling
So I built Inklin.
It’s a small terminal styling utility for Node.js that focuses on predictable behavior, modern module support, and minimal overhead.
What Inklin does
Inklin is not trying to replace everything—it’s focused on a few specific improvements.
- Smart style nesting
Most terminal styling libraries reset styles when a nested style ends.
That creates unexpected output when combining styles.
Inklin instead tracks a style stack, so parent styles are restored automatically.
Example idea:
red("Error: " + blue("file not found"))
After blue() ends, the output correctly returns to red() instead of resetting to default.
This makes deeply nested styling more predictable in real CLI output.
- ESM + CommonJS support out of the box
One of the most annoying parts of modern Node.js libraries is module compatibility.
Inklin works in both environments without extra setup:
- ESM (import)
- CommonJS (require)
No dual package confusion, no build hacks required for basic usage.
- Modern terminal features
Inklin includes support for:
- Truecolor (HEX and RGB)
- OSC 8 hyperlinks (clickable terminal links)
These are useful for modern CLI tools where terminals are no longer just plain text environments.
- Lightweight core (~3KB)
The goal was to keep the core small and predictable.
No large dependency tree, no unnecessary abstractions.
How it works internally
Under the hood, Inklin uses a lazy Proxy-based chaining system.
Instead of eagerly computing styles, it builds them dynamically when accessed.
This allows:
- flexible chaining APIs
- minimal runtime overhead
- consistent output behavior
It also uses a recursive structure to manage style composition, which helps keep nesting behavior consistent.
Example usage
import inklin from "inklin";
console.log(
inklin.red.bold("Error:") + " something went wrong"
);
Or chain-style:
inklin.bold.blue("Hello world").log();
Why I built it
The goal wasn’t to reinvent terminal styling.
It was to explore a simpler, more predictable API for CLI output while avoiding some of the edge-case issues I kept running into in real projects.
Especially around:
- nested styling behavior
- module compatibility friction
- lightweight CLI design
Repo
https://github.com/sapirrior/inklin
Feedback welcome
I’d especially appreciate feedback on:
- API design (is chaining intuitive enough?)
- edge cases in nested styling
- performance considerations for CLI-heavy use cases