Project_Detail
All_Projects

Ergonaut

An SSH IRC Client for Ergo IRCd

View on GitHub
README.md

Ergonaut

Ergonaut is an SSH server that logs users into Ergo IRC and drops them directly into a terminal IRC client.

The login flow is:

  1. SSH login to Ergonaut
  2. Ergonaut checks the username/password against Ergo's HTTP API
  3. Ergonaut starts an in-terminal IRC UI
  4. The IRC session connects to Ergo and authenticates with SASL using the same credentials

The result is a single-entry SSH experience for Ergo IRC accounts.

What it does

  • Authenticates SSH logins against Ergo NickServ accounts
  • Reuses the successful login for IRC SASL PLAIN
  • Auto-discovers Ergo API and IRC connection settings from an existing ircd.yaml
  • Auto-loads the logged-in account's registered/associated channels from Ergo
  • Requests channel history on join
  • Shows channels, chat, members, topic, and backlog in a terminal UI

Requirements

  • Go 1.24+
  • A running Ergo IRC server
  • Ergo HTTP API enabled with at least one bearer token
  • Local read access to Ergo's config file if you want auto-discovery

Quick start

  1. Adjust ergonaut.yaml
  2. Start Ergonaut:
go run . -config ./ergonaut.yaml
  1. Connect over SSH:
ssh -p 2222 <ergo-account>@127.0.0.1

Use the same password you use for your Ergo account.

Configuration

Ergonaut is configured with ergonaut.yaml.

Example:

ssh:
  listen: "127.0.0.1:2222"
  host-key-path: "./data/ergonaut_ed25519"

ergo:
  config-path: "/home/ergo/ircd.yaml"

  api:
    url: ""
    bearer-token: ""

  irc:
    address: ""
    tls: false
    skip-tls-verify: false
    server-name: ""

session:
  auto-join: []
  motd: "Welcome to Ergonaut. Use /join #channel to start chatting."

How config resolution works

There are two ways Ergonaut can learn how to talk to Ergo:

  1. Discover from ergo.config-path
  2. Use explicit overrides in ergonaut.yaml

Recommended mode: discover from Ergo config

If ergo.config-path points at a real Ergo ircd.yaml, Ergonaut reads it at startup and discovers:

  • Ergo API URL
  • Ergo API bearer token
  • IRC server address
  • IRC TLS/plaintext mode
  • IRC server name

In this mode, you can leave these fields blank:

ergo:
  config-path: "/home/ergo/ircd.yaml"
  api:
    url: ""
    bearer-token: ""
  irc:
    address: ""
    server-name: ""

That means:

"Read the values from Ergo's config instead of duplicating them here."

Override mode

If you fill in values in ergonaut.yaml, those values win over discovery.

For example:

ergo:
  config-path: "/home/ergo/ircd.yaml"
  api:
    url: "http://127.0.0.1:8089"
    bearer-token: "your-token-here"

That means:

"Use this URL/token even if Ergo's config says something else."

Do I need to set both config-path and bearer-token?

No.

If config-path is valid and the Ergo config contains the API token, you do not need to repeat the bearer token in ergonaut.yaml.

Set bearer-token manually only if:

  • you do not want Ergonaut reading Ergo's config directly, or
  • you want to override the discovered value

Config reference

ssh.listen

Address Ergonaut listens on for SSH.

Example:

ssh:
  listen: "127.0.0.1:2222"

ssh.host-key-path

Path to the SSH host key file. If it does not exist, Ergonaut creates one.

ergo.config-path

Path to Ergo's ircd.yaml. Used for discovery.

ergo.api.url

Optional explicit override for the Ergo API base URL.

ergo.api.bearer-token

Optional explicit override for the Ergo API bearer token.

ergo.irc.address

Optional explicit override for the IRC server address Ergonaut connects to.

ergo.irc.tls

Force IRC TLS on or off.

ergo.irc.skip-tls-verify

Skip TLS certificate verification for IRC connections. Useful for local testing; avoid in production unless you understand the tradeoff.

ergo.irc.server-name

Optional explicit override for the IRC server name.

session.auto-join

Extra channels to join in addition to the account's channels discovered from Ergo.

session.motd

Message shown when the TUI opens.

Runtime behavior

After a successful SSH login, Ergonaut:

  1. Validates credentials with Ergo /v1/check_auth
  2. Reads account metadata from Ergo /v1/ns/info
  3. Starts the IRC client
  4. Negotiates SASL and chat history capabilities
  5. Autojoins:
    • channels listed in session.auto-join
    • channels associated with the logged-in account in Ergo
  6. Requests backlog for joined channels

TUI behavior

The terminal UI currently provides:

  • left pane: channels/buffers
  • center pane: current chat buffer and topic
  • right pane: channel members
  • bottom input: message entry
  • status line: connection/status feedback

Keybindings

  • Tab / Shift+Tab: switch buffers
  • PgUp / PgDn: scroll chat history
  • Home / End: jump in chat history
  • F1: toggle help
  • Ctrl+C: quit

Commands

  • /join #channel
  • /part [#channel]
  • /switch <buffer>
  • /msg <target> <message>
  • /nick <newnick>
  • /raw <command>
  • /buffers
  • /quit

Security notes

  • The Ergo bearer token is sensitive
  • Do not commit real bearer tokens to source control
  • Do not commit generated SSH host keys
  • Prefer discovery from a protected local Ergo config instead of duplicating secrets

Development

Format, test, and build:

gofmt -w .
go test ./...
go build ./...

Run with a specific config:

go run . -config ./ergonaut.yaml

Repository layout

main.go                  server entrypoint
ergonaut.yaml            example config
internal/auth/           SSH session auth state
internal/config/         config loading and Ergo discovery
internal/ergo/           Ergo HTTP API client
internal/irc/            IRC protocol client
internal/ui/             Bubble Tea terminal UI