lark-push runs independent Feishu/Lark interactive-card tasks. The runtime
package handles scheduling, rendering, API calls, persisted message state, and
the admin UI. Each business task owns its configuration, template, data fetcher,
mock data, and handoff notes.
.
├── lark_push/ # Runtime package and Flask admin/callback service
├── tasks/ # Independent business task directories
├── runtime/ # Local runtime state; contents are not committed
├── deploy/ # systemd and Nginx production templates
├── docs/ # Deployment and operations documentation
├── scripts/ # Isolated verification and service smoke tests
├── tests/ # unittest coverage
├── app.py # Vercel Flask entrypoint
├── requirements.txt
└── vercel.json
Python 3.12 or newer is recommended.
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install -r requirements.txt
cp .env.example .envConfigure .env before starting the service. Process environment variables
take precedence over values from .env.
Required variables:
LARK_APP_IDLARK_APP_SECRETLARK_RECIPIENTS_JSONLARK_ADMIN_PASSWORDLARK_ADMIN_SESSION_SECRET
LARK_RECIPIENTS_JSON maps stable task recipient refs to Feishu/Lark IDs:
{
"personal": {
"receive_id_type": "open_id",
"receive_id": "ou_example",
"label": "Personal"
},
"group": {
"receive_id_type": "chat_id",
"receive_id": "oc_example",
"label": "Monitoring Group"
}
}Set ZENMUX_MANAGEMENT_API_KEY when live ZenMux usage data is required.
Optional host, port, timeout, timezone, and path overrides are documented in
.env.example.
Start the long-running scheduler and callback service:
python3 -m lark_pushValidate environment variables and task/recipient references without starting the scheduler:
python3 -m lark_push.check_configAvailable HTTP surfaces:
GET /healthz: task and daemon health.POST /feishu/callback: Feishu/Lark callback and manual refresh actions.GET /admin: password-protected task and recipient management.
The admin UI writes task and recipient files on disk. Restart the long-running process after configuration changes. On Vercel, file mutations are disabled; the Flask entrypoint remains suitable for callbacks, health checks, and manual execution, but Vercel does not replace the persistent scheduler process.
Production Linux deployment uses Waitress behind Nginx with exactly one service
process so the scheduler cannot execute tasks twice. Follow
docs/DEVOPS.md for installation, upgrades, rollback,
backups, and troubleshooting.
Render card JSON without sending it:
python3 -m lark_push.preview --task hello_hourly_progress --mock
python3 -m lark_push.preview --task zenmux_personal_report --mockOmit --mock to execute the task's live fetch_data.py.
Every tasks/<task_id>/ directory contains:
config.json
template.json
fetch_data.py
mock_data.json
README.md
config.jsondefines schedules, routing, data files, and alert behavior.template.jsonis a Feishu/Lark card JSON 2.0 payload using{{ path.to.value }}placeholders.fetch_data.pyexposesfetch(context) -> dictfor live data.mock_data.jsonmirrors the live data shape for local and CI previews.README.mdrecords task behavior, owners, and recipient refs.
The daemon persists active-message state to runtime/state.json. Recipient
changes made through the admin UI are stored in
runtime/managed_recipients.json. Both are intentionally excluded from Git.
python3 -m compileall -q app.py lark_push tasks tests
python3 -m unittest discover -s tests -v
python3 -m lark_push.preview --task hello_hourly_progress --mock
python3 -m lark_push.preview --task zenmux_personal_report --mock
PYTHON_BIN=python3 bash scripts/verify.shThe verification script starts an isolated local service with disabled task copies, exercises health, callback, login, recipient writes, and task creation, then removes all temporary state. It never sends a real Lark message.
GitHub Actions runs the same checks on Python 3.12 and 3.14. See
CONTRIBUTING.md for the branch and pull-request workflow.