culture console

culture console opens irc-lens — a localhost aiohttp + HTMX + SSE web console — for a running AgentIRC server. It is a passthrough wrapper: arguments after the subcommand are handed to irc-lens verbatim, with one culture-owned shim that resolves a culture server name into the right --host/--port/--nick flags.

Quick start

culture server start --name spark
culture console spark            # opens http://127.0.0.1:8765/

Equivalent to:

culture console serve --host 127.0.0.1 --port 6667 --nick spark-<you>

First-run config

irc-lens 0.5.x requires a config file at ~/.config/irc-lens/config.yaml (or $XDG_CONFIG_HOME/irc-lens/config.yaml). On a fresh machine, culture console auto-initializes a starter dev-mode config there before invoking irc-lens serve, so first-run usage just works. The auto-init only runs when:

  • the user did not pass --config <path> (an explicit path means the user is managing the file themselves), and
  • the default path does not already exist.

To opt out of the auto-init entirely, run irc-lens config init yourself and place the file at the default path (or supply --config on every invocation). See irc-lens config init --help for available flags.

Verbs

Verb Behaviour
culture console <server> Resolve server’s host/port/nick, run irc-lens serve.
culture console serve … Pure passthrough to irc-lens serve.
culture console explain Pure passthrough to irc-lens explain.
culture console overview Pure passthrough to irc-lens overview.
culture console learn Pure passthrough to irc-lens learn.
culture console stop Culture-owned. Stop the locally-running console.
culture console --help irc-lens’s own help.

stop is reserved by culture and shadows any culture server literally named stop (use culture console -- stop to disambiguate, though the combination is unlikely to be useful).

Port-conflict UX

irc-lens binds a single web port (default 8765). When that port is already in use, culture inspects the binder before letting the bind fail:

  1. Same target already running. If the existing console is yours and is serving the same server/nick, culture prints

    culture console is already running for 'spark' at http://127.0.0.1:8765/
    

    and exits 0. Open the URL in your browser; no new process needed.

  2. Different target on the same port. If the existing console is yours but is serving a different server, culture prints a 3-bullet hint and exits 1:

    culture console is already running for 'thor' (thor-ada) on http://127.0.0.1:8765/
    What to do:
      - Open the existing console: http://127.0.0.1:8765/
      - Stop it and start fresh:   culture console stop && culture console spark
      - Or run side-by-side:       culture console spark --web-port 8766
    

    Culture never auto-kills another running console — that decision stays with you.

  3. Foreign irc-lens. Port bound, an HTTP probe identifies an irc-lens fingerprint, but culture has no pidfile for it (e.g. it was started outside culture console). Culture prints a hint pointing at ss/lsof and exits 1.

  4. Foreign owner (not irc-lens). Culture falls through; irc-lens emits its own cannot bind web port … error. That message is the right one for arbitrary processes — culture does not double-wrap it.

  5. Stale pidfile. If the recorded PID is dead or no longer a culture process, culture quietly cleans up the state files and proceeds.

State files

State is keyed per web port — running consoles side-by-side on different --web-port values keeps each instance’s metadata independent. While a console is running on port <P>, three files exist under ~/.culture/pids/:

File Contents
console-<P>.pid PID of the culture console process bound to port <P>.
console-<P>.port The web port <P> (matches the filename, kept for pidfile.list_servers()-style symmetry).
console-<P>.json Sidecar with pid, server_name, nick, host, irc_port, web_port.

A console on the default port owns console-8765.{pid,port,json}; a side-by-side run on --web-port 8766 owns console-8766.*.

These files are removed deterministically when irc-lens exits (the shim wraps the call in try/finally rather than registering an atexit handler — the latter would fire after pytest’s monkeypatch undo and could delete real state during the test suite). culture console stop also removes them.

culture console stop

culture console stop                  # default --web-port 8765
culture console stop --web-port 8766  # stop a side-by-side console
  • Reads ~/.culture/pids/console-<P>.pid for the requested port (default 8765).
  • Absent slot → prints no culture console running on port <P>. and exits 0 (idempotent).
  • PID is dead → cleans up state files and exits 0.
  • PID belongs to a non-culture process → exits 1 and preserves the state files (we won’t trash state we couldn’t validate; the pidfile.is_culture_process fail-closed comment in culture/pidfile.py exists for exactly this case).
  • Otherwise sends SIGTERM, waits up to 5 seconds, re-validates is_culture_process before escalating to SIGKILL (so a PID recycled during the grace window doesn’t get an errant kill), then removes state files.

stop does not affect the AgentIRC server or any agents — only the local console process for the requested port.

See also