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

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. Animen.

*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.
    • No Electron.
  • The romance of engineering and aesthetics

    • The code of the main program is over 95% 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).
    • 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.
    • 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

Windows

A portable ZIP and an installer, automatically built and digitally signed by GitHub Actions*2.

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 This signature is a GitHub artifact attestation: it proves that GitHub Actions built the Windows files and the source tarball from 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.

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.)

Can QKiSS be ported to macOS?

I have no Mac. So, no idea.

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.

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 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).

  • 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. 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