Relive the digital paper dolls of the 1990s on modern systems!

QKiSS

An unsolicited renaissance of KiSS

QKiSS is a modern implementation of KiSS viewer in Qt 6, compatible with KISS/GS and FKiSS 1 & 2 specifications.

Free software under GPLv3 · Linux · Windows · Mac

What is KiSS?

KiSS (Kisekae Set System) is a format of digital paper dolls. You dress the characters up by dragging their clothes with the mouse, and FKiSS scripts add interactions such as animations and sounds.

“Kisekae” comes from the Japanese word “着せ替え人形” (pronunciation: “kisekae ningyou”), meaning “dress-up dolls”.

KiSS originated from Japanese otaku subculture and personal computer enthusiasts community (particularly those using the NEC PC-9800 series) in the 1990s, and gained popularity throughout the 1990s and early 2000s.

Why QKiSS?

KiSS is full of the fascinating creative passion of the nijigen doujin communities: the 8-bit (or even lower) pixel aesthetics, full of the flavor of 1990s personal computers, that they showed off as best they could within the hardware limits of the computers of that time, all kinds of anime memes from the Japanese nijigen doujin communities, and wildly imaginative, bizarre ideas and humor. Many artists' outfit designs really have great taste, too: just looking at them puts me in a good mood.

This stinky otaku first heard of KiSS*1 around 2007, from often seeing the eye-catching, weird name “GnomeKiSS” while poking around in Synaptic on Ubuntu. But at the time, I had no idea how to use it. It was only around 2012 that I looked into it and figured out what KiSS was. Even though KiSS was already in decline by then, its Japanese anime characters and pretty outfits, its anime memes, and the memories of the pixel aesthetics of the Windows 95/98 era still kept me playing with GnomeKiSS for a long time.

But in 2024, when I felt like revisiting those KiSS sets for a while, I found that the native KiSS viewers that Linux had at the time had all stopped working: fkiss can still be built but no longer runs, and GnomeKiSS depends on outdated GNOME 2 libraries that most distributions no longer ship. So I thought: why not write one myself? And if I was going to make one, it absolutely had to run natively on Linux, with a UI/UX that I was happy with; it would also be a chance to practice writing a somewhat sizable project in Qt / C++. So I started building QKiSS, a brand-new KiSS viewer, from scratch in Qt / C++, while chewing through the KISS/GS specification.

And writing it really is a lot of fun: first understanding KISS/GS's own palette and bitmap formats, so that the images show up correctly, then implementing a parser and an interpreter of the FKiSS script language from its specification, so that things start to move. Since the formats are so old, you also run into lots of things that a modern developer like me never thought of (for example, the old Mac OS used \r for line breaks). The fun of writing all this has long since surpassed the KiSS sets themselves.

This project comes from nostalgia for the Windows 95/98 and GTK+ 2 era. After all, life is frightening enough as it is; the real world is a hot mess, while nijigen and isekai remain a pure promised land.

Verily, verily, I say unto you: ye shall consider nijigen and isekai. Anime.

*1 Strictly speaking, I had played with PalmKiss on Palm OS even earlier. But that implementation was rather awkward: it could not load LZH files by itself, and had only one KiSS set built into the program. I had no idea that KiSS was actually such a huge community; I just thought that Palm OS app had a screw loose to be called such a weird name.

Highlights

  • Full-featured, with a handy UI

    • Switch files quickly from the side panels: the sets in your folders, and the CNF files inside an archive.
    • Read the CNF, with syntax highlighting.
    • Read the docs bundled with a set.
    • Read CNF files and docs written in Shift-JIS, with no garbled text.
    • Observe objects: point at any part of a doll to see its cel, object and position.
    • Check the log, which points out problems down to the line.
  • Faithful to the specs, faithful to the users

    • Implements the KISS/GS base specification, and an interpreter for the interactive scripts of FKiSS 1 & 2 (in tests, 90% of Japanese KiSS sets run fine).
    • FKiSS 3 & 4 have too few sets, almost none of them by Japanese KiSS artists, so they were not worth the bother.
    • One-click unfix: who wants to sit there clicking a fixed item over and over? Playing shouldn't feel like work.
    • Supports all three major OSes at once, Linux, Windows and macOS, to preserve biodiversity and the balance of the ecosystem.
    • No Electron.
  • The romance of engineering and aesthetics

    • The code of the main program is over 85% typed by human hands*1 *2 (and is probably the author's last hand-written software project, so cherish it while it lasts).
    • Linux is no longer a second-class citizen (Windows is. As for macOS, it is a third-class citizen because I have no Mac to test on).
    • Open source and automated builds make sure I didn't sneak anything naughty in*3.
    • Tango-style UI icons take you back to the 2000s.
    • A built-in CRT monitor simulation takes you back, as in a dream, to the 1990s, when monitors needed screensavers and pixels were not quite sharp.
    • An AppArmor profile for tinfoil-hat security nerds.
    • Built with Qt 6 / C++ 20, without caring about old systems.

*1 The use of LLMs in each area of this project is disclosed in Q&A. For example, the HTML / CSS / JS of this website was left entirely to an LLM agent, because I have no interest in spending the weekend hours of my life writing web pages anymore; I am a dog kept by OpenAI and Anthropic. Woof woof.

*2 These days, boasting that code was typed by human hands on a keyboard doesn't mean its quality is necessarily higher than what an LLM produces. But in this code, you can feel the sopping-wet hand sweat and the pleasant body heat passed from human palms to the keyboard, and the otaku stench the author gives off, which you can smell even through the screen.

*3 Force majeure, such as supply chain attacks (for example, the incidents of XZ Utils, or of tj-actions/changed-files on GitHub Actions), is not covered.

Screenshots

Download

GitHub Releases

Linux

Packages automatically built by the Open Build Service (OBS) and digitally signed with GPG*1, for these distributions:

  • Arch Linux
  • Debian
  • Fedora
  • openSUSE
  • Ubuntu

If your distribution is not one of these, there is also an AppImage: a single file that runs without installing*2, but only on x86_64, and your Linux distribution must have glibc 2.39 or later. Unlike the packages above, it is automatically built and digitally signed by GitHub Actions*3, not by OBS, so it has no GPG signature from OBS. Note: if you care a lot about security, it is better to install QKiSS through OBS*4.

Windows

A portable ZIP and an installer, supporting Windows 10 version 1809 and later. It is automatically built and digitally signed by GitHub Actions*5.

macOS

A Universal disk image for both Apple silicon and Intel Macs, supporting macOS 13 and later. It is automatically built and digitally signed by GitHub Actions*6.

All binaries are currently tested only on x86_64.

*1 The private key is generated inside the OBS server. The fingerprint of its public key is shown on this OBS page.

*2 An AppImage mounts itself with FUSE to run. Older AppImages needed libfuse2, which many distributions no longer install, so they often stopped with “AppImages require FUSE to run”. The AppImage of QKiSS has the FUSE library built in, so it does not need libfuse2: it only needs fusermount3 or fusermount, which most desktop distributions install. If FUSE still does not work on your system (for example, in a container), run ./qkiss-VERSION-linux-x86_64.AppImage --appimage-extract-and-run: it first extracts its files into a temporary folder, and runs QKiSS from there. See also the AppImage documentation.

*3 This signature is a GitHub artifact attestation: it proves that GitHub Actions built the AppImage from the source code of this repository. To check a downloaded file, run gh attestation verify FILE -R kuanyui/qkiss (GitHub CLI). But unlike the packages of OBS, it has no GPG signature that your package manager checks, and it does not update itself: to update QKiSS, download the AppImage of the new version of QKiSS yourself.

*4 The AppImage has two weak points for security. First, the optional AppArmor profile (the qkiss-apparmor package) only knows QKiSS installed as /usr/bin/qkiss, so it does not cover the AppImage. Second, the libraries inside the AppImage (such as Qt, FFmpeg and libarchive) do not get the security updates of your distribution: they are updated only with a new version of QKiSS. But the Landlock and seccomp sandbox used when extracting LZH files works in the AppImage too.

*5 This signature is a GitHub artifact attestation: it proves that GitHub Actions built the Windows files and the source tarball from the source code of this repository. To check a downloaded file, run gh attestation verify FILE -R kuanyui/qkiss (GitHub CLI). It is not a signature inside the Windows executables themselves (Authenticode), so Windows still shows a warning the first time you run them.

*6 This signature is a GitHub artifact attestation: it proves that GitHub Actions built the disk image from the source code of this repository. To check a downloaded file, run gh attestation verify FILE -R kuanyui/qkiss (GitHub CLI). But the app itself is signed only ad hoc, without an Apple Developer ID certificate, and is not notarized by Apple. So the first time you open it, macOS refuses to open it. Then close that message, go to System Settings › Privacy & Security, scroll down to QKiSS, click “Open Anyway”, and confirm. You need to do this only once, but you will need to do it again after each update of QKiSS. See also Apple's guide.

Q&A

Which versions of FKiSS does QKiSS support?

That is quite enough to load nearly all the Japanese KiSS sets I could find on the Internet.

But I deliberately decided not to implement the shell() command, to avoid unnecessary security holes. (I don't think I've ever seen a KiSS set that uses it, either.)

Why the name “QKiSS”?

A KiSS viewer implemented in Qt 6. Having “KiSS” in the name is a convention of KiSS viewers, like fkiss, GnomeKiSS, KISSLD, and Direct KiSS.

I also considered a few other names:

  • QtKISS: pronounced the same as “Cute Kiss”, and named with the same logic as GnomeKiSS: “platform name + KiSS”. Well, actually, QKiSS had this name in the early days of development. But according to the fair use rules of the Qt trademark, the Qt name may only be used “where the Qt name is not being used in a way which suggests sponsorship or endorsement of the product”. To avoid someone giving me crap about it someday, I had to rename it.
  • Qute KISS: also pronounced “Cute Kiss”, but argh… Qute is a trademark of a Japanese computer game company. Too risky.
Where can I find KiSS sets to open?

The biggest archive right now is probably Otaku World, though you have to dig through it patiently. It has sets by both Japanese and Western artists.

Some people have also written their own implementations, such as one in JavaScript or one in Haskell, with online demos you can open right in your browser. But most of the sample sets they provide were dug up from Otaku World, too.

Note that these KiSS sets may contain NSFW content, and I can't make any guarantees.

What security measures are there for the LZH format and external programs such as lha?

LZH / LHA is a free compression format and tool, developed in 1988 by Haruyasu Yoshizaki, a Japanese physician. It was very popular in the Japanese personal computer scene of the time (by comparison, PKZIP, the ZIP tool that later became the mainstream, did not appear until 1989, and was shareware), so the KiSS developer community, which originated in Japan, naturally adopted LZH to compress KiSS sets.

But today, both the format and its implementations are old, and lha and unar extract LZH files of unknown origin, which makes them the easiest target for a malicious file. So on Linux, QKiSS locks them up:

  • Landlock: they can read only the system files and the archive being opened, nothing else in your home folder, and they can write nowhere except unar's temporary folder.
  • seccomp: high-risk system calls such as io_uring, sockets and namespaces are turned off.
  • AppArmor (the optional qkiss-apparmor package, Debian / Ubuntu / openSUSE only): lha and unar are restricted once more, and QKiSS itself cannot read secrets such as ~/.ssh, nor write files used for persistent attacks, such as ~/.bashrc.

Landlock and seccomp are built into QKiSS, with nothing to install, but they cover only these two external programs, not QKiSS itself.

As for Windows: as Eisen once said, anyone who uses Windows is a brave warrior, and needs none of these little tricks.

As for the App Sandbox of macOS, I have given up on it for now. I believe Himmel the Hero, who, like me, never bought a Mac nor subscribed to the Apple Developer Program, would have done the same.

Why is only AppArmor supported? Is there no SELinux support?

It doesn't fit the use case. SELinux's security model is inherently bad at “deny access to a few folders such as ~/.config/autostart, and allow access to everything else”, and I can't force users to put their KiSS LZH files only into some hardcoded ~/qkiss folder.

Besides, on the Linux desktop, people who deliberately run GUI apps outside unconfined_t must be rare. Such people either work at the Pentagon*1, or moved to Qubes OS long ago.

But even if you use SELinux, you still have the protection of Landlock and seccomp, which covers only the extraction by the two external programs, lha and unar.

*1 Generally speaking, playing any kind of KiSS viewer in the workplace is not recommended.

Why does Windows say “Unknown publisher” when I start QKiSS?

Because I didn't buy a code signing certificate from Microsoft.

A “signature” (or digital signature) is one of the uses of asymmetric cryptography: a mathematical way to prove that “something was really made by a certain person, and nobody else has changed it”. But I can't say much about it here, or this would get very long, so I only give the main points. If you want to understand it more deeply, ask an LLM.

Simply put, “buying a signature” means: I'm a developer, and once I have written my program, I pay Microsoft (or a certificate authority it trusts), they check who I am, and then they put my public key into a public certificate and issue it to me. Then I can digitally sign the compiled executables with my own private key, so that any Windows computer can use the public certificate to verify that “this executable was released by me, signed with my private key, and not by someone pretending to be me”. Indirectly, it also implies that “there is no malware hidden inside” (because once malware is found in it, they revoke the certificate, and since they have already checked who I am, the FBI can come looking for me any time).

There is no signature, but the whole compiling and building process of the software is transparent: you can check it yourself on GitHub Actions.

Also, the license of the lha bundled in the packages of this project is a bit unusual: it is not a license approved by the Open Source Initiative (OSI). So I can't apply for a free signature from the companies that offer free signing to free software projects, either.

Anyway, opening an unsigned program on Windows isn't much trouble: just a couple more clicks to confirm.

Why is the macOS icon in the Download section… a banana?

Because I don't want a Prepear incident of my own (the case record at the US Patent and Trademark Office).

Apple's official guidelines say this:

These guidelines are for Apple licensees, authorized resellers, developers, customers, and other parties wishing to use Apple’s trademarks, service marks or images in promotional, advertising, instructional, or reference materials, or on their web sites, products, labels, or packaging. […]

Authorized Use of Apple Trademarks

[…]

2. Compatibility: Developers may use Apple, Macintosh, iMac, or any other Apple word mark (but not the Apple Logo or other Apple-owned graphic symbol/logo) in a referential phrase on packaging or promotional/advertising materials to describe that the third party product is compatible with the referenced Apple product or technology, provided they comply with the following requirements. […]

Unauthorized Use of Apple Trademarks

[…]

3. Variations, Takeoffs or Abbreviations: You may not use an image of a real apple or other variation of the Apple logo for any purpose. Third parties cannot use a variation, phonetic equivalent, foreign language equivalent, takeoff, or abbreviation of an Apple trademark for any purpose. […]

Under the nominative fair use of trademark law, you may mention someone else's trademark to say that your product works with theirs, but only “as much as is reasonably necessary”. So I may only write plain text like “macOS”, because in theory that is already enough to say what it means, and I can't add an Apple icon to it. But my OCD makes me feel uncomfortable all over without a little icon for decoration, and since even images of a “real apple” are banned, I had to think of something else.

My spare time for this project is precious. I don't want to spend a single moment of my life drawing an icon by hand, only for salaried lawyers to make me take it down and redraw it for a reason like this. But I can't accept the ugly-as-sin plain “macOS” wordmark they require in its place, either. In a case like this, it's enough to let AI make a rough draft, then touch it up a little myself (any fruit will do, as long as its shape has nothing to do with an apple's, so that not even a one-year-old would be misled).

When I start QKiSS, macOS says “the developer cannot be verified”. That is a pain. Can't you do something about it?

This is also a signature problem, and it works much like the warning on Windows. I don't buy one because it means paying Apple 99 US dollars every year for the Apple Developer Program.

But first, I stopped being a Mac user long ago; second, I don't make a living from the Mac or iOS; third, I'm only developing a free software project that I like and give away at no cost, and its source code and build process are all public, right there. So I have no wish at all to spend 99 dollars every year feeding this company, which wants to control even the ways you pay.

Makima: “Do you remember what Apple did to out-of-store payments?”

Kishibe: “”

Kishibe: “”

Kishibe: “Out-of-store payments…?”

Why not Electron or Web technologies?

Although I already mentioned that this project was meant to be a “native desktop application”*1 from the start, this is a question people really do ask sometimes, so let me answer it here anyway.

I know there are some KiSS implementations which can run in a Web browser by using Web technologies directly, but they are (technically and architecturally) awkward when you want to turn them into a desktop application integrated with your OS and file system; and such a thing which actually can be done in a lightweight way should not need a browser at all.

On top of that, I would have to keep chasing Electron's breaking API changes, there's npm, a super uncontrollable thing that makes packaging a hassle and can even get poisoned, and the compatibility between Node versions and Electron versions to deal with (not to mention the versions of each distro)...., and so on and so forth. Taking all of this into account, for a small project like QKiSS, I don't believe at all that developing and maintaining it with Electron or Web technologies would cost less, and I can guarantee that I would have a miserable time developing and maintaining it.

*1 At least as far as Linux / KDE is concerned.

Why not Rust?
  • I'm a KDE user, and Qt feels the most seamless to use.
  • Qt Widgets is mature and stable: its major versions last for years, with few API breaks. I don't have to build any widgets myself, and I can get 80% of the features done with hardly any third-party libraries.
  • Rust would need a binding, and then I'd have to worry about its API breaks, its quality and its extra pitfalls, plus the Qt C++ patterns that don't translate directly into Rust. I'd have two things to keep up with, Qt and the binding, and I'd lose all the help from Qt Creator.
  • I want to practice C++.
Did you use AI (LLMs)?
  • This project does use help from LLMs, but keeps it under control as much as possible, with various engineering methods (e.g. isolating LLM agents in KVM virtual machines, the principle of least privilege, and reviewing commits by hand).
  • No damn vibe coding, ever, in the main program (Qt / C++) or in the Python code. Even with help from LLMs, the code was reviewed and modified by hand, line by line: I can understand and explain every line of it. I also proofread the translations by hand, as much as my broken foreign languages allow.

How much LLMs directly generated in each area

  • Qt / C++
    • Microsoft Copilot
    • ChatGPT
    • Claude

    Discussing design patterns, finding suitable Qt APIs, and writing some examples for difficult Qt APIs (e.g. the delegates of MVC).
    Since v0.9.3, I have used LLM agents for trivial debugging and fixes.
    The CRT simulation, though, was developed entirely by an LLM agent, because I am burned out: my passion for this project has almost burned to ashes, and I just want to finish it quickly and get it out the door.

  • Python
    • Microsoft Copilot
    • ChatGPT

    Rough scaffolds (e.g. argparse) and some snippets. Learning the latest “Pythonic” ways, and the best practices of type annotations in Python 3.

  • Translations
    • Microsoft Copilot
    • Codex
    • Claude Code

    Translating the strings in *.ts from English or Japanese into the other languages, then fixing them by hand, line by line.

  • FKiSS specification
    • Claude

    Collecting all the FKiSS commands from the FKiSS references in HTML, and organizing them into a formal list and docstrings in fkiss.cpp.

  • CMake
    • ChatGPT
    • Gemini

    Surveying and discussing the best practices of CPack and CMakePresets.json for a cross-platform Qt app. Learning Windows packaging, NSIS and the deployment of DLLs.

  • GitHub Actions
    • Gemini
    • ChatGPT
    • Claude Code

    For the Windows packages (I have no Windows development environment). Before the public release, I realized that fighting this was a waste of time, so I let an LLM agent debug it and write the rest of the code.

  • osc / RPM / DEB
    • Gemini
    • ChatGPT
    • Claude Code

    Learning the many detailed rules of DEB and RPM packaging, troubleshooting, and how to build locally with osc. Discussing how to connect the CI/CD of GitHub Actions to the _service of OBS. Before the public release, I let an LLM agent debug it and write the rest of the code.

  • Security measures
    • Claude
    • Claude Code
    • ChatGPT

    Claude Code is in charge of directly writing the code that uses Linux APIs like Landlock and seccomp (but all of it was still reviewed by hand afterwards, 100% of it, even though my knowledge of security is no match for an LLM's anyway, heh). It is also in charge of extracting the parts suitable for QKiSS from the AppArmor profiles that the author of QKiSS uses privately, and organizing them into compatible packages for each distro. ChatGPT also took part in the security review of the C++ code.

  • This website
    • Claude Code

    All the translations, and all the HTML / CSS / JS… I can't be bothered anymore to spend my free time writing web pages.

  • Icons

    Tango / Nome / Humanity are all forked from versions of the era before LLMs appeared. All the icons forked afterwards, and QKiSS's own icons, are hand-drawn by the author of QKiSS with Inkscape.

  • Writing
    • Claude Code

    All the text of this website and the README is hand-written by a human. LLMs are only in charge of translation or grammar correction, and of talking the author out of writing anything even more aggressive.

…Argh, I guess this might be my last project whose code is mainly written by hand… Not only KiSS itself: another era is over.

*1 Not only has freedesktop.org removed the Tango Desktop website, leaving only the tarballs, but now even the English Wikipedia has deleted this article; only Archive.org and Wikipedia in other languages (e.g. de, es, ja) still have it... I can't figure out why it was deleted. Even more absurd, the tango-icon-theme in the official Git repository of freedesktop.org itself is already incomplete, for unknown reasons. Maybe records were lost when it was migrated from SVN or CVS to Git? Anyway, I at least hope that the Tango Remixer project can keep Tango Desktop alive, even if only as a historical record...

SHA-256

Check it on

To check the downloaded file, open a terminal in its folder, and run this command. It prints “OK” if the file is intact.

To check that GitHub Actions built this file from the source code of QKiSS, run this command with the GitHub CLI, in the folder of the downloaded file. It prints “Verification succeeded!” if so.