{"id":51475338,"url":"https://github.com/klppl/stugan","last_synced_at":"2026-07-06T20:30:29.533Z","repository":{"id":361928213,"uuid":"1250609542","full_name":"klppl/stugan","owner":"klppl","description":"Self-hosted web IRC client — a 24/7 Go daemon plus a Vue 3 frontend, with IRCv3 support and a Lua plugin system.","archived":false,"fork":false,"pushed_at":"2026-07-05T21:53:41.000Z","size":981,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-05T22:09:06.465Z","etag":null,"topics":["golang","irc","irc-client","ircv3","lua","self-hosted","vue3","websocket"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/klppl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-26T19:58:12.000Z","updated_at":"2026-07-05T21:53:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/klppl/stugan","commit_stats":null,"previous_names":["klppl/stugan"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/klppl/stugan","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klppl%2Fstugan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klppl%2Fstugan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klppl%2Fstugan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klppl%2Fstugan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/klppl","download_url":"https://codeload.github.com/klppl/stugan/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klppl%2Fstugan/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35205739,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-06T02:00:07.184Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["golang","irc","irc-client","ircv3","lua","self-hosted","vue3","websocket"],"created_at":"2026-07-06T20:30:29.075Z","updated_at":"2026-07-06T20:30:29.524Z","avatar_url":"https://github.com/klppl.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# stugan\n\nA self-hosted, plugin-extensible web IRC client written in Go.\n\nstugan is a persistent daemon that holds your IRC connections 24/7 and buffers\nhistory, plus a Vue 3 browser frontend that talks to it over a typed-JSON\nWebSocket — think [TheLounge](https://thelounge.chat/), rewritten in Go, with\nthe IRCv3 discipline of [Halloy](https://github.com/squidowl/halloy) and a\n**weechat/irssi-style Lua plugin system** as the headline feature.\n\n![stugan screenshot](screenshot.png)\n\n## Features\n\n- Persistent connections that survive browser disconnects; SQLite history with\n  backlog replay and full-text search (FTS5).\n- Manage networks entirely from the web UI — add, edit, connect/disconnect,\n  remove. Server password (bouncers like ZNC/soju), per-network \"perform\"\n  commands, SASL (PLAIN and EXTERNAL/CertFP).\n- IRCv3: server-time, echo-message, away-notify, account-tag, multi-prefix,\n  extended-join, message-tags, typing indicators, standard-replies, emoji\n  reactions, message redaction, a channel browser (LIST), best-effort\n  chathistory. See [docs/ircv3.md](docs/ircv3.md).\n- Link previews + inline image/video via a local proxy, drag-drop/paste\n  uploads, autocomplete (nicks/commands/channels/emoji), command aliases,\n  per-channel mute, a mentions view, configurable highlight rules.\n- A **Lua plugin system** (weechat/irssi style): commands, message\n  filters/rewrites, signal hooks, timers, persistent KV, hot-reload.\n- PWA: installable, mobile-responsive, Web Push + desktop notifications.\n- Multi-user with bcrypt auth and full per-user isolation; an optional\n  site-wide password gate.\n\n## Quick start\n\n```sh\n# Build the client (the daemon serves client/dist at /).\ncd client \u0026\u0026 npm install \u0026\u0026 npm run build \u0026\u0026 cd ..\n\n# Build and run the daemon.\ngo build -o stugan ./cmd/stugan\n./stugan                      # uses $STUGAN_HOME, else ~/.config/stugan\n./stugan -home ./dev          # disposable config/data dir\n```\n\nThen open the listen address (default `http://127.0.0.1:8080`).\n\nFor live client reload, run the daemon and the Vite dev server side by side\n(Vite on :5173 proxies the WebSocket to the daemon on :8080):\n\n```sh\n./stugan \u0026\ncd client \u0026\u0026 npm run dev\n```\n\n## Docker\n\nImages are published to GHCR (`ghcr.io/klppl/stugan`) for amd64 and arm64:\n\n```sh\ndocker run -d --name stugan -p 8080:8080 -v stugan-data:/data \\\n  ghcr.io/klppl/stugan:latest\n```\n\nConfig, history, scripts, and uploads live in the `/data` volume. Put a\n`config.toml` there with `listen = \"0.0.0.0:8080\"`; set `public_url` /\n`origin_patterns` when serving from a non-localhost host. See\n[docs/docker.md](docs/docker.md) for the full run guide (compose, reverse\nproxy + TLS, `trusted_proxies` for login throttling, auth, updates). The image is built and published by\n`.github/workflows/docker.yml`.\n\n## Configuration\n\nConfig, scripts, and data live under one root, resolved in order:\n`$STUGAN_HOME`, then `$XDG_CONFIG_HOME/stugan`, then `~/.config/stugan`. By\ndefault stugan runs single-user and unauthenticated; add `[[users]]` to require\nlogin and isolate accounts. See [docs/config.md](docs/config.md) for the full\nreference and [docs/config.example.toml](docs/config.example.toml) for a\nstarting point.\n\n## Plugins\n\nDrop a Lua script in `$STUGAN_HOME/scripts/*.lua` and it loads live\n(hot-reloaded on save). Scripts register commands, filter/rewrite/drop\nmessages, hook signals, and run timers via a `stugan.*` API. A crashing script\nis isolated and never takes down the daemon.\n\n```lua\n-- scripts/greet.lua\nstugan.hook_command(\"greet\", function(args, ctx)\n  stugan.message(ctx.network, args[1], \"hello from a plugin!\")\nend)\n```\n\nSee [docs/plugins.md](docs/plugins.md) and [docs/examples](docs/examples)\n(`greet`, `highlight_reply`, `away`, `sed`, `urls`, `expand`, `watch`,\n`nickserv`, `qauth`, `fun`, plus the bundled FiSH encryption and `ignore`\nplugins).\n\n## Documentation\n\n| Doc | What it covers |\n|-----|----------------|\n| [architecture](docs/layout.md) | Module/interface layout, dependency contract, data flow |\n| [core](docs/core.md) | The engine, domain types, event bus, sinks, the plugin API surface |\n| [protocol](docs/protocol.md) | The WebSocket wire protocol (envelope + every event) |\n| [irc](docs/irc.md) | The IRC layer: girc wrapping, event translation, SASL |\n| [ircv3](docs/ircv3.md) | IRCv3 capability matrix and roadmap |\n| [storage](docs/storage.md) | SQLite schema, history, search, persistence |\n| [server](docs/server.md) | HTTP/WebSocket server, multi-tenant hub, auth, security |\n| [frontend](docs/frontend.md) | The Vue 3 client architecture |\n| [theming](docs/theming.md) | Creating and installing custom themes |\n| [docker](docs/docker.md) | Pulling the GHCR image and running it on a server |\n| [plugins](docs/plugins.md) | The Lua plugin API |\n| [config](docs/config.md) | Configuration reference |\n\n## License\n\nstugan is released under the [Lagom License](LICENSE) — not too much, not too\nlittle.\n\u003c/content\u003e\n\u003c/invoke\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fklppl%2Fstugan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fklppl%2Fstugan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fklppl%2Fstugan/lists"}