agentirc-cli 6.1.1__tar.gz → 6.2.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.
Files changed (355) hide show
  1. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/CHANGELOG.md +14 -0
  2. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/PKG-INFO +2 -2
  3. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/README.md +1 -1
  4. agentirc_cli-6.2.0/culture/cli/shared/constants.py +43 -0
  5. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/shared/ipc.py +3 -1
  6. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/app.py +148 -26
  7. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/commands.py +2 -0
  8. agentirc_cli-6.2.0/culture/console/status.py +74 -0
  9. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/widgets/sidebar.py +15 -1
  10. agentirc_cli-6.2.0/docs/superpowers/plans/2026-04-12-console-enhancements.md +732 -0
  11. agentirc_cli-6.2.0/docs/superpowers/specs/2026-04-12-console-enhancements-design.md +203 -0
  12. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/pyproject.toml +1 -1
  13. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_console_commands.py +6 -0
  14. agentirc_cli-6.2.0/tests/test_console_status.py +53 -0
  15. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/uv.lock +1 -1
  16. agentirc_cli-6.1.1/culture/cli/shared/constants.py +0 -20
  17. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.claude/skills/pr-review/SKILL.md +0 -0
  18. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.claude/skills/run-tests/SKILL.md +0 -0
  19. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
  20. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.flake8 +0 -0
  21. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.github/workflows/docs-check.yml +0 -0
  22. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.github/workflows/publish.yml +0 -0
  23. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.github/workflows/security-checks.yml +0 -0
  24. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.github/workflows/tests.yml +0 -0
  25. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.gitignore +0 -0
  26. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.markdownlint-cli2.yaml +0 -0
  27. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.pr_agent.toml +0 -0
  28. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.pre-commit-config.yaml +0 -0
  29. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.pylintrc +0 -0
  30. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/CLAUDE.md +0 -0
  31. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/Gemfile +0 -0
  32. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/Gemfile.lock +0 -0
  33. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/LICENSE +0 -0
  34. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/SECURITY.md +0 -0
  35. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_config.agentirc.yml +0 -0
  36. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_config.base.yml +0 -0
  37. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_config.culture.yml +0 -0
  38. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_data/sites.yml +0 -0
  39. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_includes/head_custom.html +0 -0
  40. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_plugins/site_filter.rb +0 -0
  41. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_sass/color_schemes/anthropic.scss +0 -0
  42. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_sass/color_schemes/dark-terminal.scss +0 -0
  43. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_sass/custom/custom.scss +0 -0
  44. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/IMG_3183.png +0 -0
  45. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/apple-touch-icon.png +0 -0
  46. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/favicon-16x16.png +0 -0
  47. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/favicon-32x32.png +0 -0
  48. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/favicon.ico +0 -0
  49. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/og-agentirc.png +0 -0
  50. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/og-culture.png +0 -0
  51. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/__init__.py +0 -0
  52. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/__main__.py +0 -0
  53. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/CLAUDE.md +0 -0
  54. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/__init__.py +0 -0
  55. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/__main__.py +0 -0
  56. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/channel.py +0 -0
  57. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/client.py +0 -0
  58. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/config.py +0 -0
  59. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/docs/agentirc-architecture.md +0 -0
  60. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/docs/agentirc-features.md +0 -0
  61. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/docs/agentirc-skill.md +0 -0
  62. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/docs/agentirc.md +0 -0
  63. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/history_store.py +0 -0
  64. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/ircd.py +0 -0
  65. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/remote_client.py +0 -0
  66. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/room_store.py +0 -0
  67. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/rooms_util.py +0 -0
  68. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/server_link.py +0 -0
  69. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/skill.py +0 -0
  70. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/skills/__init__.py +0 -0
  71. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/skills/history.py +0 -0
  72. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/skills/icon.py +0 -0
  73. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/skills/rooms.py +0 -0
  74. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/skills/threads.py +0 -0
  75. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/thread_store.py +0 -0
  76. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/aio.py +0 -0
  77. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/__init__.py +0 -0
  78. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/bot.py +0 -0
  79. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/bot_manager.py +0 -0
  80. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/config.py +0 -0
  81. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/http_listener.py +0 -0
  82. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/template_engine.py +0 -0
  83. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/virtual_client.py +0 -0
  84. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/__init__.py +0 -0
  85. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/agent.py +0 -0
  86. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/bot.py +0 -0
  87. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/channel.py +0 -0
  88. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/mesh.py +0 -0
  89. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/server.py +0 -0
  90. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/shared/__init__.py +0 -0
  91. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/shared/display.py +0 -0
  92. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/shared/formatting.py +0 -0
  93. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/shared/mesh.py +0 -0
  94. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/shared/process.py +0 -0
  95. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/skills.py +0 -0
  96. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/__init__.py +0 -0
  97. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/__init__.py +0 -0
  98. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/agent_runner.py +0 -0
  99. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/config.py +0 -0
  100. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/culture.yaml +0 -0
  101. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/daemon.py +0 -0
  102. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/ipc.py +0 -0
  103. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/irc_transport.py +0 -0
  104. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/message_buffer.py +0 -0
  105. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/skill/SKILL.md +0 -0
  106. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/skill/__init__.py +0 -0
  107. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/skill/irc_client.py +0 -0
  108. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/socket_server.py +0 -0
  109. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/supervisor.py +0 -0
  110. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/webhook.py +0 -0
  111. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/__init__.py +0 -0
  112. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/__main__.py +0 -0
  113. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/agent_runner.py +0 -0
  114. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/config.py +0 -0
  115. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/culture.yaml +0 -0
  116. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/daemon.py +0 -0
  117. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/ipc.py +0 -0
  118. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/irc_transport.py +0 -0
  119. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/message_buffer.py +0 -0
  120. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/skill/SKILL.md +0 -0
  121. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/skill/__init__.py +0 -0
  122. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/skill/irc_client.py +0 -0
  123. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/socket_server.py +0 -0
  124. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/supervisor.py +0 -0
  125. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/webhook.py +0 -0
  126. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/__init__.py +0 -0
  127. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/agent_runner.py +0 -0
  128. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/config.py +0 -0
  129. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/culture.yaml +0 -0
  130. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/daemon.py +0 -0
  131. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/ipc.py +0 -0
  132. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/irc_transport.py +0 -0
  133. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/message_buffer.py +0 -0
  134. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/skill/SKILL.md +0 -0
  135. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/skill/__init__.py +0 -0
  136. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/skill/irc_client.py +0 -0
  137. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/socket_server.py +0 -0
  138. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/supervisor.py +0 -0
  139. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/webhook.py +0 -0
  140. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/__init__.py +0 -0
  141. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/agent_runner.py +0 -0
  142. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/config.py +0 -0
  143. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/culture.yaml +0 -0
  144. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/daemon.py +0 -0
  145. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/ipc.py +0 -0
  146. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/irc_transport.py +0 -0
  147. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/message_buffer.py +0 -0
  148. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/skill/SKILL.md +0 -0
  149. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/skill/__init__.py +0 -0
  150. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/skill/irc_client.py +0 -0
  151. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/socket_server.py +0 -0
  152. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/supervisor.py +0 -0
  153. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/webhook.py +0 -0
  154. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/config.py +0 -0
  155. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/__init__.py +0 -0
  156. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/client.py +0 -0
  157. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/widgets/__init__.py +0 -0
  158. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/widgets/chat.py +0 -0
  159. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/widgets/info_panel.py +0 -0
  160. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/credentials.py +0 -0
  161. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/formatting.py +0 -0
  162. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/learn_prompt.py +0 -0
  163. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/mesh_config.py +0 -0
  164. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/observer.py +0 -0
  165. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/overview/__init__.py +0 -0
  166. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/overview/collector.py +0 -0
  167. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/overview/model.py +0 -0
  168. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/overview/renderer_text.py +0 -0
  169. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/overview/renderer_web.py +0 -0
  170. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/overview/web/style.css +0 -0
  171. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/persistence.py +0 -0
  172. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/pidfile.py +0 -0
  173. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/__init__.py +0 -0
  174. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/commands.py +0 -0
  175. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/extensions/federation.md +0 -0
  176. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/extensions/history.md +0 -0
  177. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/extensions/icons.md +0 -0
  178. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/extensions/rooms.md +0 -0
  179. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/extensions/tags.md +0 -0
  180. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/extensions/threads.md +0 -0
  181. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/message.py +0 -0
  182. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/protocol-index.md +0 -0
  183. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/replies.py +0 -0
  184. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/skills/culture/SKILL.md +0 -0
  185. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/README.md +0 -0
  186. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/agentirc/architecture-overview.md +0 -0
  187. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/agentirc/index.md +0 -0
  188. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/agentirc/why-agentirc.md +0 -0
  189. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/agent-lifecycle.md +0 -0
  190. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/choose-a-harness.md +0 -0
  191. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/index.md +0 -0
  192. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/mental-model.md +0 -0
  193. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/operate.md +0 -0
  194. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/patterns.md +0 -0
  195. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/quickstart.md +0 -0
  196. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/reflective-development.md +0 -0
  197. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/vision-patterns-index.md +0 -0
  198. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/vision.md +0 -0
  199. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/why-culture.md +0 -0
  200. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/architecture/agent-harness-spec.md +0 -0
  201. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/architecture/index.md +0 -0
  202. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/architecture/layers.md +0 -0
  203. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/architecture/threads.md +0 -0
  204. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/cli/commands.md +0 -0
  205. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/cli/index.md +0 -0
  206. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/harnesses/acp.md +0 -0
  207. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/harnesses/claude.md +0 -0
  208. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/harnesses/codex.md +0 -0
  209. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/harnesses/copilot.md +0 -0
  210. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/harnesses/index.md +0 -0
  211. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/index.md +0 -0
  212. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/server/architecture.md +0 -0
  213. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/server/config.md +0 -0
  214. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/server/deployment.md +0 -0
  215. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/server/index.md +0 -0
  216. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/server/security.md +0 -0
  217. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/resources/github-copilot-sdk-instructions.md +0 -0
  218. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/concepts/federation.md +0 -0
  219. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/concepts/harnesses.md +0 -0
  220. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/concepts/humans-and-agents.md +0 -0
  221. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/concepts/index.md +0 -0
  222. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/concepts/persistence.md +0 -0
  223. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/concepts/rooms.md +0 -0
  224. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/demos/magic-demo.md +0 -0
  225. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/guides/first-session.md +0 -0
  226. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/guides/index.md +0 -0
  227. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/guides/join-as-human.md +0 -0
  228. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/guides/local-setup.md +0 -0
  229. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/guides/multi-machine.md +0 -0
  230. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/01-pair-programming.md +0 -0
  231. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/02-code-review-ensemble.md +0 -0
  232. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/03-cross-server-delegation.md +0 -0
  233. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/04-knowledge-propagation.md +0 -0
  234. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/05-the-observer.md +0 -0
  235. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/06-cross-server-ops.md +0 -0
  236. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/07-supervisor-intervention.md +0 -0
  237. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/08-apps-as-agents.md +0 -0
  238. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/09-research-swarm.md +0 -0
  239. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/10-agent-lifecycle.md +0 -0
  240. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases-index.md +0 -0
  241. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
  242. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
  243. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
  244. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
  245. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
  246. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
  247. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
  248. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
  249. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
  250. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-04-09-decentralized-agent-config.md +0 -0
  251. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
  252. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
  253. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
  254. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
  255. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
  256. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
  257. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
  258. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
  259. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
  260. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
  261. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
  262. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
  263. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
  264. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-07-reflective-development-reframe-design.md +0 -0
  265. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-08-reflective-development-deepening-design.md +0 -0
  266. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-09-decentralized-agent-config-design.md +0 -0
  267. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/favicon.ico +0 -0
  268. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/README.md +0 -0
  269. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/config.py +0 -0
  270. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/culture.yaml +0 -0
  271. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/daemon.py +0 -0
  272. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/ipc.py +0 -0
  273. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/irc_transport.py +0 -0
  274. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/message_buffer.py +0 -0
  275. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/skill/SKILL.md +0 -0
  276. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/skill/irc_client.py +0 -0
  277. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/socket_server.py +0 -0
  278. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/webhook.py +0 -0
  279. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
  280. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/plugins/claude-code/skills/culture/SKILL.md +0 -0
  281. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/plugins/claude-code/skills/irc/SKILL.md +0 -0
  282. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
  283. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/robots.txt +0 -0
  284. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/sonar-project.properties +0 -0
  285. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/__init__.py +0 -0
  286. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/conftest.py +0 -0
  287. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_acp_daemon.py +0 -0
  288. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_agent_runner.py +0 -0
  289. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_archive.py +0 -0
  290. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_bot.py +0 -0
  291. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_bot_config.py +0 -0
  292. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_bot_manager.py +0 -0
  293. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_bots_integration.py +0 -0
  294. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_channel.py +0 -0
  295. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_channel_cli.py +0 -0
  296. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_codex_daemon.py +0 -0
  297. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_connection.py +0 -0
  298. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_console_client.py +0 -0
  299. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_console_connection.py +0 -0
  300. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_console_icons.py +0 -0
  301. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_console_integration.py +0 -0
  302. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_copilot_daemon.py +0 -0
  303. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_credentials.py +0 -0
  304. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_culture_config.py +0 -0
  305. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_daemon.py +0 -0
  306. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_daemon_config.py +0 -0
  307. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_daemon_ipc.py +0 -0
  308. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_discovery.py +0 -0
  309. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_display.py +0 -0
  310. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_federation.py +0 -0
  311. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_history.py +0 -0
  312. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_http_listener.py +0 -0
  313. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_integration_layer5.py +0 -0
  314. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_ipc.py +0 -0
  315. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_irc_transport.py +0 -0
  316. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_learn_prompt.py +0 -0
  317. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_link_reconnect.py +0 -0
  318. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_manifest_config.py +0 -0
  319. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_mention_alias.py +0 -0
  320. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_mention_target_cleanup.py +0 -0
  321. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_mention_warning.py +0 -0
  322. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_mentions.py +0 -0
  323. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_mesh_config.py +0 -0
  324. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_mesh_readiness.py +0 -0
  325. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_message.py +0 -0
  326. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_message_buffer.py +0 -0
  327. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_messaging.py +0 -0
  328. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_migrate_cli.py +0 -0
  329. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_modes.py +0 -0
  330. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_overview_cli.py +0 -0
  331. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_overview_collector.py +0 -0
  332. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_overview_model.py +0 -0
  333. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_overview_renderer.py +0 -0
  334. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_overview_web.py +0 -0
  335. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_persistence.py +0 -0
  336. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_pidfile.py +0 -0
  337. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_poll_loop.py +0 -0
  338. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_register_cli.py +0 -0
  339. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_room_persistence.py +0 -0
  340. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_rooms.py +0 -0
  341. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_rooms_federation.py +0 -0
  342. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_rooms_integration.py +0 -0
  343. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_server_icon_skill.py +0 -0
  344. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_setup_update_cli.py +0 -0
  345. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_skill_client.py +0 -0
  346. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_skill_docs.py +0 -0
  347. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_skills.py +0 -0
  348. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_socket_server.py +0 -0
  349. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_supervisor.py +0 -0
  350. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_template_engine.py +0 -0
  351. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_thread_buffer.py +0 -0
  352. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_threads.py +0 -0
  353. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_virtual_client.py +0 -0
  354. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_wait_for_port.py +0 -0
  355. {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_webhook.py +0 -0
@@ -4,6 +4,20 @@ 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
+ ## [6.2.0] - 2026-04-12
8
+
9
+
10
+ ### Added
11
+
12
+ - Agent status indicators in console sidebar (#218) — shows working/idle/paused/circuit-open for each agent
13
+ - Auto-read channel history on switch (#219) — loads last 20 messages when switching channels via Tab, sidebar click, or /join
14
+ - Help menu — /help command and Ctrl+H keybinding showing all commands and keybindings
15
+
16
+
17
+ ### Fixed
18
+
19
+ - Joined message no longer wiped by channel switch clear_log
20
+
7
21
  ## [6.1.1] - 2026-04-11
8
22
 
9
23
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentirc-cli
3
- Version: 6.1.1
3
+ Version: 6.2.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
@@ -27,7 +27,7 @@ Description-Content-Type: text/markdown
27
27
  The complete human-agent collaboration system built around AgentIRC.
28
28
 
29
29
  **AgentIRC** is the IRC-native runtime for persistent AI agents and humans in shared live rooms.
30
- **Culture** is the full solution — CLI, harnesses, workflows, and multi-machine mesh.
30
+ **Culture** is the full solution — CLI, harnesses, console, workflows, and multi-machine mesh.
31
31
 
32
32
  ## Start here
33
33
 
@@ -3,7 +3,7 @@
3
3
  The complete human-agent collaboration system built around AgentIRC.
4
4
 
5
5
  **AgentIRC** is the IRC-native runtime for persistent AI agents and humans in shared live rooms.
6
- **Culture** is the full solution — CLI, harnesses, workflows, and multi-machine mesh.
6
+ **Culture** is the full solution — CLI, harnesses, console, workflows, and multi-machine mesh.
7
7
 
8
8
  ## Start here
9
9
 
@@ -0,0 +1,43 @@
1
+ """Shared constants for culture CLI modules."""
2
+
3
+ import os
4
+ import stat
5
+
6
+ from culture.bots.config import BOT_CONFIG_FILE # noqa: F401
7
+
8
+ DEFAULT_CONFIG = os.path.expanduser("~/.culture/server.yaml")
9
+ LOG_DIR = os.path.expanduser("~/.culture/logs")
10
+
11
+ _CONFIG_HELP = "Config file path"
12
+ _SERVER_NAME_HELP = "Server name"
13
+ _BOT_NAME_HELP = "Bot name"
14
+
15
+ DEFAULT_CHANNEL = "#general"
16
+ NO_AGENTS_MSG = "No agents configured"
17
+ CULTURE_DIR = ".culture"
18
+ AGENTS_YAML = "agents.yaml"
19
+
20
+ DEFAULT_SERVER_CONFIG = os.path.expanduser("~/.culture/server.yaml")
21
+ LEGACY_CONFIG = os.path.expanduser("~/.culture/agents.yaml")
22
+
23
+
24
+ def culture_runtime_dir() -> str:
25
+ """Return a safe directory for culture daemon sockets.
26
+
27
+ Uses ``$XDG_RUNTIME_DIR`` when available (user-private, set by
28
+ systemd/logind). Otherwise creates a user-private subdirectory
29
+ under the system temp dir so sockets never live in a publicly
30
+ writable location.
31
+ """
32
+ xdg = os.environ.get("XDG_RUNTIME_DIR")
33
+ if xdg:
34
+ return xdg
35
+ fallback = os.path.join(
36
+ os.path.expanduser("~"),
37
+ ".culture",
38
+ "run",
39
+ )
40
+ os.makedirs(fallback, mode=0o700, exist_ok=True)
41
+ # Enforce permissions even if the directory already existed
42
+ os.chmod(fallback, stat.S_IRWXU)
43
+ return fallback
@@ -9,8 +9,10 @@ from culture.config import load_config_or_default
9
9
 
10
10
 
11
11
  def agent_socket_path(nick: str) -> str:
12
+ from culture.cli.shared.constants import culture_runtime_dir
13
+
12
14
  return os.path.join(
13
- os.environ.get("XDG_RUNTIME_DIR", "/tmp"),
15
+ culture_runtime_dir(),
14
16
  f"culture-{nick}.sock",
15
17
  )
16
18
 
@@ -15,6 +15,7 @@ from textual.widgets import Footer, Header
15
15
  from culture.aio import maybe_await
16
16
  from culture.console.client import ConsoleIRCClient
17
17
  from culture.console.commands import CommandType, parse_command
18
+ from culture.console.status import query_all_agents
18
19
  from culture.console.widgets.chat import ChatPanel
19
20
  from culture.console.widgets.info_panel import InfoPanel
20
21
  from culture.console.widgets.sidebar import ChannelItem, EntityItem, Sidebar
@@ -22,6 +23,7 @@ from culture.console.widgets.sidebar import ChannelItem, EntityItem, Sidebar
22
23
  logger = logging.getLogger(__name__)
23
24
 
24
25
  BUFFER_INTERVAL = 10.0 # seconds between UI refreshes
26
+ STATUS_POLL_INTERVAL = 30.0 # seconds between agent status polls
25
27
 
26
28
 
27
29
  class ConsoleApp(App):
@@ -33,6 +35,7 @@ class ConsoleApp(App):
33
35
  BINDINGS = [
34
36
  Binding("ctrl+o", "show_overview", "Overview", show=True),
35
37
  Binding("ctrl+s", "show_status", "Status", show=True),
38
+ Binding("ctrl+h", "show_help", "Help", show=True),
36
39
  Binding("escape", "back_to_chat", "Chat", show=True),
37
40
  Binding("ctrl+q", "quit_app", "Quit", show=True),
38
41
  Binding("tab", "next_channel", "Next channel", show=False),
@@ -65,6 +68,7 @@ class ConsoleApp(App):
65
68
 
66
69
  self._buffer_task: asyncio.Task | None = None
67
70
  self._background_tasks: set[asyncio.Task] = set()
71
+ self._status_poll_task: asyncio.Task | None = None
68
72
 
69
73
  # Dispatch table for command execution
70
74
  self._command_handlers: dict[CommandType, Any] = {
@@ -84,6 +88,7 @@ class ConsoleApp(App):
84
88
  CommandType.INVITE: self._handle_invite,
85
89
  CommandType.SERVER: self._handle_server,
86
90
  CommandType.QUIT: self._handle_quit,
91
+ CommandType.HELP: self._handle_help,
87
92
  }
88
93
 
89
94
  # ------------------------------------------------------------------
@@ -106,6 +111,7 @@ class ConsoleApp(App):
106
111
  """Set sub-title and kick off the buffer-drain loop."""
107
112
  self.sub_title = f"{self._client.nick}@{self._server_name}"
108
113
  self._buffer_task = asyncio.create_task(self._buffer_loop())
114
+ self._status_poll_task = asyncio.create_task(self._status_poll_loop())
109
115
 
110
116
  # Populate sidebar with any channels already joined at startup
111
117
  self._sync_sidebar()
@@ -140,6 +146,43 @@ class ConsoleApp(App):
140
146
  text=msg.text,
141
147
  )
142
148
 
149
+ async def _status_poll_loop(self) -> None:
150
+ """Periodically poll agent daemon sockets for status updates."""
151
+ # Initial poll on startup
152
+ await self._poll_agent_status()
153
+ while True:
154
+ try:
155
+ await asyncio.sleep(STATUS_POLL_INTERVAL)
156
+ await self._poll_agent_status()
157
+ except asyncio.CancelledError:
158
+ raise
159
+ except Exception:
160
+ logger.exception("Error in _status_poll_loop")
161
+
162
+ async def _poll_agent_status(self) -> None:
163
+ """Query daemon sockets and update sidebar entity activity."""
164
+ status_map = await query_all_agents()
165
+ if not status_map:
166
+ return
167
+ sidebar: Sidebar = self.query_one(Sidebar)
168
+ updated = False
169
+ new_entities = []
170
+ for ent in sidebar.entities:
171
+ if ent.nick in status_map:
172
+ new_ent = EntityItem(
173
+ nick=ent.nick,
174
+ entity_type=ent.entity_type,
175
+ online=ent.online,
176
+ icon=ent.icon,
177
+ activity=status_map[ent.nick],
178
+ )
179
+ new_entities.append(new_ent)
180
+ updated = True
181
+ else:
182
+ new_entities.append(ent)
183
+ if updated:
184
+ sidebar.entities = new_entities
185
+
143
186
  # ------------------------------------------------------------------
144
187
  # Input handler
145
188
  # ------------------------------------------------------------------
@@ -189,9 +232,8 @@ class ConsoleApp(App):
189
232
  return
190
233
  channel = cmd.args[0]
191
234
  await self._client.join(channel)
192
- self._current_channel = channel
193
235
  self._sync_sidebar()
194
- chat.set_channel(channel)
236
+ await self._switch_to_channel(channel)
195
237
  chat.add_message(time.time(), "", "system", f"Joined [bold]{channel}[/]")
196
238
 
197
239
  async def _handle_part(self, cmd) -> None: # noqa: ANN001
@@ -341,6 +383,51 @@ class ConsoleApp(App):
341
383
  async def _handle_quit(self, cmd) -> None: # noqa: ANN001
342
384
  await self.action_quit_app()
343
385
 
386
+ def _handle_help(self, cmd) -> None: # noqa: ANN001
387
+ self.action_show_help()
388
+
389
+ def action_show_help(self) -> None:
390
+ """Show help content with all commands and keybindings."""
391
+ self._current_view = "help"
392
+ chat: ChatPanel = self.query_one(ChatPanel)
393
+ lines = [
394
+ "[bold $warning]COMMANDS[/]",
395
+ "",
396
+ " [bold]/help[/] Show this help",
397
+ " [bold]/join[/] #channel Join a channel",
398
+ " [bold]/part[/] [#channel] Leave a channel",
399
+ " [bold]/read[/] [#ch] [-n N] Read channel history (default 50)",
400
+ " [bold]/who[/] [target] List channel members",
401
+ " [bold]/send[/] <target> <text> Send a direct message",
402
+ " [bold]/channels[/] List server channels",
403
+ " [bold]/agents[/] List visible agents",
404
+ " [bold]/status[/] [agent] Show status info",
405
+ " [bold]/overview[/] Show mesh overview",
406
+ " [bold]/icon[/] <emoji> Set your icon",
407
+ " [bold]/topic[/] #ch <text> Set channel topic",
408
+ " [bold]/kick[/] #ch <nick> Kick a user",
409
+ " [bold]/invite[/] <nick> #ch Invite a user",
410
+ " [bold]/server[/] [name] Switch server (restarts console)",
411
+ " [bold]/quit[/] Exit console",
412
+ "",
413
+ "[bold $warning]KEYBINDINGS[/]",
414
+ "",
415
+ " [bold]Tab / Shift+Tab[/] Cycle channels",
416
+ " [bold]Ctrl+O[/] Overview",
417
+ " [bold]Ctrl+S[/] Status",
418
+ " [bold]Ctrl+H[/] Help",
419
+ " [bold]Escape[/] Back to chat",
420
+ " [bold]Ctrl+Q[/] Quit",
421
+ ]
422
+ chat.set_content("Help", lines)
423
+
424
+ # Hide input — not meaningful in help view
425
+ try:
426
+ input_widget = self.query_one(self._CHAT_INPUT_ID)
427
+ input_widget.display = False
428
+ except Exception:
429
+ pass
430
+
344
431
  # ------------------------------------------------------------------
345
432
  # View actions
346
433
  # ------------------------------------------------------------------
@@ -468,8 +555,15 @@ class ConsoleApp(App):
468
555
  chat.set_content("Agents", lines)
469
556
 
470
557
  # Update sidebar entity roster
558
+ status_map = await query_all_agents()
471
559
  entity_items = [
472
- EntityItem(nick=nick, entity_type="agent", online=True) for nick in sorted(all_agents)
560
+ EntityItem(
561
+ nick=nick,
562
+ entity_type="agent",
563
+ online=True,
564
+ activity=status_map.get(nick, ""),
565
+ )
566
+ for nick in sorted(all_agents)
473
567
  ]
474
568
  sidebar.entities = entity_items
475
569
 
@@ -506,16 +600,15 @@ class ConsoleApp(App):
506
600
  if not channels:
507
601
  return
508
602
  if self._current_channel not in channels:
509
- self._current_channel = channels[0]
603
+ target = channels[0]
510
604
  else:
511
605
  idx = channels.index(self._current_channel)
512
606
  idx = (idx + direction) % len(channels)
513
- self._current_channel = channels[idx]
607
+ target = channels[idx]
514
608
 
515
- chat: ChatPanel = self.query_one(ChatPanel)
516
- sidebar: Sidebar = self.query_one(Sidebar)
517
- chat.set_channel(self._current_channel)
518
- sidebar.active_channel = self._current_channel
609
+ task = asyncio.create_task(self._switch_to_channel(target))
610
+ self._background_tasks.add(task)
611
+ task.add_done_callback(self._background_tasks.discard)
519
612
 
520
613
  # ------------------------------------------------------------------
521
614
  # Quit
@@ -523,10 +616,14 @@ class ConsoleApp(App):
523
616
 
524
617
  async def action_quit_app(self) -> None:
525
618
  """Disconnect the IRC client and exit the app."""
526
- if self._buffer_task:
527
- self._buffer_task.cancel()
528
- await asyncio.gather(self._buffer_task, return_exceptions=True)
529
- self._buffer_task = None
619
+ for task_ref in (self._buffer_task, self._status_poll_task):
620
+ if task_ref:
621
+ task_ref.cancel()
622
+ tasks_to_cancel = [t for t in (self._buffer_task, self._status_poll_task) if t]
623
+ if tasks_to_cancel:
624
+ await asyncio.gather(*tasks_to_cancel, return_exceptions=True)
625
+ self._buffer_task = None
626
+ self._status_poll_task = None
530
627
 
531
628
  if self._client.connected:
532
629
  try:
@@ -542,19 +639,9 @@ class ConsoleApp(App):
542
639
 
543
640
  def on_sidebar_channel_selected(self, event: Sidebar.ChannelSelected) -> None:
544
641
  """Switch to the selected channel when user clicks sidebar."""
545
- self._current_channel = event.channel
546
- self._current_view = "chat"
547
- chat: ChatPanel = self.query_one(ChatPanel)
548
- sidebar: Sidebar = self.query_one(Sidebar)
549
- chat.set_channel(self._current_channel)
550
- sidebar.active_channel = self._current_channel
551
-
552
- # Re-show input if hidden
553
- try:
554
- input_widget = self.query_one(self._CHAT_INPUT_ID)
555
- input_widget.display = True
556
- except Exception:
557
- pass
642
+ task = asyncio.create_task(self._switch_to_channel(event.channel))
643
+ self._background_tasks.add(task)
644
+ task.add_done_callback(self._background_tasks.discard)
558
645
 
559
646
  def on_sidebar_entity_selected(self, event: Sidebar.EntitySelected) -> None:
560
647
  """Show agent detail when user clicks an entity in the sidebar."""
@@ -566,6 +653,41 @@ class ConsoleApp(App):
566
653
  # Internal helpers
567
654
  # ------------------------------------------------------------------
568
655
 
656
+ async def _switch_to_channel(self, channel: str) -> None:
657
+ """Switch to a channel, update UI, and auto-load recent history."""
658
+ if not channel:
659
+ return
660
+ # Guard against stale results from rapid switching
661
+ self._current_channel = channel
662
+ self._current_view = "chat"
663
+
664
+ sidebar: Sidebar = self.query_one(Sidebar)
665
+ chat: ChatPanel = self.query_one(ChatPanel)
666
+ sidebar.active_channel = channel
667
+ chat.set_channel(channel)
668
+ chat.clear_log()
669
+
670
+ # Re-show input if hidden (e.g., coming from overview/status view)
671
+ try:
672
+ input_widget = self.query_one(self._CHAT_INPUT_ID)
673
+ input_widget.display = True
674
+ except Exception:
675
+ pass
676
+
677
+ # Fetch recent history
678
+ entries = await self._client.history(channel, limit=20)
679
+ # Stale check: if user switched away during fetch, discard results
680
+ if self._current_channel != channel:
681
+ return
682
+ for e in entries:
683
+ try:
684
+ ts = float(e.get("timestamp", 0))
685
+ except (ValueError, TypeError):
686
+ ts = time.time()
687
+ chat.add_message(ts, "", e.get("nick", ""), e.get("text", ""))
688
+ if not entries:
689
+ chat.add_message(time.time(), "", "system", f"[dim]No history for {channel}[/]")
690
+
569
691
  def _sync_sidebar(self) -> None:
570
692
  """Sync the sidebar channel list from the client's joined_channels."""
571
693
  sidebar: Sidebar = self.query_one(Sidebar)
@@ -26,6 +26,7 @@ class CommandType(Enum):
26
26
  INVITE = auto()
27
27
  SERVER = auto()
28
28
  QUIT = auto()
29
+ HELP = auto()
29
30
  UNKNOWN = auto()
30
31
 
31
32
 
@@ -60,6 +61,7 @@ _COMMANDS: dict[str, CommandType] = {
60
61
  "invite": CommandType.INVITE,
61
62
  "server": CommandType.SERVER,
62
63
  "quit": CommandType.QUIT,
64
+ "help": CommandType.HELP,
63
65
  }
64
66
 
65
67
 
@@ -0,0 +1,74 @@
1
+ """Lightweight daemon IPC status queries for the console."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import os
7
+ from pathlib import Path
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+
12
+ def discover_agent_sockets() -> list[tuple[str, Path]]:
13
+ """List culture daemon sockets in the culture runtime directory.
14
+
15
+ Returns a list of ``(nick, socket_path)`` tuples.
16
+ """
17
+ from culture.cli.shared.constants import culture_runtime_dir
18
+
19
+ runtime_dir = Path(culture_runtime_dir())
20
+ results: list[tuple[str, Path]] = []
21
+ if not runtime_dir.is_dir():
22
+ return results
23
+ for entry in runtime_dir.iterdir():
24
+ if entry.name.startswith("culture-") and entry.name.endswith(".sock") and entry.is_socket():
25
+ nick = entry.name[len("culture-") : -len(".sock")]
26
+ results.append((nick, entry))
27
+ return results
28
+
29
+
30
+ async def query_agent_status(socket_path: Path) -> dict:
31
+ """Query a single daemon socket for status (no LLM query).
32
+
33
+ Returns a dict with ``activity``, ``paused``, ``circuit_open``,
34
+ ``running`` keys, or an empty dict on failure.
35
+ """
36
+ from culture.cli.shared.ipc import ipc_request
37
+
38
+ resp = await ipc_request(str(socket_path), "status")
39
+ if resp is None or not resp.get("ok"):
40
+ return {}
41
+ return resp.get("data", {})
42
+
43
+
44
+ def _derive_activity(data: dict) -> str:
45
+ """Derive a single activity string from daemon status fields."""
46
+ if data.get("circuit_open"):
47
+ return "circuit-open"
48
+ if data.get("paused"):
49
+ return "paused"
50
+ if not data.get("running"):
51
+ return "idle"
52
+ return data.get("activity", "idle")
53
+
54
+
55
+ async def query_all_agents() -> dict[str, str]:
56
+ """Query all local daemon sockets and return nick -> activity mapping."""
57
+ import asyncio
58
+
59
+ sockets = discover_agent_sockets()
60
+ if not sockets:
61
+ return {}
62
+
63
+ results: dict[str, str] = {}
64
+
65
+ async def _query_one(nick: str, path: Path) -> None:
66
+ try:
67
+ data = await asyncio.wait_for(query_agent_status(path), timeout=3.0)
68
+ if data:
69
+ results[nick] = _derive_activity(data)
70
+ except Exception:
71
+ logger.debug("Failed to query status for %s", nick)
72
+
73
+ await asyncio.gather(*[_query_one(nick, path) for nick, path in sockets])
74
+ return results
@@ -32,6 +32,7 @@ class EntityItem:
32
32
  entity_type: str = "agent" # "agent" | "admin" | "human" | "bot"
33
33
  online: bool = True
34
34
  icon: str = ""
35
+ activity: str = "" # "working" | "idle" | "paused" | "circuit-open" | ""
35
36
 
36
37
 
37
38
  # ---------------------------------------------------------------------------
@@ -46,6 +47,14 @@ _TYPE_ICON: dict[str, str] = {
46
47
  "bot": "⚙",
47
48
  }
48
49
 
50
+ # Activity indicators for agent status
51
+ _ACTIVITY_INDICATOR: dict[str, str] = {
52
+ "working": "[green]●[/]",
53
+ "idle": "[dim]○[/]",
54
+ "paused": "[yellow]⏸[/]",
55
+ "circuit-open": "[red]⚠[/]",
56
+ }
57
+
49
58
  # Group order for entity types
50
59
  _GROUP_ORDER = ["agent", "admin", "human", "bot"]
51
60
 
@@ -105,7 +114,12 @@ class _EntityRow(Static):
105
114
  """
106
115
 
107
116
  def __init__(self, entity: EntityItem) -> None:
108
- dot = "[green]●[/]" if entity.online else "[dim]○[/]"
117
+ if entity.activity and entity.activity in _ACTIVITY_INDICATOR:
118
+ dot = _ACTIVITY_INDICATOR[entity.activity]
119
+ elif entity.online:
120
+ dot = "●"
121
+ else:
122
+ dot = "[dim]○[/]"
109
123
  icon = entity.icon or _TYPE_ICON.get(entity.entity_type, "")
110
124
  markup = f"{dot} {icon} {entity.nick}"
111
125
  super().__init__(markup, markup=True)