Skip to content

JIRCD

License: Apache 2.0 Quality gate status Bugs Code Smells Coverage Duplicated Lines (%)

A modular IRCv3 chat server, written in Java, designed to be extended without touching its core.

Status: implemented. All six mandatory user stories from the initial release plan (connect/chat, capability negotiation, extension toggling, channel moderation, in-band administration, and user lookup) are built and covered by integration tests. See Project status below.

What is JIRCD?

JIRCD is a standalone IRC server that speaks both classic IRC (RFC 1459/2812) and a defined set of IRCv3 capability extensions. Its defining goal is modularity with a clear boundary: core protocol behavior (connection handling, channel moderation, capability negotiation) is always present and never optional, while enhancements — individual IRCv3 capabilities, hostname cloaking, in-band server administration — are independently loadable extensions an administrator can enable or disable at runtime, without a restart.

Planned for the first release:

  • Real-time connection registration, channel messaging, and moderation (classic first-join-gets-operator model)
  • IRCv3 capability negotiation, with message-tags, server-time, and echo-message as the initial capability set
  • Runtime-toggleable extensions, configurable via file or in-band IRC administrative commands
  • Standard nickname!ident@hostname identity presentation, with an optional hostname-cloaking extension

Authentication/accounts and server-to-server federation are deliberately out of scope for the first release — see the spec for the reasoning.

Project status

This project is being built with a spec-driven workflow (GitHub Spec Kit): every feature is fully specified and planned before implementation begins. The complete specification, clarifications, technical plan, data model, and API contracts for the initial server feature live under specs/001-ircv3-server/:

  • spec.md — what the server must do, and why
  • plan.md — the technical approach and domain model
  • research.md — key technical decisions and their rationale
  • data-model.md — entities and their relationships
  • contracts/ — the wire protocol and configuration contracts

The project's governing principles (code quality, testing, UX consistency, performance) are recorded in the constitution.

Getting started

Requires JDK 25.

./gradlew build                 # build + unit/integration tests + static analysis, all subprojects
touch jircd-server/jircd.yaml   # a Server Configuration file must exist at this path; an empty
                                 # file is valid and loads every default
./gradlew :jircd-server:run     # starts the server on 6667 (plaintext) and 6697 (TLS)

Then connect with any IRC client, or a raw TCP tool for a quick check:

nc localhost 6667
NICK alice
USER alice 0 * :Alice
JOIN #lobby
PRIVMSG #lobby :hello

The empty config above enables no optional capabilities or extensions — only core protocol behavior (connecting, messaging, moderation, WHOIS/ WHO). To turn on IRCv3 capabilities, hostname cloaking, or in-band administration (OPER, REHASH, etc.), see the full annotated schema in contracts/server-configuration.md. For a guided, story-by-story walkthrough of every feature, see quickstart.md.

Generating an administrator credential

administratorCredentials entries (see the config schema link above) store a bcrypt or Argon2id password hash — never a plaintext password. Generate one with jshell against the jars already bundled in a standalone build:

./gradlew :jircd-server:installDist
cd jircd-server/build/install/jircd-server
jshell --class-path "lib/*"
jshell> com.password4j.Password.hash("your-password-here").withArgon2().getResult()
$1 ==> "$argon2id$v=19$m=15360,t=2,p=1$..."

jshell> com.password4j.Password.hash("your-password-here").withBcrypt().getResult()
$2 ==> "$2b$10$..."

jshell> /exit

Paste the printed value into that credential's hashedPassword field. Only the $argon2id$ Argon2 variant is accepted — $argon2i$/$argon2d$ hashes are rejected at startup, not silently ignored.

Running a standalone build

./gradlew :jircd-server:run is for development only — it stays attached to Gradle. For a standalone install (no Gradle needed to run it), build a distribution instead:

./gradlew :jircd-server:installDist

This produces jircd-server/build/install/jircd-server/, containing a bin/jircd-server (and .bat) launcher plus every runtime dependency — including the bundled capability/extension jars, which are discovered via ServiceLoader at startup — in lib/. Run it from that directory (it looks for jircd.yaml in the working directory, same as :run):

cd jircd-server/build/install/jircd-server
touch jircd.yaml
bin/jircd-server

To produce a distributable archive instead (e.g. for attaching to a release), use distZip or distTar, which land in jircd-server/build/distributions/. See Releases for prebuilt archives — pushing a vX.Y.Z tag builds and publishes these automatically (see .github/workflows/release.yml).

Contributing

Contributions are welcome — see CONTRIBUTING.md for the workflow and expectations. Please also review our Code of Conduct.

Security

See SECURITY.md for how to report a vulnerability.

License

Apache License 2.0 — see LICENSE.

About

Java IRC daemon (Server)

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages