ChatZulip Specification
This page defines the first functional ChatZulip boundary: package identity, code layout, CLI/API contract, tests, and release gates. It is the standalone package contract before the follow-up ChatTool parent-removal PR.
Package Identity
| Item | Value |
|---|---|
| PyPI distribution | ChatZulip |
| import module | chatzulip |
| CLI executable | chatzulip |
| GitHub repository | ChatArch/ChatZulip |
| Documentation site | https://arch.gh.wzhecnu.cn/ChatZulip/ |
| Configuration service name | zulip |
| First functional version | 0.1.0 |
Configuration Boundary
ChatZulip models the external Zulip service, not the package name itself. The ChatEnv provider is therefore zulip, and fields keep Zulip service semantics:
ZULIP_SITE
ZULIP_BOT_EMAIL
ZULIP_BOT_API_KEY
ZULIP_NEWS_STREAMS
ZULIP_NEWS_TOPICS
ZULIP_NEWS_SINCE_HOURS
ZULIP_NEWS_PER_STREAM
Rules:
ZULIP_BOT_API_KEYis sensitive. Do not print real values in docs, tests, PR comments, or logs.- Client construction loads ChatEnv active/profile values before explicit constructor overrides.
- Typed profiles live under
$CHATARCH_HOME/envs/Zulip/; an explicitly selected profile must not backfill missing credentials from the process environment. - The package must not maintain a second dotenv/profile renderer; ChatEnv is the configuration system.
- Do not add
CHATZULIP_*credential aliases unless a future migration explicitly requires them.
CLI Boundary
The first CLI version exposes read-oriented and reporting commands:
chatzulip streams # List subscribed streams; --all shows accessible public streams
chatzulip topics --stream TEXT # List stream topics; missing stream can use ChatStyle prompts
chatzulip search-topics QUERY --stream TEXT # Search topics in explicit stream scope
chatzulip search QUERY --stream TEXT # Search messages in explicit stream scope
chatzulip topic --stream TEXT --topic TEXT # Export a full thread, optionally to Markdown
chatzulip messages [filters...] # Fetch messages by stream/topic/sender/search
chatzulip profile # Show the authenticated bot/user profile
chatzulip news [filters...] --output PATH # Render a Markdown news digest
Write operations are not CLI commands yet:
send_messagereactupload_file
They are available through importable Python APIs and MCP adapters. CLI write commands need a separate design for confirmation, permissions, dry-run behavior, and real Zulip smoke tests.
Python API Boundary
Code layout:
src/chatzulip/
├── client.py # Zulip REST client: HTTP, parameter serialization, error mapping
├── config.py # ChatEnv provider: Zulip service fields only
├── operations.py # Reusable business/API functions shared by CLI and MCP
├── cli.py # Thin Click + ChatStyle adapter
└── mcp.py # FastMCP registration adapter
Conventions:
- CLI commands must not be the only business entry point; core logic belongs in
operations.pyorclient.py. - The MCP adapter calls
operations.pyand does not duplicate REST or formatting logic. newsLLM summarization is optional: the base install does not depend onChatTool;chatzulip[llm]enables a best-effortchattoolsummarizer and falls back to a rule-based digest when unavailable.
Test Structure
The repository keeps the ChatPyPI 0.2.4 test directory scaffold and places new tests by responsibility:
tests/
├── cli-tests/ # Doc-first real-service/manual CLI cases
├── mock-cli-tests/ # Fake-client/mock CLI automated tests
├── code-tests/ # Client, operations, config code tests
└── test_version.py # Template-level version smoke
Verification gates:
python -m pytest -q
chatzulip --version
chatzulip --tree
chatzulip --tree-brief
chatzulip --help
chatzulip topics -I
chatenv --home <task-local-home> test -t zulip -I
python -m build
python -m twine check dist/*
mkdocs build --strict
git diff --check
Release And Parent Migration Order
- Merge the
ChatZulipfeature PR. - Tag
v0.1.0from mergedmainand publish through PyPI Trusted Publisher. - Clean-install verify
ChatZulip==0.1.0. - Then create a separate
ChatToolPR from the latest default branch to remove the bundledchattool zulipimplementation. - Keep aggregate availability through an extra such as
chattool[zulip] -> ChatZulip>=0.1.0,<0.2.0; baseChatToolshould no longer ship duplicate Zulip business logic.
Non-goals
- Do not modify
ChatToolin this PR. - Do not expose Zulip write operations as default CLI commands yet.
- Do not rename Zulip service credentials to
CHATZULIP_*. - Do not manually upload functional PyPI releases;
0.1.0+must be tag-driven through Trusted Publisher.