Icalingua++: an Electron chat front end for QQ with a read-only mode and a Bridge backend
A client for QQ and more. :electron:
At a glance
- What is it?
- Icalingua++ is a TypeScript and Electron client that talks to chat platforms through adapters. Its readOnly adapter browses a local SQLite history with no server connection, and its socketIo adapter hands the connection to the icalingua-bridge-oicq service.
- Who is it for?
- Adopt Icalingua++ if you want a Linux desktop front end that keeps QQ history in a local SQLite file and can fall back to readOnly browsing when login fails, or if you want to run the oicq connection inside the icalingua-bridge-oicq service and reach it over Socket.IO. Do not adopt it if you need a supported, vendor-sanctioned QQ client, or if you intend to keep modifications private: AGPL-3.0 requires that the source be offered alongside a modified running service.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap Icalingua++ fills for Linux QQ users
The README frames the project as a fork of Icalingua that provides limited updates to a deleted upstream, and describes the goal as building a conversation front-end framework for Linux. That framing matters more than the QQ support itself. The desktop client is one half of the repository; the other half is a set of adapters, and the README says the project already ships a fork of oicq called oicq-icalingua-plus-plus plus a backend for Icalingua's own protocol.
The intended reader is someone on Linux who wants a native-feeling window for QQ rather than a web wrapper, and who is willing to accept that the connection layer is a community reimplementation. The disclaimer is explicit that problems arising from calling different adapter backends are the user's responsibility. That is not boilerplate here. The oicq path is an unofficial protocol client, and the README's own header-signature API section warns that using an untrusted API can leak message contents.
So the honest description is: a front end with a pluggable transport, aimed at people who value local history and theming over vendor support.
Adapters, the local SQLite store, and where messages actually flow
The adapter is chosen by the `adapter` field in the client configuration file. The README lists three values. `oicq` is the default and embeds oicq directly in the client. `readOnly` reads chat data already present on the machine and never connects to a server. `socketIo` connects to a Bridge over Socket.IO, with deployment, authentication and client configuration deferred to the icalingua-bridge-oicq README.
The split is architecturally clean. In `oicq` mode the Electron process owns the network session and the message store. In `socketIo` mode the network session moves into the bridge service, which the Dockerfile exposes on port 6789, and the client becomes a rendering and storage layer. In `readOnly` mode there is no session at all.
Storage is local and per-account. The readOnly example sets `storageType: sqlite` under `account`, and the `username` is described as the QQ number corresponding to the local database. That means the history you browse is keyed to a specific account directory, not to a global archive. If you have logged in with two accounts, readOnly mode will show only the one whose number you put in the config.
The extension surface follows the same pattern of reading files from the data directory at startup. `addon.js` is loaded if present but is not created by default. `style.css` is the same. Every JSON file in the `themes` directory becomes a theme named after its filename, and the README points at a default theme file in the source as the reference for the schema. Plugins live in a directory named `custom`, must be enabled in the options or via `custom: true` in the bridge config, and only the exported `onMessage` method is called on message receipt.
Installing Icalingua++ and taking it for a first run
The README does not give a build-from-source walkthrough for the desktop client. It points at GitHub releases, and it thanks the community for an AUR package named `icalingua++`. Those are the two distribution channels the project itself names. If you are on Arch, the AUR package is the shortest path; otherwise take the release artifact for your platform.
Configuration lives in a per-OS data directory. Linux uses `~/.config/icalingua`, Windows uses `%AppData%\icalingua`, and macOS uses `~/Library/Application Support/icalingua`. You can override the whole location with `--user-data-dir=` followed by the path you want, and you can point at a specific config file with `--config xxx.yaml` or the short form `-c xxx.yaml`.
To try read-only browsing, quit the client first, then edit `config.yaml` in that data directory. The README gives this exact shape:
adapter: readOnly
account:
username: 123456789 # 与本地数据库对应的 QQ 号
password: ''
storageType: sqliteReplace the username with the QQ number whose local database you want to read. On the next start the client should come up without a login step and show the rooms and messages already stored. The README is direct about the ceiling: read-only mode can browse saved rooms, history and local search results, and cannot send messages, receive messages online, re-fetch history, or perform group and friend management.
The README also lists startup flags worth knowing before you file a bug. `--dha` disables hardware acceleration, which is the usual first thing to try when an Electron window renders badly. `--hide` or `-h` starts with the main window hidden.
If you would rather run the connection on a server, the repository ships a Dockerfile for the bridge. It builds from `node:24-alpine`, installs build tools and Python, enables corepack, then runs `pnpm i` and `pnpm build` inside `icalingua-bridge-oicq`. The runner stage installs `ffmpeg` and `curl`, sets `TZ=Asia/Shanghai` and `NODE_OPTIONS=--enable-source-maps`, and declares `EXPOSE 6789`. The container command is a shell, not a started service, so the image is a base you drive yourself rather than a turnkey deployment.
What readOnly mode cannot do, and when Icalingua++ is the wrong tool
Read-only mode is the clearest limitation and also the most useful one to understand, because it is the fallback people reach for when login breaks. It does not re-pull history. If your local database is thin, or if the account was only ever used briefly on this machine, the client will show you a thin archive and there is no way to fill it in without a working session.
The second limitation is the login layer itself. The README includes a section on a header-signature API described as a way to work around being unable to log in or send messages, and immediately warns against using APIs you cannot trust because of message-content leakage. That is an admission that the default path can fail and that the workaround carries real risk. Anyone whose threat model includes message confidentiality should treat the header-signature route as off the table.
The third is scope. The disclaimer states the project is for learning and exchange about front-end framework implementation, forbids illegal use, and says not to use it commercially. If you need a client with a support contract, an official protocol, or a guarantee that a protocol change will be fixed on a schedule, this is not that. The last push was on 2026-09-23 with a release the same day, so the repository is current, but current is not the same as supported.
Finally, plugin authors should note the constraint the README states plainly: plugins must be written in JavaScript, and the reference plugin must be compiled with tsc before use. The `onMessage` hook fires on message receipt only. If you need to react to other events you are told to use `bot.on()`, which pushes you toward the modified OICQ v1 API rather than a stable plugin interface.
Icalingua++ against a plain web QQ client
The obvious alternative for most Linux users is a browser tab pointed at QQ's web client. The difference is not cosmetic. A web client keeps history wherever the vendor keeps it, and closing the tab does not leave you a local database. Icalingua++ writes to a SQLite file in a directory you control, which is why readOnly mode can exist at all: there is something on disk to read when the network path is gone.
The second difference is the extension model. A web client gives you no supported way to inject a stylesheet, a color theme or a message hook. Icalingua++ reads `style.css`, `addon.js`, a `themes` directory and a `custom` plugin directory from the data directory on startup. The README's transparent-dark example shows the theme schema is a flat set of color keys across `general`, `header`, `footer`, `content`, `message` and `panel`, with `baseTheme` selecting light or dark. That is a narrow surface by design: the README states color themes only change colors, and that changing anything else requires the custom stylesheet.
The trade-off is that you are now responsible for the transport. A web client breaks when the vendor changes something, and someone else fixes it. Icalingua++ breaks in the same way, and the fix arrives as a pull request from whoever is maintaining the oicq fork that week.
Licence and the cost of keeping a fork
Icalingua++ is AGPL-3.0. The README states the practical consequence without hedging: modification, redistribution and running as a service must comply with the licence, and the source must be provided together with the service. For a desktop client that most people run locally this rarely bites. It bites if you take the bridge, modify it, and expose it to other users, because the bridge is exactly the component that runs as a service.
Upgrade cost is dominated by the transport, not the UI. The root `package.json` pins the package manager to `[email protected]`, declares workspaces for `icalingua`, `icalingua-bridge-oicq` and `packages/*`, and overrides `negotiator` to `0.6.4` and `node-gyp` to `12.4.0`. Those overrides are a signal: the dependency graph needs pinning to build, and a fork that diverges from the `develop` branch inherits the job of keeping those pins coherent.
There is no upgrade path documented for the local database. The README describes `storageType: sqlite` and the account-to-database mapping but says nothing about schema migration between releases. Back up the data directory before moving between versions, because the documentation does not promise that an older database will open cleanly in a newer client.
Editorial conclusion
Adopt Icalingua++ if you want a Linux desktop front end that keeps QQ history in a local SQLite file and can fall back to readOnly browsing when login fails, or if you want to run the oicq connection inside the icalingua-bridge-oicq service and reach it over Socket.IO. Do not adopt it if you need a supported, vendor-sanctioned QQ client, or if you intend to keep modifications private: AGPL-3.0 requires that the source be offered alongside a modified running service. Before committing, verify that the adapter you need is documented in the icalingua-bridge-oicq README for your deployment shape, and confirm that your distribution package matches the develop branch you are reading.
Frequently asked questions
What is Icalingua++?
It is a fork of Icalingua that provides limited updates to the deleted upstream, built as a conversation front-end framework for Linux in TypeScript and Electron. It supports QQ through an oicq fork and through Icalingua's own protocol backend.
How do I install Icalingua++ on Linux?
The README points to GitHub releases and thanks the community for an AUR package named icalingua++. It does not document a build-from-source procedure for the desktop client.
What does Icalingua++ readOnly mode do?
Setting adapter to readOnly in config.yaml makes the client read chat data already stored on the machine without connecting to a server. It can browse saved rooms, history and local search results, but cannot send messages, receive messages online, re-fetch history, or manage groups and friends.
Where does Icalingua++ store its data?
On Linux the data directory is ~/.config/icalingua, on Windows %AppData%\icalingua, and on macOS ~/Library/Application Support/icalingua. You can override it with --user-data-dir= followed by the path you want.
What licence is Icalingua++ released under?
AGPL-3.0. The README states that modification, redistribution and running as a service must comply with the licence, and that the source must be provided together with the service.
Official sources
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.
[](https://hysenlabs.com/projects/icalingua-plus-plus-icalingua-plus-plus)