Files
chenhg5-cc-connect/INSTALL.md
Wupei 6f8d3a2bd8 feat(matrix): add Matrix platform adapter with E2EE support (#834)
* 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>
2026-06-16 09:54:55 +08:00

26 KiB
Raw Permalink Blame History

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

npm install -g cc-connect

After installation, the cc-connect binary will be available globally.

Option B: Homebrew (macOS / Linux)

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)
# 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:

xattr -d com.apple.quarantine cc-connect

Option D: Build from source

Requires Go 1.22+.

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:

# 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:

Verify your selected agent works:

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:

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:

cp config.example.toml config.toml

The configuration has this structure:

# 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):

# 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:

[[projects.platforms]]
type = "feishu"

[projects.platforms.options]
app_id = "cli_xxxxxxxxxxxx"
app_secret = "xxxxxxxxxxxxxxxxxxxxxxxx"

Detailed guide: 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:

[[projects.platforms]]
type = "dingtalk"

[projects.platforms.options]
client_id = "dingxxxxxxxxxxxxxxxxx"
client_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Detailed guide: 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:

[[projects.platforms]]
type = "telegram"

[projects.platforms.options]
token = "1234567890:ABCdefGHIjklMNOpqrsTUVwxyz"

Detailed guide: 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:

[[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


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:

[[projects.platforms]]
type = "discord"

[projects.platforms.options]
token = "your-discord-bot-token"

Detailed guide: 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:

[[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:

[[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

Personal WeChat uses Tencents 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:

    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

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):
    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:
[[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


Matrix — No public IP needed

Connection: Long Polling via /sync

Setup steps:

  1. Create an account on a Matrix homeserver (e.g. matrix.org, or your own self-hosted server)
  2. Get an access token:
    • Open Element (or your preferred Matrix client)
    • Go to SettingsHelp & AboutAdvanced → 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:

[[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


Step 5: Run cc-connect

Open the Web UI (recommended):

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:

unset CLAUDECODE && cc-connect

Alternatively, open a separate terminal and run cc-connect there — this avoids the issue entirely.

Normal startup:

# 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):

# 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:

[[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

cc-connect --version

npm users

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:

# 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

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

cc-connect daemon install --config ~/.cc-connect/config.toml

You can also point the daemon at the directory that contains config.toml:

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:

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):

sudo cc-connect daemon install --config ~/.cc-connect/config.toml

System-level services are independent of login sessions.

Control the service

cc-connect daemon start
cc-connect daemon stop
cc-connect daemon restart
cc-connect daemon status

View logs

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

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.