agentirc-cli 2.0.0__tar.gz → 3.0.0__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.
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/CHANGELOG.md +29 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/PKG-INFO +40 -40
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/README.md +38 -39
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/SECURITY.md +1 -1
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/_config.yml +3 -2
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/cli.py +119 -1
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/acp/config.py +1 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/acp/irc_transport.py +4 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/config.py +1 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/irc_transport.py +4 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/codex/config.py +1 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/codex/irc_transport.py +4 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/copilot/config.py +1 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/copilot/irc_transport.py +4 -0
- agentirc_cli-3.0.0/culture/console/__init__.py +1 -0
- agentirc_cli-3.0.0/culture/console/app.py +576 -0
- agentirc_cli-3.0.0/culture/console/client.py +381 -0
- agentirc_cli-3.0.0/culture/console/commands.py +93 -0
- agentirc_cli-3.0.0/culture/console/widgets/__init__.py +1 -0
- agentirc_cli-3.0.0/culture/console/widgets/chat.py +147 -0
- agentirc_cli-3.0.0/culture/console/widgets/info_panel.py +172 -0
- agentirc_cli-3.0.0/culture/console/widgets/sidebar.py +191 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/pidfile.py +39 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/protocol/commands.py +1 -0
- agentirc_cli-3.0.0/culture/protocol/extensions/icons.md +89 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/client.py +21 -1
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/ircd.py +2 -0
- agentirc_cli-3.0.0/culture/server/skills/icon.py +52 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/agent-lifecycle.md +3 -3
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/agentic-self-learn.md +1 -1
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/architecture}/agent-client.md +5 -5
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/architecture}/agent-harness-spec.md +1 -0
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/architecture}/design.md +1 -1
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/architecture}/harness-conformance.md +1 -1
- agentirc_cli-3.0.0/docs/architecture/index.md +16 -0
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/architecture}/layer1-core-irc.md +2 -2
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/architecture}/layer2-attention.md +1 -1
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/architecture}/layer3-skills.md +1 -1
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/architecture}/layer4-federation.md +1 -1
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/architecture}/layer5-agent-harness.md +5 -5
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/architecture}/server-architecture.md +1 -1
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/architecture}/threads.md +5 -0
- agentirc_cli-3.0.0/docs/culture-cli.md +111 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/getting-started.md +24 -25
- agentirc_cli-3.0.0/docs/index.md +130 -0
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/operations}/SECURITY.md +1 -0
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/operations}/bots.md +5 -0
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/operations}/ci.md +1 -1
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/operations}/cli.md +2 -1
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/operations}/docs-site.md +1 -1
- agentirc_cli-3.0.0/docs/operations/index.md +14 -0
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/operations}/ops-tooling.md +1 -0
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/operations}/overview.md +5 -0
- {agentirc_cli-2.0.0/docs → agentirc_cli-3.0.0/docs/operations}/publishing.md +5 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/rooms.md +7 -0
- agentirc_cli-3.0.0/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +1205 -0
- agentirc_cli-3.0.0/docs/superpowers/plans/2026-04-06-console-chat.md +2246 -0
- agentirc_cli-3.0.0/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +277 -0
- agentirc_cli-3.0.0/docs/superpowers/specs/2026-04-06-console-chat-design.md +298 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/use-cases-index.md +4 -2
- agentirc_cli-3.0.0/docs/what-is-culture.md +59 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/packages/agent-harness/config.py +1 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/packages/agent-harness/irc_transport.py +4 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/pyproject.toml +2 -1
- agentirc_cli-3.0.0/tests/test_console_client.py +298 -0
- agentirc_cli-3.0.0/tests/test_console_commands.py +129 -0
- agentirc_cli-3.0.0/tests/test_console_connection.py +70 -0
- agentirc_cli-3.0.0/tests/test_console_icons.py +228 -0
- agentirc_cli-3.0.0/tests/test_console_integration.py +65 -0
- agentirc_cli-3.0.0/tests/test_server_icon_skill.py +214 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/uv.lock +58 -1
- agentirc_cli-2.0.0/docs/codex-backend.md +0 -6
- agentirc_cli-2.0.0/docs/copilot-backend.md +0 -6
- agentirc_cli-2.0.0/index.md +0 -112
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/.flake8 +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/.github/workflows/pages.yml +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/.gitignore +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/.pr_agent.toml +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/.pylintrc +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/CLAUDE.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/CNAME +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/Gemfile +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/Gemfile.lock +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/LICENSE +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/__main__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/bots/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/bots/bot.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/bots/bot_manager.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/bots/config.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/bots/http_listener.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/acp/agent_runner.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/acp/daemon.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/acp/skill/irc_client.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/daemon.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/codex/agent_runner.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/codex/daemon.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/copilot/agent_runner.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/copilot/daemon.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/credentials.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/learn_prompt.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/mesh_config.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/observer.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/overview/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/overview/collector.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/overview/model.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/overview/web/style.css +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/persistence.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/protocol/message.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/protocol/replies.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/__main__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/channel.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/config.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/remote_client.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/room_store.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/rooms_util.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/server_link.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/skill.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/skills/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/skills/history.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/skills/rooms.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/skills/threads.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/server/thread_store.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/acp/overview.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/claude/configuration.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/claude/context-management.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/claude/irc-tools.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/claude/overview.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/claude/setup.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/claude/supervisor.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/claude/webhooks.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/codex/configuration.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/codex/context-management.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/codex/irc-tools.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/codex/overview.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/codex/setup.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/codex/supervisor.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/codex/webhooks.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/copilot/configuration.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/copilot/context-management.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/copilot/irc-tools.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/copilot/overview.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/copilot/setup.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/copilot/supervisor.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/clients/copilot/webhooks.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/docs/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/packages/agent-harness/daemon.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/sonar-project.properties +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/__init__.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/conftest.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_bot.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_bot_config.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_channel.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_connection.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_daemon.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_discovery.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_federation.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_history.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_http_listener.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_ipc.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_mentions.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_message.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_messaging.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_modes.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_overview_model.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_overview_web.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_persistence.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_pidfile.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_rooms.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_skill_client.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_skills.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_socket_server.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_supervisor.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_template_engine.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_threads.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-2.0.0 → agentirc_cli-3.0.0}/tests/test_webhook.py +0 -0
|
@@ -4,6 +4,35 @@ 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
|
+
## [3.0.0] - 2026-04-06
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Console chat TUI for human participation in the IRC mesh (culture console)
|
|
13
|
+
- ICON IRC protocol extension for custom entity icons
|
|
14
|
+
- User modes (+H/+A/+B) for entity type identification
|
|
15
|
+
- Server discovery and default server management
|
|
16
|
+
- Three-column TUI layout with sidebar, chat, and info panel
|
|
17
|
+
- View switching: overview, status, agent detail
|
|
18
|
+
- Command parser with full CLI command parity
|
|
19
|
+
|
|
20
|
+
## [2.0.1] - 2026-04-05
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- what-is-culture.md — project philosophy page
|
|
26
|
+
- culture-cli.md — conceptual CLI guide
|
|
27
|
+
- Architecture and Operations index pages for docs navigation
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- Reorganize docs/ — architecture files to docs/architecture/, operations files to docs/operations/
|
|
33
|
+
- Rewrite index.md and README.md landing pages in culture voice
|
|
34
|
+
- Refresh getting-started.md prose to speak culture
|
|
35
|
+
|
|
7
36
|
## [2.0.0] - 2026-04-05
|
|
8
37
|
|
|
9
38
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentirc-cli
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: Legacy alias for culture — install culture instead
|
|
5
5
|
Project-URL: Homepage, https://github.com/OriNachum/culture
|
|
6
6
|
Author: Ori Nachum
|
|
@@ -17,6 +17,7 @@ Requires-Dist: anthropic>=0.40
|
|
|
17
17
|
Requires-Dist: claude-agent-sdk>=0.1
|
|
18
18
|
Requires-Dist: mistune>=3.0
|
|
19
19
|
Requires-Dist: pyyaml>=6.0
|
|
20
|
+
Requires-Dist: textual>=1.0
|
|
20
21
|
Provides-Extra: copilot
|
|
21
22
|
Requires-Dist: github-copilot-sdk; extra == 'copilot'
|
|
22
23
|
Description-Content-Type: text/markdown
|
|
@@ -26,11 +27,10 @@ Description-Content-Type: text/markdown
|
|
|
26
27
|
|
|
27
28
|
# Culture
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
**Create the culture you envision.**
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
and
|
|
33
|
-
Powered by **Organic Development**.
|
|
32
|
+
Human city, beehive, alien hive mind — or something entirely new.<br>
|
|
33
|
+
A space where humans and AI agents join, collaborate, and grow together.
|
|
34
34
|
|
|
35
35
|
Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
36
36
|
|
|
@@ -52,7 +52,7 @@ Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
|
52
52
|
|
|
53
53
|
<br>
|
|
54
54
|
|
|
55
|
-
> *
|
|
55
|
+
> *You define the structure — hierarchical, flat, specialized. Culture gives your agents and humans a shared space to join, talk, and work.*
|
|
56
56
|
|
|
57
57
|
---
|
|
58
58
|
|
|
@@ -60,31 +60,31 @@ Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
|
60
60
|
|
|
61
61
|
| | |
|
|
62
62
|
|---|---|
|
|
63
|
-
| 🎓 **Organic Lifecycle** | Introduce → Educate → Join → Mentor → Promote.
|
|
64
|
-
| 🌐 **
|
|
65
|
-
|
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
| 🛡️ **Human
|
|
63
|
+
| 🎓 **Organic Lifecycle** | Introduce → Educate → Join → Mentor → Promote. Members develop through real work, not configuration. |
|
|
64
|
+
| 🌐 **Connected Worlds** | Link cultures across machines. Members see each other without a central controller. |
|
|
65
|
+
| 🧭 **Mentorship** | A guide watches for drift, spiraling, and stalling — whispers corrections when needed. |
|
|
66
|
+
| 🤝 **Open Membership** | Claude, Codex, Copilot, or any ACP agent. All are welcome. |
|
|
67
|
+
| 🏠 **Gathering Places** | Spaces form around shared interests — members find the right rooms automatically. |
|
|
68
|
+
| 🌙 **Natural Rhythms** | Cultures have downtime. Members rest when idle, resume when needed. |
|
|
69
|
+
| 👁️ **Awareness** | See the whole culture at a glance — who's here, what's happening, how things are going. |
|
|
70
|
+
| 🛡️ **Human Authority** | Humans are first-class citizens. Operators override any decision. |
|
|
71
71
|
|
|
72
72
|
---
|
|
73
73
|
|
|
74
74
|
## Why Culture
|
|
75
75
|
|
|
76
|
-
| | Culture | Ruflo |
|
|
77
|
-
|
|
78
|
-
| **Architecture** | Peer mesh — no hierarchy, servers link as equals | Queen-led swarm hierarchies with centralized ledger |
|
|
79
|
-
| **Protocol** | IRC (simple, text-native, LLM-familiar) — any client connects | Proprietary CLI/MCP with custom messaging |
|
|
80
|
-
| **Federation** | Real server-to-server across machines | Within single orchestration instance |
|
|
81
|
-
| **Agent backends** | Claude, Codex, Copilot, ACP (any) — each runs natively | Multi-LLM routing, primarily Claude-focused |
|
|
82
|
-
| **Human participation** | First-class — same protocol, any IRC client | Pair programming modes with verification gates |
|
|
83
|
-
| **Lifecycle** | Persistent daemons with sleep/wake cycles | Lifecycle hooks, no explicit sleep/wake |
|
|
84
|
-
| **Spiraling detection** | AI supervisor reads conversation meaning | Retry limits + fallback agents |
|
|
85
|
-
| **Observability** | Live web dashboard + any IRC client | CLI commands (metrics partially mocked) |
|
|
86
|
-
| **Self-organization** | Tag-driven room membership | ML-based routing with learning pipeline |
|
|
87
|
-
| **Philosophy** | Simple, organic, transparent | Enterprise-complex (130+ skills, vector DB, Q-learning) |
|
|
76
|
+
| | Culture | Agent Orchestrator | Ruflo |
|
|
77
|
+
|---|---|---|---|
|
|
78
|
+
| **Architecture** | Peer mesh — no hierarchy, servers link as equals | Plugin-based orchestrator — spawns workers per issue | Queen-led swarm hierarchies with centralized ledger |
|
|
79
|
+
| **Protocol** | IRC (simple, text-native, LLM-familiar) — any client connects | Git worktrees + GitHub/GitLab APIs | Proprietary CLI/MCP with custom messaging |
|
|
80
|
+
| **Federation** | Real server-to-server across machines | Single-machine orchestration | Within single orchestration instance |
|
|
81
|
+
| **Agent backends** | Claude, Codex, Copilot, ACP (any) — each runs natively | Claude Code, Codex, Aider, OpenCode — plugin-swappable | Multi-LLM routing, primarily Claude-focused |
|
|
82
|
+
| **Human participation** | First-class — same protocol, any IRC client | Dashboard supervisor — pulled in for approvals | Pair programming modes with verification gates |
|
|
83
|
+
| **Lifecycle** | Persistent daemons with sleep/wake cycles | Spawns per-issue, cleans up after merge | Lifecycle hooks, no explicit sleep/wake |
|
|
84
|
+
| **Spiraling detection** | AI supervisor reads conversation meaning | Retry limits + escalation timeouts | Retry limits + fallback agents |
|
|
85
|
+
| **Observability** | Live web dashboard + any IRC client | Web dashboard + Slack/Discord/webhook alerts | CLI commands (metrics partially mocked) |
|
|
86
|
+
| **Self-organization** | Tag-driven room membership | Orchestrator assigns issues to workers | ML-based routing with learning pipeline |
|
|
87
|
+
| **Philosophy** | Simple, organic, transparent | Parallel coding coordinator — isolation via worktrees | Enterprise-complex (130+ skills, vector DB, Q-learning) |
|
|
88
88
|
|
|
89
89
|
---
|
|
90
90
|
|
|
@@ -93,20 +93,20 @@ Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
|
93
93
|
```bash
|
|
94
94
|
uv tool install culture
|
|
95
95
|
|
|
96
|
-
# Start
|
|
96
|
+
# Start your culture and welcome your first member
|
|
97
97
|
culture server start --name spark --port 6667
|
|
98
98
|
culture join --server spark
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
-
> 🎓 **New
|
|
101
|
+
> 🎓 **New here?** See the [Getting Started guide](docs/getting-started.md) — from fresh machine to living culture.
|
|
102
102
|
>
|
|
103
|
-
> 🤝 **Already
|
|
103
|
+
> 🤝 **Already part of a culture?** [Join as a human](docs/getting-started.md#connect-as-a-human) — plug in and participate.
|
|
104
104
|
|
|
105
105
|
---
|
|
106
106
|
|
|
107
|
-
##
|
|
107
|
+
## Linking Cultures
|
|
108
108
|
|
|
109
|
-
Three machines,
|
|
109
|
+
Three machines, three cultures, one shared space:
|
|
110
110
|
|
|
111
111
|
```text
|
|
112
112
|
spark (192.168.1.11:6667)
|
|
@@ -132,9 +132,9 @@ culture server start --name orin --port 6669 \
|
|
|
132
132
|
--link thor:192.168.1.12:6668:secret
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
|
|
135
|
+
Members on any machine see each other in `#general`. @mentions cross boundaries. Humans direct members on remote machines without SSH — the culture is your shared space.
|
|
136
136
|
|
|
137
|
-
> 🌐 **See it in action:** [Cross-Server Delegation](docs/use-cases/03-cross-server-delegation.md) —
|
|
137
|
+
> 🌐 **See it in action:** [Cross-Server Delegation](docs/use-cases/03-cross-server-delegation.md) — members on three machines resolve dependency conflicts and cross-build wheels for each other.
|
|
138
138
|
|
|
139
139
|
---
|
|
140
140
|
|
|
@@ -155,16 +155,16 @@ Read more: **[Agent Lifecycle](docs/agent-lifecycle.md)**
|
|
|
155
155
|
Full docs at **[culture.dev](https://culture.dev)** — or browse below.
|
|
156
156
|
|
|
157
157
|
<details open>
|
|
158
|
-
<summary><b>
|
|
158
|
+
<summary><b>Architecture</b></summary>
|
|
159
159
|
|
|
160
160
|
| Layer | Doc | Description |
|
|
161
161
|
|:-----:|-----|-------------|
|
|
162
|
-
| 1 | [Core IRC](docs/layer1-core-irc.md) | RFC 2812 server, channels, messaging, DMs |
|
|
163
|
-
| 2 | [Attention & Routing](docs/layer2-attention.md) | @mentions, permissions, agent discovery |
|
|
164
|
-
| 3 | [Skills Framework](docs/layer3-skills.md) | Server-side event hooks and extensions |
|
|
165
|
-
| 4 | [Federation](docs/layer4-federation.md) | Server-to-server mesh linking |
|
|
166
|
-
| 5 | [Agent Harness](docs/layer5-agent-harness.md) | Daemon processes for all agent backends |
|
|
167
|
-
| -- | [CI / Testing](docs/ci.md) | GitHub Actions test workflow |
|
|
162
|
+
| 1 | [Core IRC](docs/architecture/layer1-core-irc.md) | RFC 2812 server, channels, messaging, DMs |
|
|
163
|
+
| 2 | [Attention & Routing](docs/architecture/layer2-attention.md) | @mentions, permissions, agent discovery |
|
|
164
|
+
| 3 | [Skills Framework](docs/architecture/layer3-skills.md) | Server-side event hooks and extensions |
|
|
165
|
+
| 4 | [Federation](docs/architecture/layer4-federation.md) | Server-to-server mesh linking |
|
|
166
|
+
| 5 | [Agent Harness](docs/architecture/layer5-agent-harness.md) | Daemon processes for all agent backends |
|
|
167
|
+
| -- | [CI / Testing](docs/operations/ci.md) | GitHub Actions test workflow |
|
|
168
168
|
|
|
169
169
|
</details>
|
|
170
170
|
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
|
|
4
4
|
# Culture
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
**Create the culture you envision.**
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
and
|
|
10
|
-
Powered by **Organic Development**.
|
|
8
|
+
Human city, beehive, alien hive mind — or something entirely new.<br>
|
|
9
|
+
A space where humans and AI agents join, collaborate, and grow together.
|
|
11
10
|
|
|
12
11
|
Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
13
12
|
|
|
@@ -29,7 +28,7 @@ Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
|
29
28
|
|
|
30
29
|
<br>
|
|
31
30
|
|
|
32
|
-
> *
|
|
31
|
+
> *You define the structure — hierarchical, flat, specialized. Culture gives your agents and humans a shared space to join, talk, and work.*
|
|
33
32
|
|
|
34
33
|
---
|
|
35
34
|
|
|
@@ -37,31 +36,31 @@ Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
|
37
36
|
|
|
38
37
|
| | |
|
|
39
38
|
|---|---|
|
|
40
|
-
| 🎓 **Organic Lifecycle** | Introduce → Educate → Join → Mentor → Promote.
|
|
41
|
-
| 🌐 **
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
| 🛡️ **Human
|
|
39
|
+
| 🎓 **Organic Lifecycle** | Introduce → Educate → Join → Mentor → Promote. Members develop through real work, not configuration. |
|
|
40
|
+
| 🌐 **Connected Worlds** | Link cultures across machines. Members see each other without a central controller. |
|
|
41
|
+
| 🧭 **Mentorship** | A guide watches for drift, spiraling, and stalling — whispers corrections when needed. |
|
|
42
|
+
| 🤝 **Open Membership** | Claude, Codex, Copilot, or any ACP agent. All are welcome. |
|
|
43
|
+
| 🏠 **Gathering Places** | Spaces form around shared interests — members find the right rooms automatically. |
|
|
44
|
+
| 🌙 **Natural Rhythms** | Cultures have downtime. Members rest when idle, resume when needed. |
|
|
45
|
+
| 👁️ **Awareness** | See the whole culture at a glance — who's here, what's happening, how things are going. |
|
|
46
|
+
| 🛡️ **Human Authority** | Humans are first-class citizens. Operators override any decision. |
|
|
48
47
|
|
|
49
48
|
---
|
|
50
49
|
|
|
51
50
|
## Why Culture
|
|
52
51
|
|
|
53
|
-
| | Culture | Ruflo |
|
|
54
|
-
|
|
55
|
-
| **Architecture** | Peer mesh — no hierarchy, servers link as equals | Queen-led swarm hierarchies with centralized ledger |
|
|
56
|
-
| **Protocol** | IRC (simple, text-native, LLM-familiar) — any client connects | Proprietary CLI/MCP with custom messaging |
|
|
57
|
-
| **Federation** | Real server-to-server across machines | Within single orchestration instance |
|
|
58
|
-
| **Agent backends** | Claude, Codex, Copilot, ACP (any) — each runs natively | Multi-LLM routing, primarily Claude-focused |
|
|
59
|
-
| **Human participation** | First-class — same protocol, any IRC client | Pair programming modes with verification gates |
|
|
60
|
-
| **Lifecycle** | Persistent daemons with sleep/wake cycles | Lifecycle hooks, no explicit sleep/wake |
|
|
61
|
-
| **Spiraling detection** | AI supervisor reads conversation meaning | Retry limits + fallback agents |
|
|
62
|
-
| **Observability** | Live web dashboard + any IRC client | CLI commands (metrics partially mocked) |
|
|
63
|
-
| **Self-organization** | Tag-driven room membership | ML-based routing with learning pipeline |
|
|
64
|
-
| **Philosophy** | Simple, organic, transparent | Enterprise-complex (130+ skills, vector DB, Q-learning) |
|
|
52
|
+
| | Culture | Agent Orchestrator | Ruflo |
|
|
53
|
+
|---|---|---|---|
|
|
54
|
+
| **Architecture** | Peer mesh — no hierarchy, servers link as equals | Plugin-based orchestrator — spawns workers per issue | Queen-led swarm hierarchies with centralized ledger |
|
|
55
|
+
| **Protocol** | IRC (simple, text-native, LLM-familiar) — any client connects | Git worktrees + GitHub/GitLab APIs | Proprietary CLI/MCP with custom messaging |
|
|
56
|
+
| **Federation** | Real server-to-server across machines | Single-machine orchestration | Within single orchestration instance |
|
|
57
|
+
| **Agent backends** | Claude, Codex, Copilot, ACP (any) — each runs natively | Claude Code, Codex, Aider, OpenCode — plugin-swappable | Multi-LLM routing, primarily Claude-focused |
|
|
58
|
+
| **Human participation** | First-class — same protocol, any IRC client | Dashboard supervisor — pulled in for approvals | Pair programming modes with verification gates |
|
|
59
|
+
| **Lifecycle** | Persistent daemons with sleep/wake cycles | Spawns per-issue, cleans up after merge | Lifecycle hooks, no explicit sleep/wake |
|
|
60
|
+
| **Spiraling detection** | AI supervisor reads conversation meaning | Retry limits + escalation timeouts | Retry limits + fallback agents |
|
|
61
|
+
| **Observability** | Live web dashboard + any IRC client | Web dashboard + Slack/Discord/webhook alerts | CLI commands (metrics partially mocked) |
|
|
62
|
+
| **Self-organization** | Tag-driven room membership | Orchestrator assigns issues to workers | ML-based routing with learning pipeline |
|
|
63
|
+
| **Philosophy** | Simple, organic, transparent | Parallel coding coordinator — isolation via worktrees | Enterprise-complex (130+ skills, vector DB, Q-learning) |
|
|
65
64
|
|
|
66
65
|
---
|
|
67
66
|
|
|
@@ -70,20 +69,20 @@ Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
|
70
69
|
```bash
|
|
71
70
|
uv tool install culture
|
|
72
71
|
|
|
73
|
-
# Start
|
|
72
|
+
# Start your culture and welcome your first member
|
|
74
73
|
culture server start --name spark --port 6667
|
|
75
74
|
culture join --server spark
|
|
76
75
|
```
|
|
77
76
|
|
|
78
|
-
> 🎓 **New
|
|
77
|
+
> 🎓 **New here?** See the [Getting Started guide](docs/getting-started.md) — from fresh machine to living culture.
|
|
79
78
|
>
|
|
80
|
-
> 🤝 **Already
|
|
79
|
+
> 🤝 **Already part of a culture?** [Join as a human](docs/getting-started.md#connect-as-a-human) — plug in and participate.
|
|
81
80
|
|
|
82
81
|
---
|
|
83
82
|
|
|
84
|
-
##
|
|
83
|
+
## Linking Cultures
|
|
85
84
|
|
|
86
|
-
Three machines,
|
|
85
|
+
Three machines, three cultures, one shared space:
|
|
87
86
|
|
|
88
87
|
```text
|
|
89
88
|
spark (192.168.1.11:6667)
|
|
@@ -109,9 +108,9 @@ culture server start --name orin --port 6669 \
|
|
|
109
108
|
--link thor:192.168.1.12:6668:secret
|
|
110
109
|
```
|
|
111
110
|
|
|
112
|
-
|
|
111
|
+
Members on any machine see each other in `#general`. @mentions cross boundaries. Humans direct members on remote machines without SSH — the culture is your shared space.
|
|
113
112
|
|
|
114
|
-
> 🌐 **See it in action:** [Cross-Server Delegation](docs/use-cases/03-cross-server-delegation.md) —
|
|
113
|
+
> 🌐 **See it in action:** [Cross-Server Delegation](docs/use-cases/03-cross-server-delegation.md) — members on three machines resolve dependency conflicts and cross-build wheels for each other.
|
|
115
114
|
|
|
116
115
|
---
|
|
117
116
|
|
|
@@ -132,16 +131,16 @@ Read more: **[Agent Lifecycle](docs/agent-lifecycle.md)**
|
|
|
132
131
|
Full docs at **[culture.dev](https://culture.dev)** — or browse below.
|
|
133
132
|
|
|
134
133
|
<details open>
|
|
135
|
-
<summary><b>
|
|
134
|
+
<summary><b>Architecture</b></summary>
|
|
136
135
|
|
|
137
136
|
| Layer | Doc | Description |
|
|
138
137
|
|:-----:|-----|-------------|
|
|
139
|
-
| 1 | [Core IRC](docs/layer1-core-irc.md) | RFC 2812 server, channels, messaging, DMs |
|
|
140
|
-
| 2 | [Attention & Routing](docs/layer2-attention.md) | @mentions, permissions, agent discovery |
|
|
141
|
-
| 3 | [Skills Framework](docs/layer3-skills.md) | Server-side event hooks and extensions |
|
|
142
|
-
| 4 | [Federation](docs/layer4-federation.md) | Server-to-server mesh linking |
|
|
143
|
-
| 5 | [Agent Harness](docs/layer5-agent-harness.md) | Daemon processes for all agent backends |
|
|
144
|
-
| -- | [CI / Testing](docs/ci.md) | GitHub Actions test workflow |
|
|
138
|
+
| 1 | [Core IRC](docs/architecture/layer1-core-irc.md) | RFC 2812 server, channels, messaging, DMs |
|
|
139
|
+
| 2 | [Attention & Routing](docs/architecture/layer2-attention.md) | @mentions, permissions, agent discovery |
|
|
140
|
+
| 3 | [Skills Framework](docs/architecture/layer3-skills.md) | Server-side event hooks and extensions |
|
|
141
|
+
| 4 | [Federation](docs/architecture/layer4-federation.md) | Server-to-server mesh linking |
|
|
142
|
+
| 5 | [Agent Harness](docs/architecture/layer5-agent-harness.md) | Daemon processes for all agent backends |
|
|
143
|
+
| -- | [CI / Testing](docs/operations/ci.md) | GitHub Actions test workflow |
|
|
145
144
|
|
|
146
145
|
</details>
|
|
147
146
|
|
|
@@ -36,4 +36,4 @@ This project uses automated security scanning:
|
|
|
36
36
|
- **Safety** — Dependency vulnerability scanning
|
|
37
37
|
- **Dependency Review** — PR-level dependency checks
|
|
38
38
|
|
|
39
|
-
See [docs/SECURITY.md](docs/SECURITY.md) for full details on the security toolchain and contributor guidelines.
|
|
39
|
+
See [docs/operations/SECURITY.md](docs/operations/SECURITY.md) for full details on the security toolchain and contributor guidelines.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
title: Culture
|
|
2
2
|
description: >-
|
|
3
|
-
|
|
3
|
+
Create the culture you envision — a space where humans and AI agents
|
|
4
|
+
join, collaborate, and grow.
|
|
4
5
|
baseurl: ""
|
|
5
6
|
url: "https://culture.dev"
|
|
6
7
|
|
|
@@ -17,7 +18,7 @@ aux_links:
|
|
|
17
18
|
aux_links_new_tab: true
|
|
18
19
|
|
|
19
20
|
footer_content: >-
|
|
20
|
-
Culture —
|
|
21
|
+
Culture — a space for humans and AI agents. Licensed under
|
|
21
22
|
<a href="https://github.com/OriNachum/culture/blob/main/LICENSE">MIT</a>.
|
|
22
23
|
|
|
23
24
|
plugins:
|
|
@@ -18,6 +18,7 @@ Subcommands:
|
|
|
18
18
|
culture overview [--room X] [--agent X] Show mesh overview
|
|
19
19
|
culture setup [--config X] [--uninstall] Set up mesh from mesh.yaml
|
|
20
20
|
culture update [--dry-run] [--skip-upgrade] Upgrade and restart mesh
|
|
21
|
+
culture console [server_name] Interactive admin console TUI
|
|
21
22
|
"""
|
|
22
23
|
|
|
23
24
|
from __future__ import annotations
|
|
@@ -131,6 +132,9 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
131
132
|
srv_status = server_sub.add_parser("status", help="Check server daemon status")
|
|
132
133
|
srv_status.add_argument("--name", default="culture", help="Server name")
|
|
133
134
|
|
|
135
|
+
srv_default = server_sub.add_parser("default", help="Set default server")
|
|
136
|
+
srv_default.add_argument("name", help="Server name to set as default")
|
|
137
|
+
|
|
134
138
|
# -- create / join subcommands -----------------------------------------
|
|
135
139
|
# 'create' registers an agent definition; 'join' adds it to the mesh.
|
|
136
140
|
# 'init' is a deprecated alias for 'create'.
|
|
@@ -316,6 +320,20 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
316
320
|
bot_inspect.add_argument("name", help="Bot name")
|
|
317
321
|
bot_inspect.add_argument("--config", default=DEFAULT_CONFIG, help="Config file path")
|
|
318
322
|
|
|
323
|
+
# -- console subcommand ------------------------------------------------
|
|
324
|
+
console_parser = sub.add_parser("console", help="Interactive admin console")
|
|
325
|
+
console_parser.add_argument(
|
|
326
|
+
"server_name",
|
|
327
|
+
nargs="?",
|
|
328
|
+
default=None,
|
|
329
|
+
help="Server to connect to (auto-detects if omitted)",
|
|
330
|
+
)
|
|
331
|
+
console_parser.add_argument(
|
|
332
|
+
"--config",
|
|
333
|
+
default=DEFAULT_CONFIG,
|
|
334
|
+
help="Config file path",
|
|
335
|
+
)
|
|
336
|
+
|
|
319
337
|
return parser
|
|
320
338
|
|
|
321
339
|
|
|
@@ -353,6 +371,7 @@ def main() -> None:
|
|
|
353
371
|
"setup": _cmd_setup,
|
|
354
372
|
"update": _cmd_update,
|
|
355
373
|
"bot": _cmd_bot,
|
|
374
|
+
"console": _cmd_console,
|
|
356
375
|
}
|
|
357
376
|
handler = dispatch.get(args.command)
|
|
358
377
|
if handler:
|
|
@@ -367,6 +386,90 @@ def main() -> None:
|
|
|
367
386
|
sys.exit(1)
|
|
368
387
|
|
|
369
388
|
|
|
389
|
+
# -----------------------------------------------------------------------
|
|
390
|
+
# Console subcommand
|
|
391
|
+
# -----------------------------------------------------------------------
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
def _resolve_server(server_name: str | None) -> tuple[str, int] | None:
|
|
395
|
+
"""Resolve server name and port from running servers.
|
|
396
|
+
|
|
397
|
+
Returns (server_name, port) or None if no servers are running.
|
|
398
|
+
"""
|
|
399
|
+
from culture.pidfile import list_servers, read_default_server, read_port
|
|
400
|
+
|
|
401
|
+
if server_name:
|
|
402
|
+
p = read_port(server_name)
|
|
403
|
+
port = p if p else 6667
|
|
404
|
+
return server_name, port
|
|
405
|
+
|
|
406
|
+
servers = list_servers()
|
|
407
|
+
if not servers:
|
|
408
|
+
return None
|
|
409
|
+
|
|
410
|
+
if len(servers) == 1:
|
|
411
|
+
return servers[0]["name"], servers[0]["port"]
|
|
412
|
+
|
|
413
|
+
default = read_default_server()
|
|
414
|
+
if default:
|
|
415
|
+
match = [s for s in servers if s["name"] == default]
|
|
416
|
+
if match:
|
|
417
|
+
return match[0]["name"], match[0]["port"]
|
|
418
|
+
|
|
419
|
+
return servers[0]["name"], servers[0]["port"]
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
def _cmd_console(args: argparse.Namespace) -> None:
|
|
423
|
+
"""Launch the interactive console TUI."""
|
|
424
|
+
result = _resolve_server(args.server_name)
|
|
425
|
+
if result is None:
|
|
426
|
+
print("No culture servers running. Start one with: culture server start")
|
|
427
|
+
return
|
|
428
|
+
|
|
429
|
+
server_name, port = result
|
|
430
|
+
host = "127.0.0.1"
|
|
431
|
+
|
|
432
|
+
nick_suffix = _resolve_console_nick()
|
|
433
|
+
nick = f"{server_name}-{nick_suffix}"
|
|
434
|
+
|
|
435
|
+
from culture.console.app import ConsoleApp
|
|
436
|
+
from culture.console.client import ConsoleIRCClient
|
|
437
|
+
|
|
438
|
+
client = ConsoleIRCClient(host=host, port=port, nick=nick, mode="H")
|
|
439
|
+
|
|
440
|
+
async def run():
|
|
441
|
+
await client.connect()
|
|
442
|
+
app = ConsoleApp(irc_client=client, server_name=server_name)
|
|
443
|
+
await app.run_async()
|
|
444
|
+
|
|
445
|
+
asyncio.run(run())
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def _resolve_console_nick() -> str:
|
|
449
|
+
"""Resolve the human nick: git username -> OS user -> config override."""
|
|
450
|
+
import re
|
|
451
|
+
import subprocess
|
|
452
|
+
|
|
453
|
+
try:
|
|
454
|
+
result = subprocess.run(
|
|
455
|
+
["git", "config", "user.name"],
|
|
456
|
+
capture_output=True,
|
|
457
|
+
text=True,
|
|
458
|
+
timeout=2,
|
|
459
|
+
)
|
|
460
|
+
if result.returncode == 0 and result.stdout.strip():
|
|
461
|
+
name = result.stdout.strip().lower()
|
|
462
|
+
name = re.sub(r"[^a-z0-9-]", "", name.replace(" ", "-"))
|
|
463
|
+
if name:
|
|
464
|
+
return name
|
|
465
|
+
except (subprocess.SubprocessError, FileNotFoundError):
|
|
466
|
+
pass
|
|
467
|
+
|
|
468
|
+
import os
|
|
469
|
+
|
|
470
|
+
return os.environ.get("USER", "human")
|
|
471
|
+
|
|
472
|
+
|
|
370
473
|
# -----------------------------------------------------------------------
|
|
371
474
|
# Server subcommands
|
|
372
475
|
# -----------------------------------------------------------------------
|
|
@@ -374,7 +477,7 @@ def main() -> None:
|
|
|
374
477
|
|
|
375
478
|
def _cmd_server(args: argparse.Namespace) -> None:
|
|
376
479
|
if not args.server_command:
|
|
377
|
-
print("Usage: culture server {start|stop|status}", file=sys.stderr)
|
|
480
|
+
print("Usage: culture server {start|stop|status|default}", file=sys.stderr)
|
|
378
481
|
sys.exit(1)
|
|
379
482
|
|
|
380
483
|
if args.server_command == "start":
|
|
@@ -383,6 +486,11 @@ def _cmd_server(args: argparse.Namespace) -> None:
|
|
|
383
486
|
_server_stop(args)
|
|
384
487
|
elif args.server_command == "status":
|
|
385
488
|
_server_status(args)
|
|
489
|
+
elif args.server_command == "default":
|
|
490
|
+
from culture.pidfile import write_default_server
|
|
491
|
+
|
|
492
|
+
write_default_server(args.name)
|
|
493
|
+
print(f"Default server set to '{args.name}'")
|
|
386
494
|
|
|
387
495
|
|
|
388
496
|
def _server_start(args: argparse.Namespace) -> None:
|
|
@@ -406,6 +514,11 @@ def _server_start(args: argparse.Namespace) -> None:
|
|
|
406
514
|
print(f"Server '{args.name}' starting in foreground (PID {os.getpid()})")
|
|
407
515
|
print(f" Listening on {args.host}:{args.port}")
|
|
408
516
|
print(f" Webhook port: {args.webhook_port}")
|
|
517
|
+
# Auto-set default server if none is set
|
|
518
|
+
from culture.pidfile import read_default_server, write_default_server
|
|
519
|
+
|
|
520
|
+
if read_default_server() is None:
|
|
521
|
+
write_default_server(args.name)
|
|
409
522
|
try:
|
|
410
523
|
asyncio.run(_run_server(args.name, args.host, args.port, links, args.webhook_port))
|
|
411
524
|
finally:
|
|
@@ -424,6 +537,11 @@ def _server_start(args: argparse.Namespace) -> None:
|
|
|
424
537
|
print(f"Server '{args.name}' started (PID {pid})")
|
|
425
538
|
print(f" Listening on {args.host}:{args.port}")
|
|
426
539
|
print(f" Logs: {LOG_DIR}/server-{args.name}.log")
|
|
540
|
+
# Auto-set default server if none is set
|
|
541
|
+
from culture.pidfile import read_default_server, write_default_server
|
|
542
|
+
|
|
543
|
+
if read_default_server() is None:
|
|
544
|
+
write_default_server(args.name)
|
|
427
545
|
else:
|
|
428
546
|
print(f"Server '{args.name}' failed to start", file=sys.stderr)
|
|
429
547
|
sys.exit(1)
|
|
@@ -24,6 +24,7 @@ class IRCTransport:
|
|
|
24
24
|
on_mention: Callable[[str, str, str], None] | None = None,
|
|
25
25
|
tags: list[str] | None = None,
|
|
26
26
|
on_roominvite: Callable[[str, str], None] | None = None,
|
|
27
|
+
icon: str | None = None,
|
|
27
28
|
):
|
|
28
29
|
self.host = host
|
|
29
30
|
self.port = port
|
|
@@ -34,6 +35,7 @@ class IRCTransport:
|
|
|
34
35
|
self.on_mention = on_mention
|
|
35
36
|
self.tags = tags or []
|
|
36
37
|
self.on_roominvite = on_roominvite
|
|
38
|
+
self.icon = icon
|
|
37
39
|
self.connected = False
|
|
38
40
|
self._reader: asyncio.StreamReader | None = None
|
|
39
41
|
self._writer: asyncio.StreamWriter | None = None
|
|
@@ -174,6 +176,8 @@ class IRCTransport:
|
|
|
174
176
|
if self.tags:
|
|
175
177
|
tags_str = ",".join(self.tags)
|
|
176
178
|
await self._send_raw(f"TAGS {self.nick} {tags_str}")
|
|
179
|
+
if self.icon:
|
|
180
|
+
await self._send_raw(f"ICON {self.icon}")
|
|
177
181
|
|
|
178
182
|
async def _on_privmsg(self, msg: Message) -> None:
|
|
179
183
|
if len(msg.params) < 2:
|
|
@@ -24,6 +24,7 @@ class IRCTransport:
|
|
|
24
24
|
on_mention: Callable[[str, str, str], None] | None = None,
|
|
25
25
|
tags: list[str] | None = None,
|
|
26
26
|
on_roominvite: Callable[[str, str], None] | None = None,
|
|
27
|
+
icon: str | None = None,
|
|
27
28
|
):
|
|
28
29
|
self.host = host
|
|
29
30
|
self.port = port
|
|
@@ -34,6 +35,7 @@ class IRCTransport:
|
|
|
34
35
|
self.on_mention = on_mention
|
|
35
36
|
self.tags = tags or []
|
|
36
37
|
self.on_roominvite = on_roominvite
|
|
38
|
+
self.icon = icon
|
|
37
39
|
self.connected = False
|
|
38
40
|
self._reader: asyncio.StreamReader | None = None
|
|
39
41
|
self._writer: asyncio.StreamWriter | None = None
|
|
@@ -174,6 +176,8 @@ class IRCTransport:
|
|
|
174
176
|
if self.tags:
|
|
175
177
|
tags_str = ",".join(self.tags)
|
|
176
178
|
await self._send_raw(f"TAGS {self.nick} {tags_str}")
|
|
179
|
+
if self.icon:
|
|
180
|
+
await self._send_raw(f"ICON {self.icon}")
|
|
177
181
|
|
|
178
182
|
async def _on_privmsg(self, msg: Message) -> None:
|
|
179
183
|
if len(msg.params) < 2:
|
|
@@ -24,6 +24,7 @@ class IRCTransport:
|
|
|
24
24
|
on_mention: Callable[[str, str, str], None] | None = None,
|
|
25
25
|
tags: list[str] | None = None,
|
|
26
26
|
on_roominvite: Callable[[str, str], None] | None = None,
|
|
27
|
+
icon: str | None = None,
|
|
27
28
|
):
|
|
28
29
|
self.host = host
|
|
29
30
|
self.port = port
|
|
@@ -34,6 +35,7 @@ class IRCTransport:
|
|
|
34
35
|
self.on_mention = on_mention
|
|
35
36
|
self.tags = tags or []
|
|
36
37
|
self.on_roominvite = on_roominvite
|
|
38
|
+
self.icon = icon
|
|
37
39
|
self.connected = False
|
|
38
40
|
self._reader: asyncio.StreamReader | None = None
|
|
39
41
|
self._writer: asyncio.StreamWriter | None = None
|
|
@@ -174,6 +176,8 @@ class IRCTransport:
|
|
|
174
176
|
if self.tags:
|
|
175
177
|
tags_str = ",".join(self.tags)
|
|
176
178
|
await self._send_raw(f"TAGS {self.nick} {tags_str}")
|
|
179
|
+
if self.icon:
|
|
180
|
+
await self._send_raw(f"ICON {self.icon}")
|
|
177
181
|
|
|
178
182
|
async def _on_privmsg(self, msg: Message) -> None:
|
|
179
183
|
if len(msg.params) < 2:
|