This document is written for a coding agent (Claude Code, Codex, or similar) that is helping a human install darwin-evolve. If you are that agent: you drive. Run the commands yourself, verify each phase before moving on, and only involve the human for the three things you cannot do: clicking through the Feishu console, pasting secrets, and answering persona questions.
Rules of engagement:
- Verify, then proceed. Every phase ends with a check; do not continue past a failing check, diagnose it first.
- Never invent credentials, chat IDs, or scope names. If something is unknown, get it from the console, the logs, or the database.
- Secrets belong in
.envonly. If the user prefers not to paste secrets into the chat, have them edit.envdirectly and tell you when done. - Keep the user informed with one-line progress notes, not walls of text.
node --version # need 20, 22, or 24+
git --version
claude --version || codex --version # at least one coding-agent CLI, installed and authenticatedThen install and verify the tree:
npm install # postinstall bootstraps agent-runner/
npm run build:all
npm test # expect: 205 passedIf tests fail on a fresh clone, stop and investigate before touching configuration.
Guide the user through https://open.feishu.cn (or their tenant's admin console):
- Create a custom app (企业自建应用). Suggested name: whatever they want to call their agent, e.g. Darwin.
- Add the Bot capability (机器人).
- Permissions (权限管理): grant the IM message scopes so the bot can receive and send messages and manage reactions. Have the user search for and enable the message read, message send, and message reaction scopes. Exact scope names vary by console version; if the running app later fails with a permission error, the error message names the missing scope. Grant it and publish a new app version.
- Events (事件与回调): set the subscription mode to Long Connection (长连接). This is important, it means no public webhook URL and no server are needed. Then subscribe to the event
im.message.receive_v1. - Publish: create a version and release it (self-built apps are usually approved instantly).
- From 凭证与基础信息, copy the App ID and App Secret.
cp .env.example .envFill in, asking the user for each value:
FEISHU_APP_ID/FEISHU_APP_SECRET: from Phase 1.ASSISTANT_NAME: what the agent answers to. The chat trigger becomes@<name>.WIKI_LANGUAGE: the language the evolution loops will write the knowledge base in. Match the user's language (e.g.Chinese).
npm run devWatch the logs. Success looks like the Feishu channel connecting without a credentials warning. A Channel installed but credentials missing warning means .env is wrong or unread.
With the process running, ask the user to send any direct message to the bot in Feishu (or add it to a group and @ it). The message will not get a reply yet, that is expected: the chat is not registered.
Incoming messages are stored even for unregistered chats, so fish the chat ID out of the message store:
node -e "
const db = require('better-sqlite3')('store/messages.db');
console.log(db.prepare('SELECT DISTINCT chat_jid, sender_name FROM messages ORDER BY rowid DESC LIMIT 5').all());
"(If the table or column names differ, inspect the schema with .tables-style introspection via better-sqlite3, or read src/db.ts. Do not guess.)
Take the user's chat JID (format feishu:oc_...), then edit scripts/register-feishu.ts: replace the placeholder chat ID with the real one, set trigger to @<ASSISTANT_NAME>, keep isMain: true for this first chat. Run it:
npx tsx scripts/register-feishu.tsRestart the dev process, have the user message the bot again, and confirm a reply arrives. That reply is the whole pipeline working end to end: Feishu, router, agent-runner, coding-agent CLI, and back.
Interview the user briefly (three questions is plenty):
- How should the agent address you?
- What persona or voice should it have, if any?
- Anything it should know about you from day one (role, interests, timezone)?
Write the answers into groups/CLAUDE.md: fill the persona placeholder and the User Profile template.
Privacy warning to relay verbatim: groups/CLAUDE.md is tracked by git. If the user's fork is public, personal details written here will be public too. Offer the choice: keep the fork private, or keep this file generic and put personal details in groups/main/CLAUDE.md patterns instead (per-group files under groups/* are gitignored except the shipped templates).
bash scripts/start.sh # pm2 daemon; logs via scripts/logs.sh
npm run setup -- --step verifyExplain to the user what is now running on a schedule:
| Task | When |
|---|---|
| Reflection (self-review of the day) | daily 23:00 |
| Learning (topic study) | every 60 min |
| Synthesis (knowledge-graph maintenance) | Sunday 03:00 |
| MOC rebuild (index consistency) | daily 01:00 |
These four tasks are self-healing: they re-register themselves on every boot. The wiki/ directory will start growing within a day.
End with a short summary for the user:
- What was configured and where (
.env, registered chats, persona file). - How to operate it:
scripts/start.sh/stop.sh/restart.sh/logs.sh, and/claudevs/codexin chat to switch engines. - How to register more group chats (repeat Phase 4 with
isMain: falseand a new folder name). - Where the knowledge will accumulate (
wiki/) and what graduates into always-loaded rules. - That the safety boundary means the agent will propose, never self-apply, changes to its own code. Proposals land in
wiki/proposals/for the user to review.