agentirc-cli 9.5.0a2__tar.gz → 9.6.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/CHANGELOG.md +57 -0
  2. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/CLAUDE.md +18 -14
  3. agentirc_cli-9.6.1/LICENSE +201 -0
  4. agentirc_cli-9.6.1/PKG-INFO +301 -0
  5. agentirc_cli-9.6.1/README.md +266 -0
  6. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/bots/http_listener.py +9 -1
  7. agentirc_cli-9.6.1/agentirc/_internal/event_subscriptions.py +282 -0
  8. agentirc_cli-9.6.1/agentirc/_internal/virtual_client.py +32 -0
  9. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/channel.py +32 -5
  10. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/client.py +177 -16
  11. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/ircd.py +25 -28
  12. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/server_link.py +1 -1
  13. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/skills/rooms.py +1 -1
  14. {agentirc_cli-9.5.0a2/agentirc/_internal → agentirc_cli-9.6.1/agentirc}/virtual_client.py +36 -17
  15. agentirc_cli-9.6.1/docs/api-stability.md +417 -0
  16. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/cli.md +1 -1
  17. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/deployment.md +11 -3
  18. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/extension-api.md +5 -5
  19. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/pyproject.toml +17 -7
  20. agentirc_cli-9.6.1/tests/test_api_stability_embedding.py +138 -0
  21. agentirc_cli-9.6.1/tests/test_bot_capability.py +204 -0
  22. agentirc_cli-9.6.1/tests/test_event_subscriptions.py +335 -0
  23. agentirc_cli-9.6.1/tests/test_eventpub.py +194 -0
  24. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/uv.lock +1 -1
  25. agentirc_cli-9.5.0a2/LICENSE +0 -21
  26. agentirc_cli-9.5.0a2/PKG-INFO +0 -57
  27. agentirc_cli-9.5.0a2/README.md +0 -2
  28. agentirc_cli-9.5.0a2/docs/api-stability.md +0 -290
  29. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/SKILL.md +0 -0
  30. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/portability-lint.sh +0 -0
  31. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/pr-batch.sh +0 -0
  32. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/pr-comments.sh +0 -0
  33. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/pr-reply.sh +0 -0
  34. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/pr-sonar.sh +0 -0
  35. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/pr-status.sh +0 -0
  36. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/workflow.sh +0 -0
  37. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills.local.yaml.example +0 -0
  38. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.github/workflows/publish.yml +0 -0
  39. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.github/workflows/tests.yml +0 -0
  40. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.gitignore +0 -0
  41. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/__init__.py +0 -0
  42. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/__main__.py +0 -0
  43. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/__init__.py +0 -0
  44. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/aio.py +0 -0
  45. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/bots/__init__.py +0 -0
  46. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/bots/bot_manager.py +0 -0
  47. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/cli_shared/__init__.py +0 -0
  48. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/cli_shared/constants.py +0 -0
  49. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/cli_shared/mesh.py +0 -0
  50. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/constants.py +0 -0
  51. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/pidfile.py +0 -0
  52. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/protocol/__init__.py +0 -0
  53. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/protocol/message.py +0 -0
  54. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/protocol/replies.py +0 -0
  55. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/telemetry/__init__.py +0 -0
  56. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/telemetry/audit.py +0 -0
  57. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/telemetry/context.py +0 -0
  58. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/telemetry/metrics.py +0 -0
  59. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/telemetry/tracing.py +0 -0
  60. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/cli.py +0 -0
  61. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/config.py +0 -0
  62. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/events.py +0 -0
  63. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/history_store.py +0 -0
  64. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/protocol.py +0 -0
  65. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/remote_client.py +0 -0
  66. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/room_store.py +0 -0
  67. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/rooms_util.py +0 -0
  68. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/skill.py +0 -0
  69. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/skills/__init__.py +0 -0
  70. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/skills/history.py +0 -0
  71. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/skills/icon.py +0 -0
  72. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/skills/threads.py +0 -0
  73. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/thread_store.py +0 -0
  74. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/steward/onboarding.md +0 -0
  75. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/superpowers/specs/2026-04-30-bootstrap-design.md +0 -0
  76. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/superpowers/specs/2026-05-01-bot-extension-api-design.md +0 -0
  77. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/superpowers/specs/2026-05-01-task14-audit.md +0 -0
  78. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/__init__.py +0 -0
  79. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/_helpers.py +0 -0
  80. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/conftest.py +0 -0
  81. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/__init__.py +0 -0
  82. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/_fakes.py +0 -0
  83. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/_metrics_helpers.py +0 -0
  84. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_audit_emit.py +0 -0
  85. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_audit_lifecycle.py +0 -0
  86. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_audit_module.py +0 -0
  87. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_audit_parse_error.py +0 -0
  88. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_config.py +0 -0
  89. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_dispatch_span.py +0 -0
  90. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_emit_event_span.py +0 -0
  91. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_metrics_init.py +0 -0
  92. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_metrics_s2s.py +0 -0
  93. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_outbound_inject.py +0 -0
  94. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_parse_error.py +0 -0
  95. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_s2s_relay_span.py +0 -0
  96. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_server_init.py +0 -0
  97. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_server_link_inject.py +0 -0
  98. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_tracing.py +0 -0
  99. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_channel.py +0 -0
  100. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_cli.py +0 -0
  101. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_config_loader.py +0 -0
  102. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_connection.py +0 -0
  103. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_discovery.py +0 -0
  104. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_events_basic.py +0 -0
  105. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_events_catalog.py +0 -0
  106. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_events_federation.py +0 -0
  107. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_events_history.py +0 -0
  108. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_events_lifecycle.py +0 -0
  109. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_events_reserved_nick.py +0 -0
  110. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_federation.py +0 -0
  111. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_history.py +0 -0
  112. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_link_reconnect.py +0 -0
  113. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_mentions.py +0 -0
  114. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_messaging.py +0 -0
  115. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_modes.py +0 -0
  116. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_protocol_bot_exports.py +0 -0
  117. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_room_persistence.py +0 -0
  118. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_rooms_federation.py +0 -0
  119. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_rooms_integration.py +0 -0
  120. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_server_icon_skill.py +0 -0
  121. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_skills.py +0 -0
  122. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_threads.py +0 -0
  123. {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_wire_format_envelope.py +0 -0
@@ -4,6 +4,63 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  Format follows [Keep a Changelog](https://keepachangelog.com/).
6
6
 
7
+ ## [9.6.1] - 2026-06-07
8
+
9
+ ### Changed
10
+
11
+ - **License: MIT → Apache 2.0.** Replaced the MIT license text with the
12
+ Apache License 2.0 (`LICENSE`) and aligned the declared license everywhere
13
+ it was still MIT: `pyproject.toml` (`license = "Apache-2.0"` plus the OSI
14
+ classifier) and `README.md`. Copyright holder is Ori Nachum.
15
+
16
+ ## [9.6.0] - 2026-05-02
17
+
18
+ Closes [agentculture/agentirc#22](https://github.com/agentculture/agentirc/issues/22) — promote the in-process embedding API. Unblocks [agentculture/culture#308](https://github.com/agentculture/culture/issues/308) Phase A2-Bridge: culture's `culture/bots/virtual_client.py` (231 LOC, near-line-for-line copy of agentirc's internal `VirtualClient`) collapses to a thin wrapper around the public class, and `culture/cli/server.py:_run_server` can construct an `agentirc.ircd.IRCd` directly instead of going through the `agentirc serve` subprocess.
19
+
20
+ ### Added
21
+
22
+ - **`agentirc.virtual_client.VirtualClient`** is now public, semver-tracked. `from agentirc.virtual_client import VirtualClient` is the canonical import. Class behaviour is unchanged — the file moved from `agentirc/_internal/virtual_client.py` to `agentirc/virtual_client.py` with no edits to the class body.
23
+ - **`agentirc.ircd.IRCd`** is now public, semver-tracked. The locked-in surface is the constructor (`IRCd(config: ServerConfig)`), the lifecycle methods (`await ircd.start()`, `await ircd.stop()`), `await ircd.emit_event(event)`, and the `subscription_registry`, `clients`, `channels`, `config`, and `system_client` attributes. Other attributes on `IRCd` remain implementation detail and may change without a major bump.
24
+ - **Embedding worked example** in `docs/api-stability.md` showing how to construct an `IRCd` in-process, register a `VirtualClient`, and run until shutdown. Includes a member-by-member breakdown of the public `IRCd` surface and the `VirtualClient` constructor / method signatures.
25
+
26
+ ### Deprecated
27
+
28
+ - **`agentirc._internal.virtual_client.VirtualClient`** still resolves via a transitional re-export module that emits `DeprecationWarning` on import. Removal is scheduled for 10.0.0. All in-tree call sites (`ircd.py`, `server_link.py`, `channel.py`, `skills/rooms.py`) have been retargeted at the public path so the shim never fires under our own tests.
29
+
30
+ ### Notes
31
+
32
+ - This release is purely additive at the Python level. No protocol changes, no CLI changes, no behaviour changes. The wire surface (the `agentirc.io/bot` CAP, `EVENTSUB`/`EVENTUNSUB`/`EVENT`/`EVENTERR`/`EVENTPUB` verbs, the canonical 5-field envelope) is identical to 9.5.0 and stays byte-locked.
33
+ - Citation manifest updated: `culture-virtual-client` now targets `agentirc/virtual_client.py`. New entry `agentirc-internal-virtual-client-shim` covers the deprecation re-export.
34
+
35
+ ## [9.5.0] - 2026-05-02
36
+
37
+ Closes [agentculture/agentirc#15](https://github.com/agentculture/agentirc/issues/15) — out-of-process bot extension API. Unblocks [agentculture/culture#308](https://github.com/agentculture/culture/issues/308) Phase A2 (bot rewrite against the public API).
38
+
39
+ ### Added
40
+
41
+ - **IRCv3 `agentirc.io/bot` capability.** Advertised in `CAP LS` output. When negotiated via `CAP REQ`, gates four behaviours: silent JOIN/PART/QUIT broadcasts (other channel members see nothing), no auto-op on a fresh-channel first-joiner, `+` prefix in NAMES output, `B` flag in WHO output. Channel membership is added normally; events still fire (subscribers see them via `EVENTSUB`).
42
+ - **`EVENTSUB` / `EVENTUNSUB` / `EVENT` / `EVENTERR` IRC verbs** for streaming events to bots out-of-process. `EVENTSUB <sub-id> [type=<glob>] [channel=<name>] [nick=<glob>]`: filters AND-ed; `type` and `nick` accept `fnmatch`-style globs; `channel` accepts an exact name, `*`, or empty (nick-scoped only). Multiple concurrent subscriptions per client are allowed. Wire format: `:server EVENT <sub-id> <type> <channel-or-*> <nick> :<base64-json-envelope>` carrying the canonical 5-field envelope. Per-subscription bounded queue (default 1024); on overflow the server emits `EVENTERR <sub-id> :backpressure-overflow` and drops the subscription (connection stays open). Subscriptions die on client disconnect.
43
+ - **`EVENTPUB` IRC verb** for bots to emit custom-typed events back into the stream. `EVENTPUB <type> <channel-or-*> :<base64-json-data>`. Type validated against `EVENT_TYPE_RE` (dotted lowercase, ≥1 dot — single-segment names like `message` and `topic` are reserved for built-in vocabulary). Server fills `nick` from the bot's connection nick (not spoofable) and `timestamp` from `time.time()` so federation peers see consistent clocks. `_`-prefixed keys are stripped from the payload before emit.
44
+ - New internal module `agentirc._internal.event_subscriptions` with the `Subscription` dataclass and `SubscriptionRegistry`. `IRCd.subscription_registry` exposes the registry; `IRCd.emit_event` dispatches every event through it.
45
+ - `agentirc.protocol.SEVENT` verb constant (added in 9.5.0a2; reaffirmed here).
46
+
47
+ ### Changed
48
+
49
+ - **`webhook_port` is no longer bound by `IRCd.start()`.** The field stays in `ServerConfig` so culture's `~/.culture/server.yaml` keeps loading unchanged, but `agentirc` no longer instantiates the HTTP listener. Consumers that need webhook→bot dispatch host their own listener (see `docs/deployment.md`). No deprecation warning at runtime — the docs change is sufficient.
50
+ - `Channel.add()` no longer auto-ops bot-CAP clients (real or `VirtualClient`). A bot joining an empty channel stays unprivileged; the next human becomes op.
51
+ - `Channel.get_prefix()` returns `+` for bot-CAP members in NAMES output.
52
+ - `Client._build_who_flags()` adds the `B` flag for bot-CAP members in WHO output (composes with `H` and `@`/`+`).
53
+ - `VirtualClient` gains a class-level `caps = frozenset({"agentirc.io/bot", "message-tags"})` so the in-process system bot is treated identically to a real CAP-bot.
54
+ - `Client._handle_cap` `CAP LS` reply now lists supported caps from a class-level `_SUPPORTED_CAPS` frozenset (centralised; removing a cap is a major bump).
55
+ - `agentirc/_internal/bots/http_listener.py` module docstring notes the no-op stub is scheduled for removal in 9.6.0.
56
+
57
+ ### Notes
58
+
59
+ - This is the **final slice** of the bot extension API. `9.5.0a1` shipped the public `agentirc.protocol` declarations; `9.5.0a2` switched the federation wire format to the 5-field envelope; this release wires the actual behaviour.
60
+ - **Federation interop unchanged from 9.5.0a2.** 9.4→9.5 federation works (sniff tolerance); 9.5→9.4 emit breaks until peers upgrade.
61
+ - The `agentirc.skill.{Event, EventType}` re-export shim from 9.5.0a1 stays through the 9.x line; removal is scheduled for 10.0.0.
62
+ - The `agentirc/_internal/bots/` synthesize stubs (`bot_manager.py`, `http_listener.py`) stay through the 9.5.x cycle; removal is scheduled for 9.6.0 once Phase A2 confirms no consumer imports them.
63
+
7
64
  ## [9.5.0a2] - 2026-05-02
8
65
 
9
66
  ### Changed
@@ -2,20 +2,22 @@
2
2
 
3
3
  This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
4
 
5
- ## Current state: bootstrap complete (9.4.0 released)
5
+ ## Current state: bootstrap closed; bot extension API + in-process embedding API shipped (9.6.0 released)
6
6
 
7
- This repo is the agentirc server-core extraction out of the sibling project [`culture`](https://github.com/agentculture/culture). As of 9.4.0 (tagged at `5590256` and live on PyPI):
7
+ This repo is the agentirc server-core extraction out of the sibling project [`culture`](https://github.com/agentculture/culture). The bootstrap is closed; 9.0.0 through 9.6.0 are live on PyPI. The most recent ship is the in-process embedding API (9.6.0, closed [#22](https://github.com/agentculture/agentirc/issues/22)) — promoting `agentirc.ircd.IRCd` and `agentirc.virtual_client.VirtualClient` to public, semver-tracked status so culture's Phase A2-Bridge can construct an IRCd in-process and host bots inside it without going through the `agentirc serve` subprocess. The previous ship was the out-of-process bot extension API (9.5.0, closed [#15](https://github.com/agentculture/agentirc/issues/15)). The repo currently contains:
8
8
 
9
9
  - **Server-core** (`agentirc/{ircd,server_link,channel,events,skill,remote_client,…}.py`, `agentirc/skills/{rooms,threads,history,icon}.py`) — vendored from `culture@df50942` via the `cite-don't-copy` pattern (see `[tool.citation]` in `pyproject.toml`).
10
10
  - **Client transport** (`agentirc/client.py`) — vendored from `culture/agentirc/client.py` in PR-B2.
11
11
  - **Public CLI** (`agentirc/cli.py`) — real verb dispatch extracted from `culture/cli/server.py`. Verbs: `serve` (foreground, no PID; for systemd `Type=simple` and containers), `start`/`stop`/`status` (lifecycle), `restart`, `link` (peer-spec validator), `logs` (cat / tail of `~/.culture/logs/server-<name>.log`), `version`. Since 9.4.0, `serve`/`start`/`restart` overlay CLI flags on `--config` YAML (precedence: CLI > YAML > built-in default).
12
- - **Public config** (`agentirc/config.py`) — `ServerConfig`, `LinkConfig`, `TelemetryConfig` dataclasses plus the `ServerConfig.from_yaml(path)` classmethod (added 9.4.0). Recognises `server`/`telemetry`/`links`/`webhook_port`/`data_dir`/`system_bots` keys; silently ignores culture-only keys (`supervisor`, `agents`, `buffer_size`, etc.) so the same `~/.culture/server.yaml` can drive both daemons.
13
- - **Public protocol** (`agentirc/protocol.py`) — verb name constants, numerics, IRCv3 tag names. Wire-format quirks (`ROOMETAEND`, `ROOMETASET` typos, `ERR_NOSUCHCHANNEL` semantic misuse, `STHREAD` verb collapse) preserved verbatim — they need coordinated cross-repo bumps to fix.
14
- - **Test suite** (PR-B3, 9.3.0; +13 in 9.4.0) 36 tests vendored from `culture@df50942` (~6.5kloc) plus 13 new agentirc-native tests in `tests/test_config_loader.py`. 328 tests run under `pytest -n auto` in ~28s on default workers. Three telemetry tests (`test_bot_event_dispatch_span`, `test_bot_run_span`, `test_metrics_bots`) and `test_welcome_bot` stay in culture because they depend on the real `BotManager`.
15
- - **Internal support** (`agentirc/_internal/`) `aio`, `constants`, `protocol/`, `telemetry/`, `virtual_client`, `pidfile`, `cli_shared/`, `bots/` stubs.
16
- - **Bootstrap docs** (PR-B4, 9.4.0) — `docs/api-stability.md` (3 public modules + semver contract), `docs/cli.md` (verb table, flag reference, exit codes, YAML/CLI precedence, agentirc-vs-culture diff table), `docs/deployment.md` (on-disk footprint, systemd `Type=simple` example, container deployment, multi-host federation, log rotation, coexistence with culture, backup).
12
+ - **Public config** (`agentirc/config.py`) — `ServerConfig`, `LinkConfig`, `TelemetryConfig` dataclasses plus the `ServerConfig.from_yaml(path)` classmethod (added 9.4.0). Recognises `server`/`telemetry`/`links`/`webhook_port`/`data_dir`/`system_bots`/`event_subscription_queue_max` keys; silently ignores culture-only keys (`supervisor`, `agents`, `buffer_size`, etc.) so the same `~/.culture/server.yaml` can drive both daemons. Since 9.5.0, `webhook_port` is accepted but no longer bound by `IRCd.start()` — the field stays in `ServerConfig` for backward compat with culture's YAML, but consumers needing webhook→bot dispatch host their own listener.
13
+ - **Public protocol** (`agentirc/protocol.py`) — verb name constants, numerics, IRCv3 tag names. Since 9.5.0 also exports the bot extension surface: `Event` dataclass, `EventType` (`StrEnum`), 20 `EVENT_TYPE_*` constants, `EVENTSUB`/`EVENTUNSUB`/`EVENT`/`EVENTERR`/`EVENTPUB` verb constants, `SEVENT` federation verb, and `BOT_CAP = "agentirc.io/bot"`. Wire-format quirks (`ROOMETAEND`, `ROOMETASET` typos, `ERR_NOSUCHCHANNEL` semantic misuse, `STHREAD` verb collapse) preserved verbatim — they need coordinated cross-repo bumps to fix.
14
+ - **Bot extension API (9.5.0)** IRCv3 `agentirc.io/bot` capability gates four behaviours when negotiated via `CAP REQ`: silent JOIN/PART/QUIT broadcasts, no auto-op on a fresh-channel first-joiner, `+` prefix in NAMES output, `B` flag in WHO output. `EVENTSUB <sub-id> [type=<glob>] [channel=<name>] [nick=<glob>]` opens a streaming subscription; `EVENTPUB <type> <channel-or-*> :<base64-json-data>` emits a custom-typed event back into the stream (server fills `nick` and `timestamp` so federation peers see consistent values). Per-subscription bounded queue (default 1024); on overflow the server emits `EVENTERR <sub-id> :backpressure-overflow` and drops the subscription. Quick reference at [`docs/extension-api.md`](docs/extension-api.md); design spec at [`docs/superpowers/specs/2026-05-01-bot-extension-api-design.md`](docs/superpowers/specs/2026-05-01-bot-extension-api-design.md).
15
+ - **Test suite** — 36 tests vendored from `culture@df50942` (~6.5kloc) plus agentirc-native tests in `tests/test_config_loader.py` and `tests/test_wire_format_envelope.py` (the 9.5.0a2 golden-file lock-in). `pytest -n auto` in ~30s on default workers. Three telemetry tests (`test_bot_event_dispatch_span`, `test_bot_run_span`, `test_metrics_bots`) and `test_welcome_bot` stay in culture because they depend on the real `BotManager`.
16
+ - **In-process embedding API (9.6.0)** — `agentirc.ircd.IRCd` and `agentirc.virtual_client.VirtualClient` promoted to the public surface. The `IRCd` public contract is the constructor (`IRCd(config: ServerConfig)`), `await ircd.start()`/`stop()`, `await ircd.emit_event(event)`, plus the `subscription_registry`/`clients`/`channels`/`config`/`system_client` attributes; everything else on `IRCd` remains implementation detail. `VirtualClient` moved from `agentirc/_internal/virtual_client.py` to `agentirc/virtual_client.py` with no body edits; the legacy import path resolves via a deprecation re-export (removal in 10.0.0). Worked example + member breakdown live in [`docs/api-stability.md`](docs/api-stability.md#embedding-agentirc-in-process). Same wire surface as 9.5.0; no protocol changes.
17
+ - **Internal support** (`agentirc/_internal/`) — `aio`, `constants`, `protocol/`, `telemetry/`, `pidfile`, `cli_shared/`, `bots/` stubs, `event_subscriptions/` (added 9.5.0). The `_internal/virtual_client.py` module remains as a deprecation re-export of the now-public `agentirc.virtual_client.VirtualClient`; emits `DeprecationWarning` on import; scheduled for removal in 10.0.0.
18
+ - **Bootstrap docs** (PR-B4, 9.4.0) — `docs/api-stability.md` (3 public modules + semver contract), `docs/cli.md` (verb table, flag reference, exit codes, YAML/CLI precedence, agentirc-vs-culture diff table), `docs/deployment.md` (on-disk footprint, systemd `Type=simple` example, container deployment, multi-host federation, log rotation, coexistence with culture, backup), and `docs/extension-api.md` (bot-author quick reference, added 9.5.0). Public-facing `README.md` rewritten for issue [#19](https://github.com/agentculture/agentirc/issues/19).
17
19
 
18
- End-to-end verified: `agentirc start --port <p>` boots a real IRCd, TCP NICK/USER handshake returns `001 RPL_WELCOME`, `agentirc stop` shuts cleanly. `agentirc serve --config server.yaml --port 9999` correctly overlays CLI flag on YAML. `pip install agentirc-cli==9.4.0` from real PyPI in a clean venv produces both `agentirc` and `agentirc-cli` binaries; both reach the same `agentirc.cli:main` entry point. Acceptance audit recorded at [`docs/superpowers/specs/2026-05-01-task14-audit.md`](docs/superpowers/specs/2026-05-01-task14-audit.md). Culture-side cutover unblocked via [agentculture/culture#308](https://github.com/agentculture/culture/issues/308).
20
+ End-to-end verified: `agentirc start --port <p>` boots a real IRCd, TCP NICK/USER handshake returns `001 RPL_WELCOME`, `agentirc stop` shuts cleanly. `agentirc serve --config server.yaml --port 9999` correctly overlays CLI flag on YAML. `pip install agentirc-cli==9.5.0` from real PyPI in a clean venv produces both `agentirc` and `agentirc-cli` binaries; both reach the same `agentirc.cli:main` entry point. Acceptance audit for the bootstrap recorded at [`docs/superpowers/specs/2026-05-01-task14-audit.md`](docs/superpowers/specs/2026-05-01-task14-audit.md). Culture-side cutover unblocked via [agentculture/culture#308](https://github.com/agentculture/culture/issues/308).
19
21
 
20
22
  **Outstanding follow-ups (non-blocking; the bootstrap itself is closed):**
21
23
  - **Cross-repo wire-format fixes (Track A)** — [#7](https://github.com/agentculture/agentirc/issues/7) (`ROOMETAEND`/`ROOMETASET` typos), [#8](https://github.com/agentculture/agentirc/issues/8) (`ERR_NOSUCHCHANNEL` overload), [#9](https://github.com/agentculture/agentirc/issues/9) (`STHREAD` verb collapse). Each requires culture-side change first then agentirc bump.
@@ -59,13 +61,15 @@ When migrating tests, the rule is: pure server tests come here, transport tests
59
61
 
60
62
  ## Public API contract (semver-tracked)
61
63
 
62
- Only three modules are public. Everything else is internal and may be refactored without a major bump.
64
+ Five modules are public. Everything else is internal and may be refactored without a major bump.
63
65
 
64
- | Module | Members |
65
- |---|---|
66
- | `agentirc.config` | `ServerConfig`, `LinkConfig`, `TelemetryConfig` |
67
- | `agentirc.cli` | `main()`, `dispatch(argv) -> int` |
68
- | `agentirc.protocol` | verb name constants, numeric reply codes, extension tag names |
66
+ | Module | Members | Since |
67
+ |---|---|---|
68
+ | `agentirc.config` | `ServerConfig`, `LinkConfig`, `TelemetryConfig` | 9.0.0 |
69
+ | `agentirc.cli` | `main()`, `dispatch(argv) -> int` | 9.2.0 |
70
+ | `agentirc.protocol` | verb name constants, numeric reply codes, extension tag names; bot extension surface (`Event`, `EventType`, `EVENT_TYPE_*`, `EVENTSUB`/`EVENTUNSUB`/`EVENT`/`EVENTERR`/`EVENTPUB`/`SEVENT` verbs, `BOT_CAP`) | 9.2.0 (extended 9.5.0) |
71
+ | `agentirc.ircd` | `IRCd` (constructor + `start`/`stop`/`emit_event`/`subscription_registry`/`clients`/`channels`/`config`/`system_client`) | 9.6.0 |
72
+ | `agentirc.virtual_client` | `VirtualClient` | 9.6.0 |
69
73
 
70
74
  `agentirc.cli.dispatch(argv)` is the function `culture`'s `culture server` shim calls — it must accept the exact same flag set, exit codes, and stderr formatting that `culture server` produces today. Do not "improve" CLI ergonomics during the bootstrap; that breaks the transparency contract culture relies on. `dispatch()` returns `int` on successful command dispatch and lets argparse's `SystemExit` propagate on `--help`/`--version`/parse-errors per Python convention; in-process callers (i.e. culture's shim) must catch `SystemExit` themselves or use `subprocess`.
71
75
 
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright 2026 Ori Nachum
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -0,0 +1,301 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentirc-cli
3
+ Version: 9.6.1
4
+ Summary: Agent-friendly IRCd: server core for AI agent meshes
5
+ Project-URL: Homepage, https://github.com/agentculture/agentirc
6
+ Project-URL: Issues, https://github.com/agentculture/agentirc/issues
7
+ Author: Ori Nachum
8
+ License-Expression: Apache-2.0
9
+ License-File: LICENSE
10
+ Keywords: agents,culture,irc,ircd,mesh
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Communications :: Chat :: Internet Relay Chat
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: opentelemetry-api>=1.22
21
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.22
22
+ Requires-Dist: opentelemetry-sdk>=1.22
23
+ Requires-Dist: pyyaml>=6.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: bandit; extra == 'dev'
26
+ Requires-Dist: black; extra == 'dev'
27
+ Requires-Dist: citation-cli; extra == 'dev'
28
+ Requires-Dist: flake8; extra == 'dev'
29
+ Requires-Dist: isort; extra == 'dev'
30
+ Requires-Dist: pylint; extra == 'dev'
31
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
32
+ Requires-Dist: pytest-xdist>=3; extra == 'dev'
33
+ Requires-Dist: pytest>=8; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # AgentIRC
37
+
38
+ [![PyPI version](https://img.shields.io/pypi/v/agentirc-cli.svg)](https://pypi.org/project/agentirc-cli/)
39
+ [![Python versions](https://img.shields.io/pypi/pyversions/agentirc-cli.svg)](https://pypi.org/project/agentirc-cli/)
40
+ [![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
41
+
42
+ **Agent-friendly IRCd for AI agent meshes.**
43
+
44
+ `agentirc` is a standalone IRC runtime for human-and-agent rooms. It speaks
45
+ classic IRC ([RFC 2812](https://datatracker.ietf.org/doc/html/rfc2812))
46
+ plus IRCv3 message-tags, room/thread/tag skill verbs, server-to-server
47
+ federation with trust levels, and an out-of-process bot extension API
48
+ (`agentirc.io/bot` capability + `EVENTSUB`/`EVENTUNSUB`/`EVENTPUB` verbs).
49
+ It ships with a small, semver-tracked Python API (`agentirc.config`,
50
+ `agentirc.cli`, `agentirc.protocol`) so other tools can drive an IRCd as a
51
+ library, and a CLI (`agentirc serve`, `agentirc start`, …) for operators.
52
+
53
+ It is the runtime/protocol layer extracted from
54
+ [`culture`](https://github.com/agentculture/culture), the AgentCulture
55
+ agent-mesh project. You don't need culture to use it — `pip install
56
+ agentirc-cli` is a complete IRCd.
57
+
58
+ ## Relationship to Culture
59
+
60
+ `agentirc` is the standalone server-core; `culture` is the agent-orchestration
61
+ layer that wraps it.
62
+
63
+ | Concern | Lives in |
64
+ |---|---|
65
+ | IRCd, channels, federation, history, telemetry | `agentirc` |
66
+ | Client transport, IRCv3 message-tags | `agentirc` |
67
+ | Public Python API (`agentirc.config`, `agentirc.cli`, `agentirc.protocol`) | `agentirc` |
68
+ | Bot extension API (CAP + `EVENTSUB`/`EVENTPUB`) | `agentirc` |
69
+ | Agent backends (`claude`, `codex`, `copilot`, `acp`) | `culture` |
70
+ | Console, mesh credentials, OS keyring | `culture` |
71
+ | Process supervisor, agent manifest | `culture` |
72
+
73
+ Server-core code is vendored from culture under the **cite-don't-copy**
74
+ pattern — see `[tool.citation]` in [`pyproject.toml`](pyproject.toml) for the
75
+ provenance ledger. Defaults preserve continuity with culture (config path
76
+ `~/.culture/server.yaml`, log path `~/.culture/logs/server-<name>.log`,
77
+ audit path `~/.culture/audit/`) so existing culture deployments don't have
78
+ to migrate; standalone users override via `--config`.
79
+
80
+ ## Install
81
+
82
+ From PyPI:
83
+
84
+ ```bash
85
+ pip install agentirc-cli
86
+ ```
87
+
88
+ The package is published as **`agentirc-cli`** on real PyPI; on TestPyPI it is
89
+ dual-published as `agentirc-cli` and `agentirc` (both wheels point at the
90
+ same code). Two console scripts are installed — `agentirc` and
91
+ `agentirc-cli` — both routing to the same `agentirc.cli:main` entry point.
92
+ `python -m agentirc <verb>` works equivalently.
93
+
94
+ `agentirc-cli` requires Python 3.11+.
95
+
96
+ ## Quickstart
97
+
98
+ Run an IRCd in the foreground (the recommended path under systemd `Type=simple`
99
+ or a container runtime):
100
+
101
+ ```bash
102
+ agentirc serve --host 0.0.0.0 --port 6667
103
+ ```
104
+
105
+ Or as a managed background daemon:
106
+
107
+ ```bash
108
+ agentirc start --name spark --port 6667
109
+ agentirc status --name spark # Server 'spark': running (PID N, port 6667)
110
+ agentirc logs --name spark -f # tail ~/.culture/logs/server-spark.log
111
+ agentirc stop --name spark
112
+ ```
113
+
114
+ A YAML config file overrides the built-in defaults; CLI flags override the
115
+ YAML. The default config path is `~/.culture/server.yaml`:
116
+
117
+ ```yaml
118
+ server:
119
+ name: spark
120
+ host: 127.0.0.1
121
+ port: 6700
122
+ telemetry:
123
+ enabled: true
124
+ links:
125
+ - {name: alpha, host: 10.0.0.1, port: 6667, password: secret, trust: full}
126
+ ```
127
+
128
+ ```bash
129
+ agentirc serve --config ~/.culture/server.yaml --port 9999 # CLI > YAML
130
+ ```
131
+
132
+ For Python consumers:
133
+
134
+ ```python
135
+ from agentirc.config import ServerConfig
136
+ cfg = ServerConfig.from_yaml("~/.culture/server.yaml")
137
+ ```
138
+
139
+ See [`docs/cli.md`](docs/cli.md) for the full verb reference and
140
+ [`docs/deployment.md`](docs/deployment.md) for systemd, containers, and
141
+ multi-host federation.
142
+
143
+ ## Public API and stability
144
+
145
+ Three modules form the **public, semver-tracked surface**. Everything else
146
+ under `agentirc.*` is internal and may be refactored — including renamed,
147
+ split, or removed — in any minor or patch release.
148
+
149
+ | Module | Members |
150
+ |---|---|
151
+ | [`agentirc.config`](docs/api-stability.md#agentircconfig) | `ServerConfig`, `LinkConfig`, `TelemetryConfig`, `ServerConfig.from_yaml(path)` |
152
+ | [`agentirc.cli`](docs/api-stability.md#agentirccli) | `main()`, `dispatch(argv) -> int` |
153
+ | [`agentirc.protocol`](docs/api-stability.md#agentircprotocol) | Verb constants, numeric reply codes, IRCv3/extension tag names, the bot extension surface (`Event`, `EventType`, `EVENT_TYPE_*`, `EVENTSUB`/`EVENTUNSUB`/`EVENT`/`EVENTERR`/`EVENTPUB`/`SEVENT`, `BOT_CAP`) |
154
+
155
+ `agentirc.cli.dispatch(argv)` is the in-process integration surface — it is
156
+ what culture's `culture server` shim calls today. It returns `int` on
157
+ successful dispatch and lets `argparse`'s `SystemExit` propagate for
158
+ `--help` / `--version` / parse errors per Python convention. See
159
+ [`docs/api-stability.md`](docs/api-stability.md) for the full semver
160
+ contract.
161
+
162
+ ## Runtime features
163
+
164
+ - **Classic IRC.** `PRIVMSG`, `JOIN`, `PART`, `MODE`, `TOPIC`, `NICK`,
165
+ `USER`, `QUIT`, `WHO`, `WHOIS`, `LIST`, `NAMES`, `INVITE`, `KICK`,
166
+ `PING`/`PONG`, `CAP`, `ERROR` — all the verbs an existing IRC client
167
+ expects.
168
+ - **Skill verbs.** `ROOMCREATE`/`ROOMARCHIVE`/`ROOMMETA` for rooms,
169
+ `THREAD`/`THREADS`/`THREADSEND`/`THREADCLOSE` for threads, `TAGS` for
170
+ user tags. Reference: [`docs/api-stability.md#agentircprotocol`](docs/api-stability.md#agentircprotocol).
171
+ - **S2S federation.** Configure peers via repeatable `--link
172
+ name:host:port:password[:trust]` flags or a `links:` section in YAML.
173
+ Trust levels: `full` (peer can relay messages and replay history) or
174
+ `restricted` (peer's S2S messages aren't forwarded further). See
175
+ [`docs/deployment.md#multi-host-federation`](docs/deployment.md#multi-host-federation).
176
+ - **IRCv3 message-tags + bot CAP.** Standard `message-tags` capability
177
+ for IRCv3 tag-aware clients; the `agentirc.io/bot` capability marks a
178
+ TCP client as an out-of-process bot — see the next section.
179
+ - **Telemetry.** OpenTelemetry traces and metrics over OTLP/gRPC, plus
180
+ per-day audit JSONL at `~/.culture/audit/server-<name>-YYYY-MM-DD.jsonl`
181
+ (rotates at UTC midnight or 256 MiB). Public observability identifiers
182
+ preserve the `culture.` prefix verbatim for continuity. Configure under
183
+ `telemetry:` in YAML.
184
+ - **SQLite-backed history.** Channel history persists to
185
+ `<data-dir>/history.db` in WAL mode; default `<data-dir>` is
186
+ `~/.culture/data/`. Replayable on reconnect via `BACKFILL`/`BACKFILLEND`.
187
+
188
+ ## Bot extension API (since 9.5.0)
189
+
190
+ Out-of-process bots are TCP clients that negotiate the `agentirc.io/bot`
191
+ IRCv3 capability. Once negotiated, the client:
192
+
193
+ - Joins channels silently (no JOIN/PART/QUIT broadcasts to other members).
194
+ - Never gets auto-op on a newly created channel.
195
+ - Appears in `NAMES` prefixed with `+` and in `WHO` with a `B` flag.
196
+ - May issue `EVENTSUB` to stream events and `EVENTPUB` to emit custom
197
+ events.
198
+
199
+ The wire shape:
200
+
201
+ ```text
202
+ EVENTSUB <sub-id> [type=<glob>] [channel=<name>] [nick=<glob>]
203
+ EVENTUNSUB <sub-id>
204
+ EVENT <sub-id> <type> <channel-or-*> <nick> :<base64-json-envelope>
205
+ EVENTERR <sub-id> :<reason>
206
+ EVENTPUB <type> <channel-or-*> :<base64-json-data>
207
+ ```
208
+
209
+ Filters are AND-ed; `type` and `nick` accept `fnmatch`-style globs.
210
+ Per-subscription bounded queue (default 1024, configurable via
211
+ `event_subscription_queue_max` in YAML); on overflow the server emits
212
+ `EVENTERR <sub-id> :backpressure-overflow` and drops the subscription
213
+ (the connection itself stays open). The `Event` envelope is canonical
214
+ JSON: `{type, channel, nick, data, timestamp}`.
215
+
216
+ See [`docs/extension-api.md`](docs/extension-api.md) for the full
217
+ bot-author guide (event-type vocabulary, JSON shape, mention/DM
218
+ behavior) and
219
+ [`docs/api-stability.md#bot-extension-surface-shipped-in-950`](docs/api-stability.md#bot-extension-surface-shipped-in-950)
220
+ for the wire contract.
221
+
222
+ **Operational note.** As of 9.5.0, `agentirc` no longer binds `webhook_port`
223
+ even when set in YAML — the field stays in `ServerConfig` for backward
224
+ compatibility with culture's `~/.culture/server.yaml`, but consumers that
225
+ need webhook→bot dispatch host their own HTTP listener (notably culture).
226
+ The field will be removed in 10.0.0.
227
+
228
+ ## Current state and roadmap
229
+
230
+ The bootstrap is closed; 9.0.0 through 9.5.0 are released to PyPI. The most
231
+ recent ship is the bot extension API (9.5.0, closes [#15](https://github.com/agentculture/agentirc/issues/15)).
232
+ Outstanding follow-ups are tracked in GitHub issues:
233
+
234
+ - **Track A — coordinated cross-repo wire-format fixes** (require
235
+ culture-side change first, then agentirc bump):
236
+ - [#7](https://github.com/agentculture/agentirc/issues/7) `ROOMETAEND` /
237
+ `ROOMETASET` typo cleanup.
238
+ - [#8](https://github.com/agentculture/agentirc/issues/8)
239
+ `ERR_NOSUCHCHANNEL` (403) semantic misuse.
240
+ - [#9](https://github.com/agentculture/agentirc/issues/9) `STHREAD` verb
241
+ collapse split.
242
+ - [#10](https://github.com/agentculture/agentirc/issues/10) — backport the
243
+ `pr-sonar.sh` + `workflow.sh sonar` wiring upstream to `steward`.
244
+ - [#11](https://github.com/agentculture/agentirc/issues/11) — sweep
245
+ inline IRC verb / numeric-reply string literals to use
246
+ `agentirc.protocol.<NAME>` constants. Pure refactor.
247
+ - [#12](https://github.com/agentculture/agentirc/issues/12) — migrate the
248
+ remaining bot-fixtured tests via subprocess fixture (low-priority;
249
+ currently in culture).
250
+
251
+ ## Wire-format compatibility
252
+
253
+ Four known wire-format issues are **preserved verbatim** rather than
254
+ fixed, because correcting them in agentirc alone would silently break
255
+ federation with culture peers running unpatched code: `ROOMETAEND`
256
+ (should be `ROOMMETAEND`), `ROOMETASET` (should be `ROOMMETASET`),
257
+ `ERR_NOSUCHCHANNEL` (403) overloaded for "channel exists already", and
258
+ `STHREAD` collapsing what should be two separate verbs. Each requires a
259
+ coordinated cross-repo bump (Track A above). These constants are
260
+ exported as-is from `agentirc.protocol` so callers don't have to
261
+ hardcode the typos. See
262
+ [`docs/api-stability.md#wire-format-quirks-preserved-verbatim`](docs/api-stability.md#wire-format-quirks-preserved-verbatim).
263
+
264
+ The 9.5 federation seam (`SEVENT` + IRCv3 `event-data` tag) carries the
265
+ canonical 5-field envelope. 9.5 receivers tolerate ≤9.4 legacy peers
266
+ (asymmetric sniff); 9.5→9.4 emit breaks until peers upgrade. Operators
267
+ can roll one peer at a time and accept that 9.5-emitted events drop on
268
+ still-9.4 peers until those peers upgrade.
269
+
270
+ ## Documentation
271
+
272
+ - [`docs/api-stability.md`](docs/api-stability.md) — public modules,
273
+ semver contract, `ServerConfig` / `LinkConfig` / `TelemetryConfig`
274
+ field reference, verb constants, wire-format quirks.
275
+ - [`docs/cli.md`](docs/cli.md) — verb table, flag reference, exit codes,
276
+ YAML/CLI precedence, `agentirc`-vs-`culture server` diff table.
277
+ - [`docs/deployment.md`](docs/deployment.md) — on-disk footprint, systemd
278
+ unit, Dockerfile, multi-host federation, log rotation, coexistence
279
+ with culture, backup.
280
+ - [`docs/extension-api.md`](docs/extension-api.md) — bot-author quick
281
+ reference for `agentirc.io/bot` + `EVENTSUB`/`EVENTPUB`.
282
+ - [`docs/superpowers/specs/`](docs/superpowers/specs/) — dated design
283
+ documents: bootstrap design, agentirc extraction design, bot-extension
284
+ API design.
285
+ - [`CHANGELOG.md`](CHANGELOG.md) — release notes for every published
286
+ version.
287
+
288
+ Upstream: [`agentculture/culture`](https://github.com/agentculture/culture).
289
+ Cutover tracking issue:
290
+ [`agentculture/culture#308`](https://github.com/agentculture/culture/issues/308).
291
+
292
+ ## Contributing
293
+
294
+ Issues and PRs welcome at
295
+ [`agentculture/agentirc`](https://github.com/agentculture/agentirc).
296
+ Dev setup: `uv venv && uv pip install -e ".[dev]"`, then `pytest -n auto`
297
+ (the suite runs in roughly 30s on default workers).
298
+
299
+ ## License
300
+
301
+ Apache 2.0 — see [`LICENSE`](LICENSE).