Open-source project
ciembor/4bit avatar
ciembor/4bit

4bit: a terminal colour scheme designer that exports for a dozen emulators

Terminal Color Scheme Designer

1,058 stars194 forksJavaScriptGPL-3.0

At a glance

What is it?
4bit is a browser-based designer for terminal colour schemes that generates configuration files for a long list of emulators, from XTerm and iTerm2 to Windows Terminal and Alacritty. The judgement is that its per-terminal export layer is the real product, and that the leftover jQuery colour wheel is a visible seam in an otherwise modern Vue application.
Who is it for?
4bit fits a user who has settled on a palette idea and wants a correctly formatted file for a specific emulator, especially on the terminals with awkward formats such as ConEmu, KiTTY or Terminator where hand-editing is error prone.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 32 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A browser app, not a terminal palette

4bit is a terminal colour scheme designer that runs entirely in a browser, with the live site hosted at `ciembor.github.io/4bit`. The user flow is three steps: open the site, design the terminal look, then click the `Download Scheme` button and pick the format of configuration file you want.

That last step is the whole product in miniature. A terminal colour scheme is not a portable file format. It is a dozen different file formats that happen to describe the same sixteen colours, and getting each one right is the tedious part that most palette designers push onto users. The list of supported targets runs from ATerm, Urxvt, Rxvt and XTerm through Gnome Terminal, Guake, XFCE4 Terminal, Konsole, Yakuake, iTerm2, macOS Terminal.app, PuTTY, KiTTY, ConEmu, Terminator, Termite, Alacritty, Mintty and Windows Terminal.

A project homepage exists at `ciembor.github.io/4bit`, the repository is at `github.com/ciembor/4bit`, and the licence is GPL v3 with the `LICENSE.md` file in the repository. The last push was on 2026-09-21 and the repository is not archived.

The tool is for a person who has a colour vision in mind and wants it applied consistently across several terminals, since a palette that works in iTerm2 does not translate for free into a Konsole colour scheme or a PuTTY registry file. The application stores the design in the URL so a scheme can be shared as a link, which is why there is a `src/infrastructure/url` layer in the codebase at all.

Seven directories separate the rules from the presentation

The project structure is the clearest description of the architecture, and it is a deliberate layering.

`src/domain` holds pure scheme rules, defaults, colour naming and colour-mode logic. `src/application` is the synchronisation and use-case layer that applies domain logic to app state. `src/infrastructure/url` covers URL and query codecs, share URL builders and URL-only scheme settings formats. `src/infrastructure/serialization` holds the terminal export serializers. `src/infrastructure/browser` deals with browser URL and storage synchronisation. `src/infrastructure/vendor` wraps the remaining legacy vendor code. And `src/presentation` contains the Vue components, Pinia stores, fonts and styles.

The dependency direction is the point. Colour rules and defaults are pure and have no knowledge of the DOM or the export formats. The export serializers live in infrastructure, and the Vue components in presentation never compute a colour mapping themselves.

The legacy part is the Advanced view's colour wheel, which the documentation is upfront about: most of the UI is now regular Vue components, while the colour wheel in `Advanced` is wrapped in Vue but still powered by the old jQuery plugin. The `jquery` and `jquery-ui` packages are still in the dependency list at version 4.0.0 and 1.14.2. Wrapping a jQuery widget in Vue means the two worlds coexist, which works but is exactly the kind of seam that makes the codebase harder to change than a pure rewrite would be.

The runtime dependencies are small and tell you what the app actually does. `@xterm/xterm` at 6.0.0 renders the live preview, `color` at 5.0.3 handles colour space conversions, `pinia` at 3.0.4 is the store, and `vue` is at 3.5.33.

Where each terminal expects its file to live

The install instructions are per terminal, and they differ in more than file format. The path matters as much as the content.

For the libXt family, ATerm, Urxvt, Rxvt and XTerm, the generated text goes into `~/.Xresources` and you run `xrdb ~/.Xresources` to apply it. For Gnome Terminal and Guake, you save the generated script as `set_colors.sh`, make it executable with `chmod +x set_colors.sh` and run it; the Gnome Terminal script updates the default profile through `gsettings` and `dconf`, while Guake uses its own `dconf` keys.

For XFCE4 Terminal, the file goes to `~/.local/share/xfce4/terminal/colorschemes/4bit.scheme` and is chosen in terminal preferences. Konsole and Yakuake take the generated file into `~/.kde/share/apps/konsole/NAME-OF-SCHEME.colorscheme` and need the terminal restarted. Alacritty takes the file to `~/.config/alacritty/alacritty.yml`.

The macOS terminals differ. iTerm2 wants a file `~/NAME-OF-SCHEME.itermcolors` with the generated XML content, loaded through the `Load Presets...` button under iTerm2 preferences for your profile. Terminal.app wants you to open the generated `.terminal` file and then manage it under Terminal, Settings, Profiles.

Windows has two paths. PuTTY wants the generated file saved with a `.reg` extension and double clicked. ConEmu wants the generated XML pasted into `%APPDATA%\ConEmu.xml` under the `<key name="Colors"...>` node, and if you add it as a new palette you need to rename `Palette1` and update the `<value name="Count"...>` value to match the palette count, then reload the settings.

Windows Terminal takes the generated JSON object into the `schemes` array in `settings.json`, after which you select `4bit` as the profile colour scheme. KiTTY is copy-and-paste of the `Colour0` through `Colour21` lines into a portable session file, Terminator wants the lines from the `[profiles]` section pasted into `~/.config/terminator/config`, Termite wants the `[colors]` section pasted into its config, and Mintty wants the colours saved in `~/.minttyrc`.

Adding an export format is a six-step checklist

The documentation includes a contributor guide for adding a new terminal export, and it is specific enough to be worth following exactly, because the download dialog is data-driven.

You add a serializer in `src/infrastructure/serialization/scheme-exports/`, following the existing `serialize...` functions there. You reuse helpers from `shared.js` in the same directory when the target format maps the standard sixteen-colour palette, the foreground or the background. You register the serializer in `src/infrastructure/serialization/scheme-exporters.js`, adding it to `EXPORT_BUILDERS` and then adding a matching entry to `SCHEME_DOWNLOADS` with `id`, `buttonId`, `text`, `linkLabel`, `downloadName` and `mimeType`. You update the user-facing list in the For users section of the README with short installation instructions. You extend `tests/infrastructure/serialization/scheme-exporters.test.js`, keeping the generic all-formats-build-a-blob coverage and adding at least one format-specific assertion that checks the actual output structure or colour mapping. And you verify locally with `npm test`, `npm run build` and, if you touched test scope or reporting, `npm run test:coverage`.

The key detail is the last one. The download dialog reads `SCHEME_DOWNLOADS` directly, so a newly registered export appears automatically without extra UI work, and the required test is not just that a blob gets produced but that the structure of the output is right. A terminal format that produces a blob full of wrong keys is a silent failure, and the format-specific assertion is what catches it.

The shared helpers are the other lever. Because many terminals map the same sixteen ANSI colours, a new format is often a small adapter over the shared mapping rather than new logic, which is why the guide tells you to reuse `shared.js` when the target maps the standard palette.

Node 24, Vitest, Playwright and a coverage badge

The build and test setup is modern and specific. The `engines` block requires Node `^24.0.0`, and the documentation points to `.nvmrc` for the exact version, `24.15.0`, to use before installing dependencies or running local checks.

The command list is the fastest way to understand the workflow:

bash
npm install
npm run dev
npm run build
npm run preview
npm test
npm run test:coverage
npm run test:e2e
npm run test:e2e:install
npm run coverage:badge
npm run lint

The scripts in `package.json` confirm what each does. `dev` and `build` are Vite, `test` is `vitest run --pool=threads`, and `test:coverage` adds the v8 coverage provider. The E2E tests are Playwright, with `test:e2e:install` running `playwright install chromium`, and there are headed and UI variants for interactive debugging. Lint is `eslint src --fix`.

The Playwright setup has a detail worth knowing. The config starts Vite automatically on `127.0.0.1:4173`, and if the bundled browser causes local problems you can use an installed browser instead with `PLAYWRIGHT_CHANNEL=chrome npm run test:e2e`. The E2E tests live in `tests/e2e`, and the current smoke coverage focuses on URL hydration, advanced option changes, share links and the download dialog. Those four areas are exactly the ones where a refactor would silently break a shareable URL or a download.

Coverage is measured for `src/**/*.js`, and the reports are written as HTML, LCOV and a JSON summary into `coverage/`. The badge in the README is generated from the line coverage in `coverage/coverage-summary.json` by `npm run coverage:badge`, so the 95.27 percent shown is regenerated by the script rather than typed by hand.

Deployment is also automated: GitHub Pages deployments run from GitHub Actions after `npm test` and `npm run build` pass on `master`.

No releases, a GPL licence and a pure-rules core

The repository has no GitHub releases, so there is no tagged version to pin and no changelog of tagged builds to diff against, though a `CHANGELOG.md` file exists in the repository root. The last push was on 2026-09-21, so the code is being worked on. If you rely on 4bit, the practical consequence is that you track the `master` branch or the deployed site rather than a version, which for a browser tool hosted on GitHub Pages is a mild concern but a real one for anyone embedding the exports in a build pipeline.

The licence is GPL v3, with the text in `LICENSE.md`. For a tool whose output is configuration files that people paste into their own dotfiles, the licence matters less for the output than for the code, and GPL v3 imposes no obligation on a user's generated scheme files. This is a licensing observation rather than legal advice, and the `LICENSE.md` file governs.

The architecture choice that deserves the most credit is the `src/domain` boundary. Colour naming, defaults and colour-mode logic are kept pure, and the export layer is a separate concern in `src/infrastructure/serialization`. That split is what makes the six-step checklist for adding a terminal workable, and it is what would let the project change its export targets without touching the rules that decide what a colour should be called or how a palette mode behaves.

The weakness is the same repository's other side. The colour wheel in the Advanced view is still the old jQuery plugin, and jQuery 4 with jQuery UI 1.14 sits in the dependency list for the sake of one control. It works, and the documentation is honest about it, but it means a future maintainer inherits a Vue application with a jQuery island in it, and the jQuery UI package in particular is the kind of dependency that ages badly.

Editorial conclusion

4bit fits a user who has settled on a palette idea and wants a correctly formatted file for a specific emulator, especially on the terminals with awkward formats such as ConEmu, KiTTY or Terminator where hand-editing is error prone. It does not fit someone who wants a theme manager that watches a config directory and reapplies schemes, since the tool produces files and stops there, and it does not fit a maintainer who wants a clean modern codebase, because the colour wheel in the Advanced view still runs on the old jQuery plugin. Verify first that your terminal appears in the For users list with a matching export format, that the generated file lands where your terminal actually reads it, for example `~/.config/alacritty/alacritty.yml` or the `schemes` array in Windows Terminal `settings.json`, and that the colours you expect in the preview survive the export mapping for that format.

Frequently asked questions

How do I use 4bit to design a terminal color scheme?

Open the live site at `ciembor.github.io/4bit`, design the terminal look, then click the `Download Scheme` button and select the format of configuration file you need. The scheme is also encoded in the URL, so a design can be shared as a link.

Which terminals can 4bit export a color scheme for?

The documented list includes ATerm, Urxvt, Rxvt, XTerm, Gnome Terminal, Guake, XFCE4 Terminal, Konsole, Yakuake, iTerm2, macOS Terminal.app, PuTTY, KiTTY, ConEmu, Terminator, Termite, Alacritty, Mintty and Windows Terminal, with a fallback of copying hex values into your own terminal's configuration.

Where do I put the 4bit generated file for Alacritty and Windows Terminal?

For Alacritty, the generated file goes to `~/.config/alacritty/alacritty.yml`. For Windows Terminal, you copy the generated JSON object into the `schemes` array in `settings.json` and then select `4bit` as the profile color scheme.

How do I add support for a new terminal in 4bit?

Add a serializer under `src/infrastructure/serialization/scheme-exports/`, reuse the helpers in `shared.js` where possible, register it in `scheme-exporters.js` by adding to `EXPORT_BUILDERS` and a matching `SCHEME_DOWNLOADS` entry, update the README's For users list, and extend the serializer test with at least one format-specific assertion. The download dialog reads `SCHEME_DOWNLOADS` directly, so the new export appears without extra UI work.

What do I need to run 4bit locally?

Node `24.15.0` as pinned in `.nvmrc`, then `npm install` and `npm run dev` for the Vite dev server. The checks are `npm test` for the Vitest suite, `npm run test:coverage` for coverage reports, and `npm run test:e2e` for the Playwright browser tests, with `npm run test:e2e:install` to fetch Chromium.

Official sources

  1. ciembor/4bit on GitHub
  2. Issues
  3. License: GPL-3.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ciembor-4bit.svg)](https://hysenlabs.com/projects/ciembor-4bit)

Was this useful?