Version 1.0a — alpha · September 2026
$ pisg
The Perl IRC Statistics Generator. Point it at your channel logs, run it, upload one HTML file. It tells you who talks, when they talk, and who they talk to — no database, no daemon, no JavaScript required to read it.
Free software since 2001, GPL-2.0-or-later. Runs anywhere Perl runs. 1.0a is an alpha: everything described here works, but it has not had a long run in the wild yet — tell us what breaks.
- Latest
- 1.0a
- Needs
- Perl 5
- Log formats
- 30+
- Themes
- 12
- Licence
- GPL-2.0+
- Since
- 2001
What it is
A log file in, a statistics page out.
pisg is one Perl script and a config file. It reads the logs your bot or client already writes, counts everything worth counting, and writes a self-contained HTML page you can drop on any web host — including GitHub Pages.
Nothing to install
No database, no cron requirement, no web framework, no build step. Perl 5 and a text editor. Run it by hand or from cron as often as you like.
Reads the logs you have
eggdrop, ZNC, mIRC, irssi, XChat, AdiIRC, BitchX, energymech, KVIrc, supybot and two dozen more. Gzipped and bzipped logs are read as they are.
Statistics people actually read
Not just line counts: who talks to whom, who owns the night shift, whose words are their own, and how much of the channel rests on five people.
Quick start
Four commands and one config file.
This is the whole thing. The example below uses an eggdrop's daily logs; swap
Format and LogDir for whatever writes your logs.
<set ColorScheme="modern"> <set HomeLink="index.html"> <channel="#nightshift"> Format = "eggdrop" LogDir = "/home/eggdrop/logs/nightshift/" Network = "Undernet" Maintainer = "vox" OutputFile = "site/nightshift.html" </channel>
perl pisg. Every channel in the config is parsed
in one run; a channel that cannot be read is skipped with a warning and the others still get
their page. Add -ch, -l and -o to do a single channel
straight from the command line — ./pisg --help lists the lot.
site/index.html next to them for the landing page.
scripts/crontab in the distribution, or
Running pisg in the manual.New in 1.0a
Same parsers, same config — a much better page.
Everything 0.80-preview2 did, pisg 1.0a still does: the same log formats, the same
statistics, the same pisg.cfg. Nothing you have set up has to change.
Who talks to whom
An interactive map of the channel's conversations: who addresses, mentions and answers whom. Click a nick or a line for the detail. Bots are left out.
Four new themes
modern, midnight, amoled and terminal,
all generated from one stylesheet. The eight classic schemes are untouched — and a theme
of your own is one CSS file, or two minutes in the creator.
Section navigation
A menu down the left on wide screens, a slim bar on phones, and a marker on the section you are reading. It works with JavaScript switched off.
A landing page
The statistics of your statistics: every channel compared, a 24-hour profile each, the last 30 days, and a button into each page. One static file, no PHP.
Seven new sections
Channel overview, closest pairs, social roles, time personalities, who carries the channel, and the word each person uses that nobody else does.
Profiles from IRC
An optional eggdrop script lets people set their own picture, link and merged nicks with
!pisginfo — authenticated against their network account.
Several channels, one run
One config, any number of channels. A channel that cannot be read no longer stops the others, and pisg exits with a real error status when something fails.
Safer output
A page is written to a temporary file and moved into place only when it is complete, so a failure can never replace a good page with half of one.
Phones included
Readable from 360 px up, with a viewport tag, full UTF-8 handling, and wide tables that scroll inside their own section instead of dragging the page sideways.
Live example
What a busy channel looks like.
A full 1.0a page for #nightshift — 133,944 lines from 915
nicks over 50 days — plus the landing page that ties it to a second, much quieter channel.
Invented channels, invented people; the numbers, the graphs and the markup are a real pisg run.
#nightshift — a very busy channel
Every section 1.0a can produce, at the scale of a channel that never really sleeps: 2,679 lines a day, a relation map with 30 nicks in it, and 19 sections to navigate.
Open the stats page → ⌂ landing pageTwo channels, one front door
The statistics of the statistics: totals across every channel, share of all lines, each
channel's busiest hour, and its last 30 days at a glance. site/index.html, reading
the channels.json pisg wrote beside it.
#basement — a quiet room
The other end of the scale: 37 lines a day over half a year, user pictures switched on, and a bot sitting at the top of the table where a person usually is.
Open the stats page → ▤ themesThe same page, six ways
A complete sample page in each colour scheme, so you can see what one line of config does before you commit to it.
Open the theme previews →Themes
Pick a look with one line of config.
<set ColorScheme="modern"> is the whole change. Four modern
schemes ship with 1.0a; modern follows the reader's light/dark setting, the other
three stay dark on purpose. Each preview is a full page pisg 1.0a made in that scheme, from an
invented channel.
darkgalaxy, ocean,
softgreen and the rest — still work exactly as they did, and they have also been
converted to the 1.0a palette, so you can have the old colours with
the new layout. Rolling your own by hand is still a CSS file in layout/ and
<set ColorScheme="myfile">. See Themes and
Changing the layout.Log formats
Whatever is already writing your logs.
Set Format to one of these. If the file ends in .gz or
.bz2 pisg decompresses it on the way in. Full details and per-format notes live in
the docs/FORMATS file in the distribution.
Bots
Clients
Format="energymech" and a
LogDir per channel. Moving an old client log into that shape is what
scripts/adiirc2eggdrop.py is for.Optional tools
For the people who run the channel.
None of these are required to use pisg. They live in scripts/ and
solve the things that otherwise mean editing config files by hand.
!pisginfo
for sex, picture and link, !pisgmerge to count their other nicks as one person,
!pisgstats for the page address. Identified by network account, rate limited, and
it can never overwrite a <user> line you wrote yourself. 107 tests ship with it.
Docs →
<user>
lines always win; shared hosts, gateways and bouncers are never merged.
Docs →
FAQ
Questions people actually ask.
I have no bot. Can I still make stats?
Yes, if your client keeps logs with timestamps. mIRC, AdiIRC, irssi,
XChat, KVIrc and others are all supported formats — turn timestamped logging on, point
Logfile at the file and run pisg. A bot or a bouncer is only better because it is
online when you are not.
Do I need a web server?
No. The page is a single HTML file with the stylesheet and the bar
graphics inside it, so opening it from your disk works. To share it, any static host will do
— GitHub Pages, a shared account, the public_html folder you have had since
1999. The landing page is static too: no PHP and no cron job.
Will 1.0a break my existing setup?
It is an alpha, so keep the version you run now until you have tried this one on a copy. That said: your pisg.cfg keeps working as it is, and every old colour
scheme looks as it did. Two things to know: the new sections are on by default (set
ShowOverview, ShowRelations, ShowTimePersonalities,
ShowConcentration, ShowSignatureWords and ShowNavBar to
0 for the old page exactly), and pisg now exits with status 1 when it fails instead
of pretending everything went fine. Check any script that read its exit code.
How long does a run take?
Minutes for years of logs, seconds once the cache is warm. Set
CacheDir and pisg keeps the parsed result of each log file, so a nightly run only
reads what changed. The example on this site — 617,000 lines across three channels —
takes about forty seconds from cold.
Can I keep people out of the statistics?
<user nick="somebot" ignore="y"> leaves a nick out
entirely, and sex="b" marks it as a bot so the relation map skips it.
BadUrls keeps image hosts and spam out of the URL list, and
IgnoreWords does the same for words. If someone asks to be left out, that one line
is the whole answer.
Is anything sent anywhere?
No. pisg reads local files and writes local files. It opens no network connection and has no option that would make it open one.
Where do I get help?
The channel: #pisg on Undernet
(irc.undernet.org). For bugs and patches, the
issue tracker on GitHub. The old SourceForge
trackers and mailing list are read-only history now.
Credits
Whose work this is.
Written by Morten “mbrix” Brix Pedersen
pisg was started in 2001 by mbrix, because IRCStats was not open source and a channel deserved to be able to read itself. It lived on SourceForge for a decade and a half and is still there: sourceforge.net/projects/pisg. Everything since — including 1.0a — is built on that code and keeps its licence.
Kept going on GitHub
Development moved to github.com/PISG/pisg, where
the current maintainer is Seb. Translations,
log-format patches and colour schemes have come from more people than this page can list —
see docs/CREDITS in the distribution.