mirror of
https://github.com/chenhg5/cc-connect.git
synced 2026-07-03 12:28:10 +08:00
* feat(matrix): add Matrix platform adapter using mautrix-go Implements a full Matrix protocol adapter so users can interact with their coding agent through any Matrix homeserver (matrix.org, self-hosted Synapse/Dendrite, etc.). Uses mautrix-go SDK for Client-Server API. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(matrix): add Matrix platform documentation Update README.md, README.zh-CN.md, INSTALL.md, CLAUDE.md and add docs/matrix.md with setup guide, config reference and FAQ. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(matrix): add unit tests and fix session key parsing 35 tests covering config validation, message handling, lifecycle, concurrency, and error paths. Race detector clean. Fixes two bugs found by tests: - stripBotMention: strip matrix.to URL before plain user ID to avoid partial replacement inside the URL path - ReconstructReplyCtx: room IDs contain colons, so colon-based SplitN corrupted them; use ":@" boundary detection instead Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(matrix): add Chinese setup guide Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(matrix): add E2EE support via mautrix cryptohelper Add Olm/Megolm encryption support using mautrix-go's built-in cryptohelper. Encrypted rooms are now fully supported for both sending and receiving messages. Key implementation details: - Crypto DB stored per device ID (~/.cc-connect/matrix-crypto-<device>.db) - Auto-recovers from stale device keys by force-uploading new keys - All outbound messages encrypted via sendRoomEvent when room has E2EE - DecryptErrorCallback logs decryption failures through slog - Cleanup client stores on failed crypto init to prevent DB panics Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(matrix): update setup guide with E2EE instructions - Recommend creating dedicated device via curl login (avoids E2EE issues) - Add E2EE section with startup log example showing device_id - Add FAQ entries for common E2EE problems and troubleshooting - Document crypto DB location and cleanup steps Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(matrix): add SAS verification and cross-signing support Enable auto-accept SAS key verification so users can verify the bot's device from Element. Bootstrap cross-signing to eliminate "encrypted by a device not verified by its owner" warning on bot messages. - Add verification helper with auto-accept/auto-confirm SAS flow - Workaround mautrix MAC verification bug for cross-user verification - Fix in-room verification transaction ID lookup from m.relates_to - Persist cross-signing seeds to disk for stable keys across restarts - Support m.login.password UIA fallback for publishing cross-signing keys - Add auto_verify and cross_signing_password config options Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(matrix): add verification and cross-signing documentation Add SAS verification and cross-signing setup instructions to both English and Chinese Matrix guides. Document new config options (auto_verify, cross_signing_password) and FAQ entries for device verification and the red exclamation mark warning. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(matrix): fix inaccurate documentation and capability table - Fix Matrix "Markdown / cards" from ✅ to ⚠️ (no CardSender) - Change "red exclamation mark" to "red question mark" per actual UI - Recommend curl with dedicated device_id for token (not Element) - Add cross-signing seeds file to E2EE reset instructions - Clarify that cross-signing may need cross_signing_password Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(matrix): reduce verbose logging in production Downgrade per-message and internal workaround logs from Info to Debug, and use structured fields for SAS verification log. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(matrix): fix formatting, rename field, and add token redaction - Run gofmt to fix struct definition and literal alignment - Rename shareSessionInChan to shareSessionInChannel for consistency with other platforms (Telegram, Discord, Slack) - Add core.RedactToken() in connectLoop error logging to prevent access token leakage in logs Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ci: install libolm-dev for Matrix E2EE crypto The mautrix-go crypto package depends on libolm (C library) for end-to-end encryption. The CI runners don't have it pre-installed, causing golangci-lint to fail when loading the CGO package. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(matrix): use build-tagged E2EE to avoid CGO/libolm dependency Split E2EE (end-to-end encryption) code behind a `goolm` build tag so the default build compiles without CGO or libolm-dev. This fixes CI lint failures caused by the mautrix-go crypto package pulling in the CGO-based libolm backend by default. - Default build: no E2EE, no CGO, CI lint passes - Build with `-tags goolm`: full E2EE using pure-Go olm backend Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * build: enable goolm tag by default in Makefile Matrix E2EE requires the goolm build tag. Add it as a default tag in the Makefile so `make build` includes E2EE automatically. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(matrix): suppress unused field lint for cryptoHelper The cryptoHelper field is only accessed in e2ee.go (goolm build tag), so the default build's linter flags it as unused. Add //nolint:unused since this is intentional. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(matrix): add Matrix platform adapter using mautrix-go Implements a full Matrix protocol adapter so users can interact with their coding agent through any Matrix homeserver (matrix.org, self-hosted Synapse/Dendrite, etc.). Uses mautrix-go SDK for Client-Server API. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(matrix): add Matrix platform documentation Update README.md, README.zh-CN.md, INSTALL.md, CLAUDE.md and add docs/matrix.md with setup guide, config reference and FAQ. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(matrix): add unit tests and fix session key parsing 35 tests covering config validation, message handling, lifecycle, concurrency, and error paths. Race detector clean. Fixes two bugs found by tests: - stripBotMention: strip matrix.to URL before plain user ID to avoid partial replacement inside the URL path - ReconstructReplyCtx: room IDs contain colons, so colon-based SplitN corrupted them; use ":@" boundary detection instead Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(matrix): add Chinese setup guide Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(matrix): add E2EE support via mautrix cryptohelper Add Olm/Megolm encryption support using mautrix-go's built-in cryptohelper. Encrypted rooms are now fully supported for both sending and receiving messages. Key implementation details: - Crypto DB stored per device ID (~/.cc-connect/matrix-crypto-<device>.db) - Auto-recovers from stale device keys by force-uploading new keys - All outbound messages encrypted via sendRoomEvent when room has E2EE - DecryptErrorCallback logs decryption failures through slog - Cleanup client stores on failed crypto init to prevent DB panics Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(matrix): update setup guide with E2EE instructions - Recommend creating dedicated device via curl login (avoids E2EE issues) - Add E2EE section with startup log example showing device_id - Add FAQ entries for common E2EE problems and troubleshooting - Document crypto DB location and cleanup steps Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(matrix): add SAS verification and cross-signing support Enable auto-accept SAS key verification so users can verify the bot's device from Element. Bootstrap cross-signing to eliminate "encrypted by a device not verified by its owner" warning on bot messages. - Add verification helper with auto-accept/auto-confirm SAS flow - Workaround mautrix MAC verification bug for cross-user verification - Fix in-room verification transaction ID lookup from m.relates_to - Persist cross-signing seeds to disk for stable keys across restarts - Support m.login.password UIA fallback for publishing cross-signing keys - Add auto_verify and cross_signing_password config options Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(matrix): add verification and cross-signing documentation Add SAS verification and cross-signing setup instructions to both English and Chinese Matrix guides. Document new config options (auto_verify, cross_signing_password) and FAQ entries for device verification and the red exclamation mark warning. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(matrix): fix inaccurate documentation and capability table - Fix Matrix "Markdown / cards" from ✅ to ⚠️ (no CardSender) - Change "red exclamation mark" to "red question mark" per actual UI - Recommend curl with dedicated device_id for token (not Element) - Add cross-signing seeds file to E2EE reset instructions - Clarify that cross-signing may need cross_signing_password Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(matrix): reduce verbose logging in production Downgrade per-message and internal workaround logs from Info to Debug, and use structured fields for SAS verification log. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(matrix): fix formatting, rename field, and add token redaction - Run gofmt to fix struct definition and literal alignment - Rename shareSessionInChan to shareSessionInChannel for consistency with other platforms (Telegram, Discord, Slack) - Add core.RedactToken() in connectLoop error logging to prevent access token leakage in logs Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ci: install libolm-dev for Matrix E2EE crypto The mautrix-go crypto package depends on libolm (C library) for end-to-end encryption. The CI runners don't have it pre-installed, causing golangci-lint to fail when loading the CGO package. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(matrix): use build-tagged E2EE to avoid CGO/libolm dependency Split E2EE (end-to-end encryption) code behind a `goolm` build tag so the default build compiles without CGO or libolm-dev. This fixes CI lint failures caused by the mautrix-go crypto package pulling in the CGO-based libolm backend by default. - Default build: no E2EE, no CGO, CI lint passes - Build with `-tags goolm`: full E2EE using pure-Go olm backend Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * build: enable goolm tag by default in Makefile Matrix E2EE requires the goolm build tag. Add it as a default tag in the Makefile so `make build` includes E2EE automatically. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(matrix): suppress unused field lint for cryptoHelper The cryptoHelper field is only accessed in e2ee.go (goolm build tag), so the default build's linter flags it as unused. Add //nolint:unused since this is intentional. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(matrix): resolve lint errors for CI (errcheck + staticcheck) * feat(agent): add GitHub Copilot as a first-class agent (#865) * chore: ignore web/tsconfig.tsbuildinfo (TS incremental build cache) Co-authored-by: Cursor <cursoragent@cursor.com> * feat(qqbot): add inline keyboard buttons and INTERACTION_CREATE event handling (#1131) * feat(qqbot): add support for inline keyboard buttons and interaction events - Update default intents to include INTERACTION_CREATE - Implement SendWithButtons to send messages with inline keyboard buttons - Encode permission decisions and session key in button_data for routing callbacks - Handle INTERACTION_CREATE events to process button clicks as permission responses - Create synthetic message for permission decisions and forward to engine - Add ackInteraction to acknowledge INTERACTION_CREATE events via API call - Add extensive tests for sending buttons, handling interactions, and edge cases * fix(qqbot): ignore ackInteraction error and correct test URL check - Suppress error from ackInteraction to avoid unused error variable warning - Update test to expect corrected interaction URL path "/interactions/interact-1" instead of "/v2/interactions/interact-1" * - Add sessionKey field to replyContext to embed in button_data and session routing - Refactor SendWithButtons to use sessionKey from replyContext and validate emptiness - Enhance replyContext construction with sessionKey in various message scenarios - Implement new tests for sharing session keys in channel, empty session key errors, and interaction_create event permission routing - Update config.example.toml to document new required intents for interaction support - Modify changelog with instructions on enabling INTERACTION_CREATE intent (bit 26) for QQ Bot - Permission requests now use clickable inline buttons instead of text replies, requiring enabling the INTERACTION capability in QQ Open Platform settings * test(qqbot): ignore errors and returned values in test HTTP handlers * feat: integrate Google Antigravity CLI (agy) agent * Harden antigravity session discovery and attachment handling to preserve resume correctness under contention Constraint: Keep external behavior and interfaces unchanged while improving runtime robustness Rejected: Full process-level session correlation | Requires upstream CLI contract not available here Confidence: medium Scope-risk: narrow Directive: Keep session-id detection conservative unless agy exposes explicit correlation metadata Tested: go test ./agent/antigravity/... && go test ./core/... && go test ./cmd/cc-connect/... Not-tested: Real concurrent agy process race on multi-session host * Fix antigravity prompt execution and shutdown safety without changing user-facing flow Constraint: Preserve existing antigravity integration surface and core event handling contracts Rejected: Introduce a custom permission event parser for agy stdout | No stable upstream protocol contract yet Confidence: medium Scope-risk: narrow Directive: If agy publishes structured permission I/O, replace y/n terminal fallback with typed request/response framing Tested: go test ./agent/antigravity/... && go test ./core/... && go test ./cmd/cc-connect/... Not-tested: End-to-end interactive agy permission prompt against a live CLI binary * Stabilize antigravity permission flow so Discord approvals consistently drive CLI execution Constraint: Preserve current antigravity stream/event contracts while improving permission reliability Rejected: Full structured agy protocol parser | Upstream schema is not yet stable/public Confidence: medium Scope-risk: narrow Directive: Replace regex prompt detection with typed protocol once agy exposes machine-readable permission events Tested: go test ./agent/antigravity/... && go test ./core/... && go test ./cmd/cc-connect/... && go build ./cmd/cc-connect Not-tested: Live Discord permission prompts across all locales/terminal themes * Prevent agy hangs and unsupported flag crashes in cross-platform antigravity runs Constraint: Keep antigravity adapter behavior compatible across Telegram/Discord while avoiding CLI-specific crashes Rejected: Keep passing -m and rely on user wrapper scripts | Breaks agy v1.0.2 directly for normal users Confidence: high Scope-risk: narrow Directive: Re-enable explicit model flag only after agy documents stable model flag support Tested: go test ./agent/antigravity/... && go test ./core/... && go test ./cmd/cc-connect/... && go build ./cmd/cc-connect Not-tested: Live agy v1.0.2 interactive permission prompts on Telegram with real long-running tool tasks * Fix lint-blocking errcheck findings in antigravity adapter without behavior changes Constraint: Keep runtime behavior unchanged while satisfying CI lint gates Rejected: Broader refactor around file/stream lifecycle | Unnecessary for this blocking lint failure Confidence: high Scope-risk: narrow Directive: Keep close/remove calls explicitly checked or intentionally ignored with clear intent in this package Tested: go test ./agent/antigravity/... && go test ./core/... && go test ./cmd/cc-connect/... Not-tested: Full GitHub Actions rerun output * Fix remaining errcheck close-handling findings from CI lint Constraint: Resolve lint blockers without behavioral changes Rejected: Broad lifecycle refactor | unnecessary for this CI-only failure class Confidence: high Scope-risk: narrow Directive: Keep file/stream close sites explicitly checked or intentionally ignored for errcheck Tested: go test ./agent/antigravity/... && go test ./core/... && go test ./cmd/cc-connect/... Not-tested: GitHub Actions rerun not yet executed * docs: update MiniMax banner to M3 release - Replace minimax-en.jpeg and minimax-zh.jpeg with new M3 PNG banners - Update MiniMax description in both READMEs to reflect M3 benchmarks (SWE-Bench Pro 59.0, Terminal Bench 2.1 66.0, VIBE V2 60.1, etc.) - Update tagline: "Build, Learn & Ship" / "Mini 价格 Max 性能" Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore: update MiniMax model to M3 in provider presets - Switch primary model from MiniMax-M2.7 to MiniMax-M3 - Add MiniMax-M3-highspeed variant - Keep M2.7 as fallback for compatibility - Update descriptions to reflect M3 features (Sparse Attention, Multimodal) - Bump updated_at to 2026-06-03 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(core): /stop preserves AgentSessionID so next message can resume (#1196) `cmdStop` no longer clears `AgentSessionID`; the next message can `--resume` the conversation, matching the card-button Stop path and eliminating the inconsistency described in #1189. - Session-ID write-back now always follows the live forked ID Claude reports on every `--resume` (was: skip if already set); name binding still fires only on first assignment to avoid polluting `sessionNames` - Removed `clearStaleSessionID` helper and `CompareAndSetAgentSessionID` guard; replaced with unconditional `SetAgentSessionID` + `wasEmpty` name-binding gate - Updated / renamed affected tests: - TestSessionIDWriteback_TracksLiveForkedID - TestInteractiveWriteBack_TracksForkedSessionID - TestInteractiveWriteBack_NamingBindsOnlyOnFirstAssignment - TestCmdStop_PreservesAgentSessionID Closes #1189 * fix: three bug fixes — WPS ChannelKey, Telegram text_link, workspace bind path fix(wps-xiezuo): set ChannelKey on inbound messages for per-group session isolation (#1217). Without ChannelKey, messages from different WPS groups were routed to the same session. fix(telegram): forward text_link entity URLs to agent as [label](url) (#1207). Telegram passes inline hyperlinks as entities (not in the plain text), so the agent never saw the URL. enrichTextLinks() rewrites text_link spans in-place using UTF-16 offsets (Telegram's coordinate system). fix(core): splitCommandArgs() respects quoted paths in /workspace bind (#1211). strings.Fields splits on every space, truncating paths like '/workspace bind "/my project/foo"'. The new parser honours single and double quotes so space-containing paths work correctly. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(pi): correct agent directory paths (SkillDirs + GlobalMemoryFile) (#1206) * fix(pi): correct SkillDirs paths for pi agent skill discovery cc-connect's pi agent reported wrong skill directories (~/.pi/skills/ instead of ~/.pi/agent/skills/), causing SkillRegistry to never find pi skills. This meant slash commands like /caveman were not intercepted by cc-connect's command routing — they fell through to pi's print mode as raw text, and the LLM never received the skill instructions. Fix: - ~/.pi/skills/ -> ~/.pi/agent/skills/ (pi's default agent dir) - Add ~/.agents/skills/ (common shared skill dir) - Add /skills/ if env var is set * fix(pi): correct GlobalMemoryFile path pi loads global AGENTS.md from getAgentDir() which defaults to ~/.pi/agent/, not ~/.pi/. Respect if set. * chore(pi): consistent homeDir variable naming in SkillDirs * fix(pi): add SetWorkDir to enable /dir command (#1177) pi agent implemented GetWorkDir() but not SetWorkDir(), so the WorkDirSwitcher interface was incomplete and /dir always returned 'current agent does not support dynamic work directory switching'. * fix(pi): pipe prompt via stdin to avoid CLI option parsing (#1185) Reply chain headers start with "---", which pi's CLI parser interprets as an option flag, producing "Unknown option" errors. Pass the prompt via stdin instead of as a positional argument, consistent with how gemini and codex agents handle it. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * fix(pi): read enabledModels from settings.json for /model (#1178) * fix(pi): read enabledModels from settings.json for /model AvailableModels() now reads ~/.pi/agent/settings.json enabledModels instead of returning nil. New() also falls back to defaultModel from settings when opts don't specify model. Add helpers: piSettingsDir, settingsPath, readSettings, readSettingsModels, readDefaultModel. Respects PI_CODING_AGENT_DIR. * fix(pi): check err return values in tests to pass errcheck linter * fix(pi): silence errcheck for os.Setenv/Unsetenv in defer cleanup blocks * feat(dingtalk): add reaction emoji support (#1213) * feat(dingtalk): add reaction emoji support * fix(dingtalk): satisfy emotion lint * feat(slack,tmux): per-thread session scope and per-session tmux windows (#1179) Add `session_scope` to the Slack platform ("user" | "channel" | "thread"). "thread" keys each Slack thread to its own cc-connect session, so a new top-level message starts a fresh conversation while replies in the same thread continue it. Backward compatible: when unset, behaviour is unchanged (share_session_in_channel maps to "channel"). Add `window_per_session` to the tmux agent: each cc-connect session gets its own tmux window (and its own init_command/agent instance) instead of sharing one pane. Required for real isolation when the platform splits sessions per thread; otherwise concurrent threads interleave into a single shared agent. The allocated window name doubles as the agent session ID so resumes reuse the same window. Both options default off. Includes unit tests and config.example.toml docs. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> * Reply to unauthorized IM senders (#1190) * feat(relay): configure group visibility (#1209) * feat(send): 支持 --at-users / --at-all 命令行参数,DingTalk @mention 通知 (#1188) * feat(send): add --at-users and --at-all support for DingTalk @mention - Add --at-users and --at-all flags to cc-connect send command - Add AtMentionSender optional interface for platforms that support @mention - Implement ReplyWithAt in DingTalk platform using text msgtype - Add CheckLinger stub for macOS compatibility * fix: update test callers for SendToSessionWithAttachments new signature * feat(send): add --at-users and --at-all support for DingTalk @mention - Add --at-users and --at-all flags to cc-connect send command - Add AtMentionSender optional interface for platforms that support @mention - Implement ReplyWithAt in DingTalk platform using text msgtype - Add CheckLinger stub for macOS compatibility - Update all test callers for new signature * fix(dingtalk): check resp.Body.Close return value for errcheck Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: wen_guoxing <wen_guoxing@itrus.com.cn> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> * feat(cron): align manual trigger command with exec (#1201) * feat: add manual cron run support * feat(cron): align manual trigger command with exec * fix(cron): guard shell manual triggers * test(cron): accept manual run output before trigger ack * test(release): align footer expectations without markdown italics * fix(core): keep full reply footer paths * test(core): normalize local dir path expectation * fix(cron): check exec response body close --------- Co-authored-by: aoko <aokodesuka@gmail.com> Co-authored-by: 张彧 <aaron@mac.tail449498.ts.net> Co-authored-by: 张彧 <aaron@Aaron-MacBook-Pro-14.local> * feat(codex): support request_user_input app-server events (#1200) Co-authored-by: Cursor <cursoragent@cursor.com> * feat(feishu): refresh rich card rendering and panel handling (#1204) Squash merge of PR #1204 (rebased onto main, minor conflicts resolved). Adds structured per-turn reply footer, cardkit-v1 streaming, status footer interface, claude context usage tracking, and rich card body improvements. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(feishu): send audio and video attachments as media (#1202) Co-authored-by: Cursor <cursoragent@cursor.com> * fix(opencode): pass --agent flag when agent config option is set (#1210) Adds optional 'agent' config option under [projects.agent.options] for opencode. When set, the value is passed as --agent to every 'opencode run' invocation, enabling plugin-defined agents (e.g. oh-my-openagent's 'Sisyphus - Ultraworker') to work correctly without falling back to the default agent. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(core): remove leftover conflict markers in engine_test.go from #1202 merge Co-authored-by: Cursor <cursoragent@cursor.com> * fix: three bug fixes for #1184, #1139, and #1176 fix(core): multiSelect AskUserQuestion on card platforms (closes #1184) - For multiSelect questions, render options as a numbered text list instead of instant-resolve buttons (buttons resolved on first click, preventing multi-selection) - Add new i18n key MsgAskQuestionNoteMulti with per-language hint to reply with comma-separated numbers (e.g. 1,3) - Single-select questions keep the existing button UX unchanged fix(config): allow cc-connect web with agent-only config (closes #1139) - Add LoadPermissive() / validatePermissive() that skip the "at least one platform" requirement - runWeb now uses LoadPermissive so the web admin UI starts even before any platforms are configured, enabling first-time setup fix(weixin): fail fast on ret=-2 when context_token cannot be refreshed (closes #1176) - When sendMessage returns ret=-2 and the stored token is the same as the current one (no inbound message has refreshed it), stop retrying immediately instead of burning 3 retries on the same stale token - Return a clear actionable error: "user must send a new message to refresh the session token" - Applied to both text (weixin.go) and media (media_outbound.go) paths Co-authored-by: Cursor <cursoragent@cursor.com> * fix(matrix): support MATRIX_CROSS_SIGNING_PASSWORD env var and document crypto DB paths - Add environment variable fallback for cross_signing_password (env var takes precedence over config file, avoiding plaintext password in config) - Document E2EE crypto data storage location (~/.cc-connect/) and file purpose (crypto DB + cross-signing seeds) in both English and Chinese setup guides - Add data directory comment in config.example.toml Addresses P3 items from PR #834 review. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: m3 <Marvae@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: 7a3lv7 <hjkl931031@gmail.com> Co-authored-by: JazzuLu <27945372+JazzuLu@users.noreply.github.com> Co-authored-by: shellus <353358601@qq.com> Co-authored-by: Han <hanzr.nju@outlook.com> Co-authored-by: Marco <48539922+MMMarcinho@users.noreply.github.com> Co-authored-by: masakasu <32926719+MASAKASUNO1@users.noreply.github.com> Co-authored-by: Rael <realraelmail@gmail.com> Co-authored-by: Yu Zhang <34849476+AaronZ345@users.noreply.github.com> Co-authored-by: wgx521 <wgx521@139.com> Co-authored-by: wen_guoxing <wen_guoxing@itrus.com.cn> Co-authored-by: aoko <aokodesuka@gmail.com> Co-authored-by: 张彧 <aaron@mac.tail449498.ts.net> Co-authored-by: 张彧 <aaron@Aaron-MacBook-Pro-14.local>
836 lines
26 KiB
Markdown
836 lines
26 KiB
Markdown
# cc-connect Installation & Configuration Guide
|
||
|
||
> **This document is designed to be read by AI coding agents (Claude Code, Cursor, Gemini CLI, etc.) to help users install and configure cc-connect.** You can feed this file directly to your AI agent.
|
||
|
||
## What is cc-connect?
|
||
|
||
cc-connect bridges local AI coding assistants to messaging platforms (Feishu, DingTalk, Telegram, Slack, Discord, LINE, WeChat Work, QQ, **personal WeChat** via the **Weixin (ilink)** platform).
|
||
|
||
GitHub: https://github.com/chenhg5/cc-connect
|
||
|
||
**IMPORTANT: If you are an AI agent helping a user install cc-connect, use interactive tools (like AskUserQuestion) to guide them through configuration choices:**
|
||
- Agent selection (Claude Code, Cursor, Gemini, etc.)
|
||
- Platform selection (Feishu, Telegram, Discord, etc.)
|
||
- API keys and authentication tokens
|
||
- Project paths and preferences
|
||
|
||
Don't guess values—always ask the user to choose via interactive prompts.
|
||
|
||
## Step 1: Install cc-connect
|
||
|
||
### Option A: npm (recommended for most users)
|
||
|
||
```bash
|
||
npm install -g cc-connect
|
||
```
|
||
|
||
After installation, the `cc-connect` binary will be available globally.
|
||
|
||
|
||
### Option B: Homebrew (macOS / Linux)
|
||
|
||
```bash
|
||
brew install cc-connect
|
||
```
|
||
|
||
### Option C: Download binary from GitHub Releases
|
||
|
||
Go to https://github.com/chenhg5/cc-connect/releases and download the binary for your platform.
|
||
|
||
Typical artifact names (check the release page for exact filenames):
|
||
|
||
- Linux: `cc-connect-<version>-linux-amd64` (or `.tar.gz`)
|
||
- macOS: `cc-connect-<version>-darwin-amd64` / `arm64`
|
||
- Windows: `cc-connect-<version>-windows-amd64.exe` (or `.zip`)
|
||
|
||
```bash
|
||
# Example for Linux amd64 (replace URL with the asset link from the release you chose):
|
||
curl -L -o cc-connect https://github.com/chenhg5/cc-connect/releases/latest/download/cc-connect-linux-amd64
|
||
chmod +x cc-connect
|
||
sudo mv cc-connect /usr/local/bin/
|
||
```
|
||
|
||
On macOS, you may need to remove the quarantine attribute:
|
||
|
||
```bash
|
||
xattr -d com.apple.quarantine cc-connect
|
||
```
|
||
|
||
### Option D: Build from source
|
||
|
||
Requires Go 1.22+.
|
||
|
||
```bash
|
||
git clone https://github.com/chenhg5/cc-connect.git
|
||
cd cc-connect
|
||
make build
|
||
# Binary will be at ./cc-connect
|
||
```
|
||
|
||
## Step 2: Install your AI Agent
|
||
|
||
cc-connect supports multiple local coding agents. Install at least one:
|
||
|
||
```bash
|
||
# Claude Code
|
||
npm install -g @anthropic-ai/claude-code
|
||
|
||
# Codex
|
||
npm install -g @openai/codex
|
||
|
||
# Gemini CLI
|
||
npm install -g @google/gemini-cli
|
||
|
||
# iFlow CLI
|
||
npm install -g @iflow-ai/iflow-cli
|
||
|
||
# Qoder CLI
|
||
curl -fsSL https://qoder.com/install | bash
|
||
```
|
||
|
||
For **Cursor Agent** and **OpenCode**, follow their official install docs:
|
||
- Cursor Agent: https://docs.cursor.com/agent
|
||
- OpenCode: https://github.com/opencode-ai/opencode
|
||
|
||
Verify your selected agent works:
|
||
|
||
```bash
|
||
claude --version
|
||
codex --version
|
||
gemini --version
|
||
iflow --version
|
||
opencode --version
|
||
qodercli --version
|
||
```
|
||
|
||
## Step 3: Create config.toml
|
||
|
||
> **💡 Recommended: Use the Web UI** — After installing, run `cc-connect web` to configure the web admin and open the dashboard in your browser. You can visually create projects, add platforms, manage API providers, and even chat with your agent directly from the browser — no need to edit TOML files by hand. **Note:** `cc-connect web` only configures and opens the browser — you still need to run `cc-connect` separately to start the service.
|
||
|
||
If you prefer manual configuration, cc-connect looks for config in this order:
|
||
1. `-config <path>` flag (explicit)
|
||
2. `./config.toml` (current directory)
|
||
3. `~/.cc-connect/config.toml` (global, **recommended**)
|
||
|
||
If no config file exists, running `cc-connect` will auto-create a starter template at `~/.cc-connect/config.toml`.
|
||
|
||
**Manual config location:**
|
||
|
||
```bash
|
||
mkdir -p ~/.cc-connect
|
||
# If you cloned the repo, copy the example:
|
||
cp config.example.toml ~/.cc-connect/config.toml
|
||
# Or just run cc-connect once — it will create a starter config automatically
|
||
```
|
||
|
||
You can also use a local config in the current directory:
|
||
|
||
```bash
|
||
cp config.example.toml config.toml
|
||
```
|
||
|
||
The configuration has this structure:
|
||
|
||
```toml
|
||
# Optional global settings
|
||
# language = "en" # "en", "zh", or "" (auto-detect)
|
||
|
||
[log]
|
||
level = "info" # debug, info, warn, error
|
||
|
||
# Each [[projects]] entry connects one code folder to one or more messaging platforms
|
||
[[projects]]
|
||
name = "my-project"
|
||
|
||
[projects.agent]
|
||
type = "claudecode" # or "codex", "cursor", "gemini", "qoder", "opencode", "iflow"
|
||
|
||
[projects.agent.options]
|
||
work_dir = "/absolute/path/to/your/project"
|
||
mode = "default"
|
||
|
||
# --- Claude Code mode options ---
|
||
# "default", "acceptEdits" (alias: "edit"), "plan", "auto", "bypassPermissions" (alias: "yolo")
|
||
# allowed_tools = ["Read", "Grep", "Glob"] # optional: pre-approve specific tools
|
||
|
||
# --- Codex mode options ---
|
||
# "suggest" (default), "auto-edit", "full-auto", "yolo"
|
||
# model = "o3" # optional: specify model
|
||
|
||
# --- Qoder CLI mode options ---
|
||
# "default", "yolo"
|
||
# model = "auto" # "auto", "ultimate", "performance", "efficient", "lite"
|
||
|
||
# --- iFlow CLI mode options ---
|
||
# "default", "auto-edit", "plan", "yolo"
|
||
# model = "Qwen3-Coder" # optional: specify model
|
||
|
||
# Add one or more platform sections below
|
||
```
|
||
|
||
## Step 4: Configure a Messaging Platform
|
||
|
||
Choose one or more platforms to connect. Each platform requires creating a bot/app on the platform's developer console and copying credentials into config.toml.
|
||
|
||
---
|
||
|
||
### Feishu (Lark) — No public IP needed
|
||
|
||
Connection: WebSocket long connection (SDK auto-negotiates)
|
||
|
||
**CLI shortcut (recommended):**
|
||
|
||
```bash
|
||
# Recommended: unified entry
|
||
cc-connect feishu setup --project my-project
|
||
cc-connect feishu setup --project my-project --app cli_xxx:sec_xxx
|
||
|
||
# Force modes (usually unnecessary)
|
||
cc-connect feishu new --project my-project
|
||
|
||
cc-connect feishu bind --project my-project --app cli_xxx:sec_xxx
|
||
```
|
||
|
||
Notes:
|
||
- `setup` is the unified entry:
|
||
- no credentials => same as `new`
|
||
- with `--app`/`--app-id` => same as `bind`
|
||
- `setup/new` prints a terminal QR code + URL for mobile scanning.
|
||
- If `--project` does not exist, cc-connect creates it automatically.
|
||
- This flow fills `app_id` / `app_secret`; in QR onboarding flow, Feishu usually pre-configures permissions and event subscriptions.
|
||
- Still verify app publish status and availability scope in Feishu Open Platform.
|
||
|
||
**Setup steps:**
|
||
1. Go to https://open.feishu.cn → Console → Create Enterprise App
|
||
2. Enable **Bot** capability (App Capabilities → Bot)
|
||
3. Go to **Permissions** → add `im:message.receive_v1`, `im:message:send_as_bot`
|
||
4. Go to **Event Subscriptions** → select **WebSocket long connection mode** → add event `im.message.receive_v1`
|
||
5. Publish the app version
|
||
6. Copy App ID and App Secret
|
||
|
||
**Config:**
|
||
|
||
```toml
|
||
[[projects.platforms]]
|
||
type = "feishu"
|
||
|
||
[projects.platforms.options]
|
||
app_id = "cli_xxxxxxxxxxxx"
|
||
app_secret = "xxxxxxxxxxxxxxxxxxxxxxxx"
|
||
```
|
||
|
||
**Detailed guide:** [docs/feishu.md](docs/feishu.md)
|
||
|
||
---
|
||
|
||
### DingTalk — No public IP needed
|
||
|
||
Connection: Stream mode (WebSocket)
|
||
|
||
**Setup steps:**
|
||
1. Go to https://open-dev.dingtalk.com → Create App
|
||
2. Enable **Bot** capability, select **Stream mode**
|
||
3. Configure permissions for messaging
|
||
4. Copy Client ID (AppKey) and Client Secret (AppSecret)
|
||
|
||
**Config:**
|
||
|
||
```toml
|
||
[[projects.platforms]]
|
||
type = "dingtalk"
|
||
|
||
[projects.platforms.options]
|
||
client_id = "dingxxxxxxxxxxxxxxxxx"
|
||
client_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||
```
|
||
|
||
**Detailed guide:** [docs/dingtalk.md](docs/dingtalk.md)
|
||
|
||
---
|
||
|
||
### Telegram — No public IP needed
|
||
|
||
Connection: Long Polling
|
||
|
||
**Setup steps:**
|
||
1. Message @BotFather on Telegram → send `/newbot`
|
||
2. Follow prompts to set bot name and username (must end with `bot`)
|
||
3. Copy the bot token
|
||
|
||
**Config:**
|
||
|
||
```toml
|
||
[[projects.platforms]]
|
||
type = "telegram"
|
||
|
||
[projects.platforms.options]
|
||
token = "1234567890:ABCdefGHIjklMNOpqrsTUVwxyz"
|
||
```
|
||
|
||
**Detailed guide:** [docs/telegram.md](docs/telegram.md)
|
||
|
||
---
|
||
|
||
### Slack — No public IP needed
|
||
|
||
Connection: Socket Mode (WebSocket)
|
||
|
||
**Setup steps:**
|
||
1. Go to https://api.slack.com/apps → Create New App → From scratch
|
||
2. Enable **Socket Mode** (Settings → Socket Mode) → generate App-Level Token (`xapp-...`)
|
||
3. Subscribe to bot events: `message.im`, `app_mention` (Event Subscriptions)
|
||
4. Add Bot Token Scopes: `chat:write`, `im:history`, `im:read`, `im:write`, `app_mentions:read`
|
||
5. Install App to Workspace → copy Bot Token (`xoxb-...`)
|
||
|
||
**Config:**
|
||
|
||
```toml
|
||
[[projects.platforms]]
|
||
type = "slack"
|
||
|
||
[projects.platforms.options]
|
||
bot_token = "xoxb-your-bot-token"
|
||
app_token = "xapp-your-app-level-token"
|
||
```
|
||
|
||
**Detailed guide:** [docs/slack.md](docs/slack.md)
|
||
|
||
---
|
||
|
||
### Discord — No public IP needed
|
||
|
||
Connection: Gateway WebSocket
|
||
|
||
**Setup steps:**
|
||
1. Go to https://discord.com/developers/applications → New Application
|
||
2. Go to **Bot** → Add Bot → copy Token
|
||
3. Enable **Message Content Intent** (under Privileged Gateway Intents)
|
||
4. Go to **OAuth2** → URL Generator → select scope `bot` → select permissions `Send Messages`, `Read Message History`
|
||
5. Open the generated URL to invite bot to your server
|
||
|
||
**Config:**
|
||
|
||
```toml
|
||
[[projects.platforms]]
|
||
type = "discord"
|
||
|
||
[projects.platforms.options]
|
||
token = "your-discord-bot-token"
|
||
```
|
||
|
||
**Detailed guide:** [docs/discord.md](docs/discord.md)
|
||
|
||
---
|
||
|
||
### LINE — Requires public URL
|
||
|
||
Connection: HTTP Webhook (you need ngrok, cloudflared, or a server with public IP)
|
||
|
||
**Setup steps:**
|
||
1. Go to https://developers.line.biz/console/ → Create Messaging API channel
|
||
2. Copy Channel Secret and Channel Access Token (long-lived)
|
||
3. Set webhook URL in LINE console: `https://<your-public-domain>:<port>/callback`
|
||
4. Expose local port using ngrok/cloudflared: `ngrok http 8080` or `cloudflared tunnel --url http://localhost:8080`
|
||
|
||
**Config:**
|
||
|
||
```toml
|
||
[[projects.platforms]]
|
||
type = "line"
|
||
|
||
[projects.platforms.options]
|
||
channel_secret = "your-channel-secret"
|
||
channel_token = "your-channel-access-token"
|
||
port = "8080"
|
||
callback_path = "/callback"
|
||
```
|
||
|
||
---
|
||
|
||
### WeChat Work (企业微信) — Requires public URL
|
||
|
||
Connection: HTTP Webhook (you need ngrok, cloudflared, or a server with public IP)
|
||
|
||
**Setup steps:**
|
||
1. Log in to https://work.weixin.qq.com/wework_admin/frame
|
||
2. **App Management** → Create custom app → note AgentId and Secret
|
||
3. **My Enterprise** → note Corp ID
|
||
4. In the app → **Receive Messages** → Set API Receive:
|
||
- URL: `https://<your-public-domain>:<port>/wecom/callback`
|
||
- Token: any random string
|
||
- EncodingAESKey: click "Random Generate" (43 chars)
|
||
- **Start cc-connect FIRST, then save** (to pass URL verification)
|
||
5. **Trusted IP** → add your server's outbound public IP
|
||
6. (Optional) **WeChat Plugin** → scan QR to link personal WeChat
|
||
|
||
**Config:**
|
||
|
||
```toml
|
||
[[projects.platforms]]
|
||
type = "wecom"
|
||
|
||
[projects.platforms.options]
|
||
corp_id = "wwxxxxxxxxxxxxxxxxx"
|
||
corp_secret = "your-app-secret"
|
||
agent_id = "1000002"
|
||
callback_token = "your-callback-token"
|
||
callback_aes_key = "your-43-char-encoding-aes-key"
|
||
port = "8081"
|
||
callback_path = "/wecom/callback"
|
||
api_base_url = "https://qyapi.weixin.qq.com" # optional: override WeChat Work API base URL (for private deployments)
|
||
enable_markdown = false # true = Markdown messages (WeChat Work app only; personal WeChat shows "unsupported")
|
||
# proxy = "http://your-vps-ip:8888" # optional: forward proxy if your IP is dynamic
|
||
```
|
||
|
||
**Detailed guide:** [docs/wecom.md](docs/wecom.md)
|
||
|
||
### Weixin (personal, ilink) — No public IP needed
|
||
|
||
Personal WeChat uses Tencent’s **ilink bot HTTP API** (same family as OpenClaw `openclaw-weixin`). The recommended flow is CLI QR login, which writes `token` (and related fields) into `config.toml`.
|
||
|
||
1. Run:
|
||
|
||
```bash
|
||
cc-connect weixin setup --project my-project
|
||
```
|
||
|
||
2. Scan the QR code (or open the printed URL) in WeChat and confirm.
|
||
|
||
3. Restart cc-connect, then send a message from WeChat once so `context_token` is cached.
|
||
|
||
If you already have a Bearer token, use `cc-connect weixin bind --project my-project --token '<token>'`.
|
||
|
||
**Detailed guide (Chinese):** [docs/weixin.md](docs/weixin.md)
|
||
|
||
### QQ (via NapCat / OneBot v11) — No public IP needed
|
||
|
||
QQ integration requires a third-party OneBot v11 implementation (e.g., NapCat) as a bridge.
|
||
|
||
1. Deploy NapCat (recommended via Docker):
|
||
```bash
|
||
docker run -d --name napcat -e ACCOUNT=<QQ号> -p 3001:3001 -p 6099:6099 --restart unless-stopped mlikiowa/napcat-docker:latest
|
||
```
|
||
2. First launch: check `docker logs -f napcat` for a QR code, scan with QQ mobile app to log in
|
||
3. Open NapCat WebUI at `http://localhost:6099`, enable **Forward WebSocket** on port 3001
|
||
4. Add to `config.toml`:
|
||
|
||
```toml
|
||
[[projects.platforms]]
|
||
type = "qq"
|
||
|
||
[projects.platforms.options]
|
||
ws_url = "ws://127.0.0.1:3001" # NapCat Forward WebSocket URL
|
||
token = "" # optional: access_token (must match NapCat config)
|
||
allow_from = "*" # allowed QQ user IDs: "12345,67890" or "*" for all
|
||
```
|
||
|
||
**Detailed guide:** [docs/qq.md](docs/qq.md)
|
||
|
||
---
|
||
|
||
### Matrix — No public IP needed
|
||
|
||
Connection: Long Polling via /sync
|
||
|
||
**Setup steps:**
|
||
1. Create an account on a Matrix homeserver (e.g. [matrix.org](https://matrix.org), or your own self-hosted server)
|
||
2. Get an access token:
|
||
- Open **Element** (or your preferred Matrix client)
|
||
- Go to **Settings** → **Help & About** → **Advanced** → click **Access Token**
|
||
- Copy the token (it starts with `syt_` on most servers)
|
||
3. (Optional) Note your user ID (e.g. `@bot:matrix.org`)
|
||
|
||
**Config:**
|
||
|
||
```toml
|
||
[[projects.platforms]]
|
||
type = "matrix"
|
||
|
||
[projects.platforms.options]
|
||
homeserver = "https://matrix.org"
|
||
access_token = "syt_xxx_xxx"
|
||
# user_id = "@bot:matrix.org" # optional, auto-detected
|
||
# allow_from = "*"
|
||
# auto_join = true # default true
|
||
# share_session_in_channel = false
|
||
# group_reply_all = false
|
||
# proxy = ""
|
||
```
|
||
|
||
**Detailed guide:** [docs/matrix.md](docs/matrix.md)
|
||
|
||
---
|
||
|
||
## Step 5: Run cc-connect
|
||
|
||
**Open the Web UI (recommended):**
|
||
|
||
```bash
|
||
cc-connect web # configure web admin & open browser (does NOT start cc-connect)
|
||
cc-connect # start the service
|
||
```
|
||
|
||
> **Note:** `cc-connect web` only configures the web admin and opens the dashboard in your browser — it does **not** start the cc-connect service itself. You still need to run `cc-connect` (or `cc-connect --config <path>`) separately to actually start the bridge. Think of it as two steps: configure first, then run.
|
||
|
||
**Important: If you are running inside a Claude Code session** (e.g., Claude Code helped you install and configure cc-connect), you must unset the `CLAUDECODE` environment variable before starting, otherwise Claude Code will refuse to launch as a subprocess:
|
||
|
||
```bash
|
||
unset CLAUDECODE && cc-connect
|
||
```
|
||
|
||
Alternatively, open a **separate terminal** and run cc-connect there — this avoids the issue entirely.
|
||
|
||
**Normal startup:**
|
||
|
||
```bash
|
||
# Run with config.toml in current directory
|
||
cc-connect
|
||
|
||
# Or specify config path
|
||
cc-connect -config /path/to/config.toml
|
||
|
||
# Check version
|
||
cc-connect --version
|
||
```
|
||
|
||
You should see logs like:
|
||
|
||
```
|
||
level=INFO msg="platform started" project=my-project platform=feishu
|
||
level=INFO msg="engine started" project=my-project agent=claudecode platforms=1
|
||
level=INFO msg="cc-connect is running" projects=1
|
||
```
|
||
|
||
## Step 6: Chat Commands
|
||
|
||
Once running, send messages to your bot on the configured platform. Available slash commands:
|
||
|
||
```
|
||
/new [name] — Start a new session
|
||
/list — List agent sessions
|
||
/switch <id> — Resume an existing session
|
||
/current — Show current active session
|
||
/history [n] — Show last n messages (default 10)
|
||
/reasoning [level] — View/switch reasoning effort (Codex)
|
||
/mode [name] — View/switch permission mode (default/edit/plan/yolo)
|
||
/quiet — Toggle thinking/tool progress messages
|
||
/allow <tool> — Pre-allow a tool (next session)
|
||
/provider [...] — Manage API providers (list/add/remove/switch)
|
||
/stop — Stop current execution
|
||
/help — Show available commands
|
||
```
|
||
|
||
During a session, Claude may ask for tool permissions. Reply:
|
||
- `allow` or `允许` — approve this request
|
||
- `deny` or `拒绝` — reject this request
|
||
- `allow all` or `允许所有` — auto-approve all remaining requests this session
|
||
|
||
## Step 7: Enable Natural Language Scheduling (Non-Claude-Code Agents)
|
||
|
||
cc-connect supports scheduled tasks (cron jobs). You can always create them via slash commands (`/cron add ...`) or CLI (`cc-connect cron add ...`), but to let the agent **understand natural language** like "every day at 6am, summarize trending repos", the agent needs to know about cc-connect's cron CLI.
|
||
|
||
**Claude Code** handles this automatically via `--append-system-prompt` — no extra setup needed.
|
||
|
||
**For Codex, Cursor Agent, Qoder CLI, Gemini CLI, OpenCode, or iFlow CLI**, add the following instructions to the agent's project-level instruction file in your project's `work_dir`:
|
||
|
||
| Agent | File to create/edit |
|
||
|-------|-------------------|
|
||
| Codex | `AGENTS.md` |
|
||
| Cursor Agent | `.cursorrules` |
|
||
| Qoder CLI | `AGENTS.md` |
|
||
| Gemini CLI | `GEMINI.md` |
|
||
| OpenCode | `OPENCODE.md` |
|
||
| iFlow CLI | `IFLOW.md` |
|
||
|
||
**Content to add** (copy-paste into the file):
|
||
|
||
```markdown
|
||
# cc-connect Integration
|
||
|
||
This project is managed via cc-connect, a bridge to messaging platforms.
|
||
|
||
## Scheduled tasks (cron)
|
||
When the user asks you to do something on a schedule (e.g. "every day at 6am",
|
||
"every Monday morning"), use the Bash/shell tool to run:
|
||
|
||
cc-connect cron add --cron "<min> <hour> <day> <month> <weekday>" --prompt "<task description>" --desc "<short label>"
|
||
|
||
Environment variables CC_PROJECT and CC_SESSION_KEY are already set — do NOT
|
||
specify --project or --session-key.
|
||
|
||
Examples:
|
||
cc-connect cron add --cron "0 6 * * *" --prompt "Collect GitHub trending repos and send a summary" --desc "Daily GitHub Trending"
|
||
cc-connect cron add --cron "0 9 * * 1" --prompt "Generate a weekly project status report" --desc "Weekly Report"
|
||
|
||
To list, run, edit, or delete cron jobs:
|
||
cc-connect cron list
|
||
cc-connect cron exec <job-id>
|
||
cc-connect cron edit <job-id> <field> <value>
|
||
cc-connect cron del <job-id>
|
||
|
||
Use `cron exec <job-id>` to run an existing scheduled task immediately; this is different from the `--exec <command>` flag used when creating a shell-command cron job.
|
||
Use `cron edit` to modify a single field instead of delete-and-recreate.
|
||
Common editable fields: cron_expr, prompt, exec, description, enabled (true/false), mute (true/false), timeout_mins (int).
|
||
Run `cc-connect cron edit --help` for the full field list.
|
||
|
||
Examples:
|
||
cc-connect cron exec abc123
|
||
cc-connect cron edit abc123 cron_expr "0 9 * * *"
|
||
cc-connect cron edit abc123 enabled false
|
||
cc-connect cron edit abc123 prompt "Updated daily summary task"
|
||
|
||
## Send message to current chat
|
||
To proactively send a message back to the user's chat session (use --stdin heredoc for long/multi-line messages):
|
||
|
||
cc-connect send --stdin <<'CCEOF'
|
||
your message here (any special characters are safe)
|
||
CCEOF
|
||
|
||
For short single-line messages:
|
||
|
||
cc-connect send -m "short message"
|
||
```
|
||
|
||
After adding this file, the agent will be able to translate natural language scheduling requests into `cc-connect cron add` commands automatically.
|
||
|
||
> **Tip:** You may want to add `AGENTS.md` / `.cursorrules` / `GEMINI.md` to your `.gitignore` if you don't want cc-connect instructions committed to version control.
|
||
|
||
## Multi-Project Setup
|
||
|
||
A single cc-connect process can manage multiple projects. Each project has its own agent, work directory, and platforms:
|
||
|
||
```toml
|
||
[[projects]]
|
||
name = "backend"
|
||
|
||
[projects.agent]
|
||
type = "claudecode"
|
||
|
||
[projects.agent.options]
|
||
work_dir = "/path/to/backend"
|
||
mode = "default"
|
||
|
||
[[projects.platforms]]
|
||
type = "feishu"
|
||
|
||
[projects.platforms.options]
|
||
app_id = "cli_xxx"
|
||
app_secret = "xxx"
|
||
|
||
# Second project — using Codex
|
||
[[projects]]
|
||
name = "frontend"
|
||
|
||
[projects.agent]
|
||
type = "codex"
|
||
|
||
[projects.agent.options]
|
||
work_dir = "/path/to/frontend"
|
||
mode = "full-auto"
|
||
|
||
[[projects.platforms]]
|
||
type = "telegram"
|
||
|
||
[projects.platforms.options]
|
||
token = "xxx"
|
||
|
||
# Third project — using Cursor Agent
|
||
[[projects]]
|
||
name = "design-system"
|
||
|
||
[projects.agent]
|
||
type = "cursor"
|
||
|
||
[projects.agent.options]
|
||
work_dir = "/path/to/design-system"
|
||
mode = "force"
|
||
|
||
[[projects.platforms]]
|
||
type = "discord"
|
||
|
||
[projects.platforms.options]
|
||
token = "xxx"
|
||
|
||
# Fourth project — using Gemini CLI
|
||
[[projects]]
|
||
name = "my-gemini-project"
|
||
|
||
[projects.agent]
|
||
type = "gemini"
|
||
|
||
[projects.agent.options]
|
||
work_dir = "/path/to/gemini-project"
|
||
mode = "yolo" # "default" | "auto_edit" | "yolo" | "plan"
|
||
|
||
[[projects.platforms]]
|
||
type = "slack"
|
||
|
||
[projects.platforms.options]
|
||
bot_token = "xoxb-xxx"
|
||
app_token = "xapp-xxx"
|
||
|
||
# Fifth project — using Qoder CLI
|
||
[[projects]]
|
||
name = "my-qoder-project"
|
||
|
||
[projects.agent]
|
||
type = "qoder"
|
||
|
||
[projects.agent.options]
|
||
work_dir = "/path/to/qoder-project"
|
||
mode = "default" # "default" | "yolo"
|
||
# model = "auto" # "auto" | "ultimate" | "performance" | "efficient" | "lite"
|
||
|
||
[[projects.platforms]]
|
||
type = "telegram"
|
||
|
||
[projects.platforms.options]
|
||
token = "xxx"
|
||
|
||
# Sixth project — using iFlow CLI
|
||
[[projects]]
|
||
name = "my-iflow-project"
|
||
|
||
[projects.agent]
|
||
type = "iflow"
|
||
|
||
[projects.agent.options]
|
||
work_dir = "/path/to/iflow-project"
|
||
mode = "default" # "default" | "auto-edit" | "plan" | "yolo"
|
||
# model = "Qwen3-Coder"
|
||
|
||
[[projects.platforms]]
|
||
type = "slack"
|
||
|
||
[projects.platforms.options]
|
||
bot_token = "xoxb-xxx"
|
||
app_token = "xapp-xxx"
|
||
```
|
||
|
||
## Upgrade
|
||
|
||
### Check current version
|
||
|
||
```bash
|
||
cc-connect --version
|
||
```
|
||
|
||
### npm users
|
||
|
||
```bash
|
||
npm update -g cc-connect
|
||
```
|
||
|
||
### Binary users
|
||
|
||
Check the latest release at https://github.com/chenhg5/cc-connect/releases and compare with your local version. To upgrade:
|
||
|
||
```bash
|
||
# Linux/macOS — replace with your platform suffix
|
||
curl -L -o /usr/local/bin/cc-connect https://github.com/chenhg5/cc-connect/releases/latest/download/cc-connect-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/')
|
||
chmod +x /usr/local/bin/cc-connect
|
||
```
|
||
|
||
### Source users
|
||
|
||
```bash
|
||
cd cc-connect
|
||
git pull
|
||
make build
|
||
```
|
||
|
||
After upgrading, restart the running cc-connect process.
|
||
|
||
## Step 8: Run as Background Service (Optional)
|
||
|
||
You can run cc-connect as a daemon managed by the OS init system (Linux systemd user service, macOS launchd LaunchAgent, Windows Task Scheduler task).
|
||
|
||
### Install the daemon
|
||
|
||
```bash
|
||
cc-connect daemon install --config ~/.cc-connect/config.toml
|
||
```
|
||
|
||
You can also point the daemon at the directory that contains `config.toml`:
|
||
|
||
```bash
|
||
cc-connect daemon install --work-dir ~/.cc-connect
|
||
```
|
||
|
||
Optional flags: `--config PATH`, `--log-file PATH`, `--log-max-size N` (MB), `--work-dir DIR`, `--force` (overwrite existing unit). `--config` points to a config file, while `--work-dir` points to the directory containing `config.toml`.
|
||
|
||
### Linux systemd: Keep service running after SSH disconnect
|
||
|
||
When installed as a user-level systemd service (non-root), cc-connect runs under `user@UID.service`. By default, systemd stops this service when your last login session ends (e.g., SSH disconnect). This is controlled by the "linger" setting.
|
||
|
||
To keep cc-connect running persistently, enable linger for your user:
|
||
|
||
```bash
|
||
sudo loginctl enable-linger $USER
|
||
```
|
||
|
||
After enabling linger, `user@UID.service` remains active even when you log out. The daemon install command will warn you if linger is not enabled.
|
||
|
||
Alternatively, you can install as a system-level service (requires root):
|
||
|
||
```bash
|
||
sudo cc-connect daemon install --config ~/.cc-connect/config.toml
|
||
```
|
||
|
||
System-level services are independent of login sessions.
|
||
|
||
### Control the service
|
||
|
||
```bash
|
||
cc-connect daemon start
|
||
cc-connect daemon stop
|
||
cc-connect daemon restart
|
||
cc-connect daemon status
|
||
```
|
||
|
||
### View logs
|
||
|
||
```bash
|
||
cc-connect daemon logs # tail current log
|
||
cc-connect daemon logs -f # follow (like tail -f)
|
||
cc-connect daemon logs -n 100 # last 100 lines
|
||
cc-connect daemon logs --log-file /path/to/log # custom log file
|
||
```
|
||
|
||
Logs auto-rotate at the configured max size and keep one backup.
|
||
|
||
On Windows, `daemon install` creates a native Task Scheduler task named `cc-connect`.
|
||
The task runs at user logon and is also started immediately after installation. The
|
||
installer writes a small PowerShell launcher under `~/.cc-connect` so the scheduled
|
||
task uses the selected config directory, log file, PATH, and proxy environment.
|
||
|
||
### Uninstall
|
||
|
||
```bash
|
||
cc-connect daemon uninstall
|
||
```
|
||
|
||
## Additional Features
|
||
|
||
The following additional features are available:
|
||
|
||
- **Codex Agent**: OpenAI Codex CLI integration (`codex exec --json`)
|
||
- **Cursor Agent**: Cursor Agent CLI integration (`agent --print --output-format stream-json`)
|
||
- **Gemini CLI**: Google Gemini CLI integration (`gemini -p --output-format stream-json`)
|
||
- **Qoder CLI**: Qoder CLI integration (`qodercli -p -f stream-json`)
|
||
- **OpenCode**: OpenCode CLI integration (`opencode run --format json`)
|
||
- **iFlow CLI**: iFlow CLI integration (`iflow -i -r -o`)
|
||
- **Voice Messages (STT)**: Speech-to-text via Whisper API (OpenAI / Groq / SiliconFlow). Requires `ffmpeg` and `[speech]` config.
|
||
- **Voice Reply (TTS)**: Text-to-speech via Qwen / OpenAI / MiniMax / MiMo / local providers. Requires `ffmpeg` and `[tts]` config.
|
||
- **Image Messages**: Send images to Claude Code for multimodal analysis
|
||
- **API Provider Management**: Runtime switching between API providers via `/provider` command or CLI
|
||
- **CLI Send**: `cc-connect send` to inject messages into active sessions from external processes
|
||
|
||
## Troubleshooting
|
||
|
||
- **"session already in use"** — A previous Claude Code process may still be running. Use `/new` to start a fresh session.
|
||
- **No response from bot** — Check `cc-connect` logs. Set `level = "debug"` in `[log]` for verbose output.
|
||
- **WeChat Work can't send messages** — Ensure your outbound IP is in the Trusted IP whitelist. If using a proxy, check the proxy is reachable.
|
||
- **LINE/WeChat Work can't receive messages** — Ensure your webhook URL is publicly accessible (ngrok/cloudflared running).
|
||
- **macOS binary won't open** — Run `xattr -d com.apple.quarantine cc-connect` to remove quarantine flag.
|