This document provides guidelines for AI coding agents working on the HexChat codebase.
HexChat is an IRC client written in C (gnu89 standard) using GTK for the GUI. It supports plugins in C, Python, Perl, and Lua.
The GTK4/libadwaita frontend (src/fe-gtk4/) is the only active build target. All new features, bug fixes, and UI work must target this frontend. The GTK4 frontend uses GtkTextView for chat display and libadwaita widgets (e.g., AdwPreferencesWindow, AdwTabView) for the UI.
The legacy GTK2 frontend (src/fe-gtk/) and text frontend (src/fe-text/) remain in the source tree for reference only. Do not implement changes in those frontends expecting them to take effect.
meson build [options] # Configure
ninja -C build # Build
ninja -C build test # Run tests
ninja -C build install # Installmeson build -Dgtk-frontend=true -Dtls=enabled -Dplugin=true \
-Dwith-python=python3 -Dwith-perl=perl -Dwith-lua=luajit -Dwith-fishlim=trueTests use TAP protocol. Currently only the fishlim plugin has tests:
ninja -C build test # Run all tests
./build/plugins/fishlim/tests/fishlim_tests # Run fishlim tests directlymsbuild win32/hexchat.sln /m /p:Configuration=Release /p:Platform=x64- C/C++/H files: Tab indentation (size 4), LF line endings
- Meson files: Space indentation (size 2), final newline
The project uses gnu89 C standard. Do not use C99/C11 features.
| Element | Style | Example |
|---|---|---|
| Functions | snake_case |
find_dialog, session_free |
| Types/Structs | snake_case typedef |
session, server |
| Macros/Constants | UPPER_SNAKE_CASE |
SESS_SERVER, NICKLEN |
| Global variables | snake_case |
sess_list, plugin_list |
| Preference vars | hex_ prefix |
hex_away_auto_unmark |
| Plugin API | hexchat_ prefix |
hexchat_hook_command |
Use traditional #ifndef/#define/#endif pattern:
#ifndef HEXCHAT_PLUGIN_H
#define HEXCHAT_PLUGIN_H
/* ... */
#endif- Standard library headers (
<stdio.h>,<string.h>) - Platform-specific headers (
#ifdef WIN32) - Project headers (
"hexchat.h","util.h") - Conditional feature headers (
#ifdef USE_OPENSSL)
All source files should include the GPL v2 license header:
/* HexChat
* Copyright (C) 1998-2010 Peter Zelezny.
* Copyright (C) 2009-2013 Berke Viktor.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/Use GLib assertion macros for precondition checks:
g_return_if_fail(ptr != NULL);
g_return_val_if_fail(ptr != NULL, -1);- Return
NULLon error for pointer functions - Return
-1or error codes for integer functions - Use
GError**pattern for detailed error reporting
Use GLib memory functions exclusively:
ptr = g_new0(type, count); /* Preferred: allocates zeroed memory */
ptr = g_malloc(size);
ptr = g_strdup(str);
ptr = g_strdup_printf("%s %d", str, num);
g_free(ptr);
GSList *list; /* Single-linked list */
GList *list; /* Double-linked list */#ifdef WIN32
/* Windows-specific code */
#else
/* Unix/Linux code */
#endif-Werror=implicit-function-declaration, -Werror=pointer-arith, -Werror=init-self,
-Werror=format-security, -Werror=missing-include-dirs, -Werror=date-time
hexchat/
├── src/
│ ├── common/ # Core IRC client logic (shared)
│ ├── fe-gtk4/ # GTK4/libadwaita frontend (ACTIVE - all work goes here)
│ ├── fe-gtk/ # Legacy GTK2 frontend (reference only, not built as active target)
│ └── fe-text/ # Legacy text-mode frontend (reference only)
├── plugins/
│ ├── fishlim/ # FiSH encryption (has tests)
│ ├── python/ # Python scripting
│ ├── perl/ # Perl scripting
│ └── lua/ # Lua scripting
├── data/ # Icons, man pages, desktop files
├── po/ # Translations (gettext)
└── win32/ # Windows build files
Plugins use the hexchat_plugin API defined in src/common/hexchat-plugin.h.
int hexchat_plugin_init(hexchat_plugin *ph, char **name, char **desc, char **version, char *arg);
int hexchat_plugin_deinit(void);- Tests use TAP (Test Anything Protocol) format
- Test timeout: 600 seconds
- Test location:
plugins/*/tests/
GitHub Actions: ubuntu-build.yml, windows-build.yml, msys-build.yml, flatpak-build.yml
- Add to appropriate
meson.buildin the subdirectory - Include necessary headers
- Add GPL license header
- Add to
struct hexchatprefsinsrc/common/hexchat.h - Use
hex_prefix for the variable name - Update preference loading/saving in
cfgfiles.c
- Create directory under
plugins/ - Add
meson.buildwith sources and dependencies - Register in root
meson.build
Use 'bd' for task tracking
When ending a work session, you MUST complete ALL steps below. Work is NOT complete until git push succeeds.
MANDATORY WORKFLOW:
- File issues for remaining work - Create issues for anything that needs follow-up
- Run quality gates (if code changed) - Tests, linters, builds
- Update issue status - Close finished work, update in-progress items
- PUSH TO REMOTE - This is MANDATORY:
git pull --rebase bd sync git push git status # MUST show "up to date with origin" - Clean up - Clear stashes, prune remote branches
- Verify - All changes committed AND pushed
- Hand off - Provide context for next session
CRITICAL RULES:
- Work is NOT complete until
git pushsucceeds - NEVER stop before pushing - that leaves work stranded locally
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds