v0.1.12 · Local-first · MIT

Group chat 「Local Agent」 Whole project

Mention @cc-bot in Slack — Claude Code runs on your laptop, reads the intent, writes the diff itself or dispatches to a specialist. Code, tokens, and shell never leave the machine.

00 — In your workspace

Where cc-bot earns its keep.

Six channels, six jobs. Ask in chat, get an answer, keep working.

  1. #bugs

    PM drops a screenshot, cc-bot opens a PR.

    Maya pastes a 500 screenshot into #bugs.

    Bot reads the image, greps the repo, finds a stale migration, opens the PR, replies with the diff.

    Why it wins: screenshot, fix, PR — one thread.

  2. #deploys

    Solo dev ships from the channel.

    You type "ship to prod" into #deploys.

    deploy_prod is admin-confirm — bot waits for "yes", deploys, posts the version tag.

    Why it wins: no SSH, no dashboard, full audit trail.

  3. #product

    Status without pinging the team.

    PM asks "where are we on Feature X?" in #product.

    Bot reads the progress doc, cross-refs recent commits, posts a tidy bullet list.

    Why it wins: engineer keeps flow, PM gets the answer in 20s.

  4. #standup

    Standup that writes itself.

    At 09:30 a prompt drops in #standup.

    Bot diffs 24h of git log, posts three lines per repo with authors linked.

    Why it wins: happens whether or not humans show up.

  5. #ops-alerts

    On-call gets a triage, not just an alert.

    Datadog fires a latency alert at 02:14.

    Bot queries logs via MCP, threads a probable cause: "p95 spike correlates with the new orders reindex."

    Why it wins: on-call wakes to a starting point, not a mystery.

  6. #ship-room

    Three devs, three agents — same channel, no clash.

    Lin asks for a rate-limit PR, Maya wants a hero image regen, Kai ships docs to staging — all in #ship-room within a minute.

    Each request spawns its own Claude Code session under the slot scheduler. Lin's session writes the PR. Maya's dispatches to Nano Banana for the image. Kai's runs the deploy script. HUD lights three lanes side by side.

    Why it wins: one project, many hands, zero conflict.

01 — On your machine

Your laptop is the agent.

Slack-native, fully local. cc-bot binds your shell to your IM — every command runs on your own hardware with your own credentials, then writes back to the chat.

  1. Yours, end-to-end.

    Code, tokens, SSH keys, git remotes — nothing leaves the machine. The IM platform sees the command you typed; everything else stays on disk.

  2. Anything you can type, the bot can type.

    File system, installed CLIs, the VPN-only Jenkins box, the private mirror behind the firewall. If your terminal reaches it, cc-bot reaches it.

  3. Built for the codebases SaaS forgot.

    Pre-2020 monorepos, SSH-only build boxes, internal Gerrit, the legacy PHP repo nobody wants to touch. SaaS agents need a clean GitHub repo; cc-bot doesn't.

02 — Capabilities

Seven muscles, one bot.

  1. 01

    Slack-native, IM-agnostic

    Socket Mode push — no public webhook, works behind firewalls. The same IMAdapter powers Lark. The next adapter is one file.

    • Slack
    • Lark
    • Socket Mode
  2. 02

    Defensive delivery

    Socket Mode push, dedupe ledger, main-busy queue. Every message delivered exactly once — even when your terminal is mid-edit.

    • Socket Mode
    • dedupe ledger
    • main-busy queue
  3. 03

    Multi-session scheduling

    Slots and tags turn parallel Claude Code sessions into a polite queue. Conflicts resolved by config, not chance.

    • slot
    • tag
    • conflict matrix
  4. 04

    HUD status broadcast

    The statusline goes live: which agents are busy, which slots are free, last thread. Terminal and Slack agree.

    • statusline
    • real-time
    • shared state
  5. 05

    Three-tier permission matrix

    Public reads, admin-auto writes, admin-confirm for the scary ones. Tag the intent once; the bot enforces it forever.

    • public
    • admin-auto
    • admin-confirm
  6. 06

    Main-window priority

    A UserPromptSubmit hook lets the dev at the keyboard preempt any background task. Focused — bot waits. Away — it works.

    • hook
    • preempt
    • focus-aware
  7. 07

    Claude Code at the helm

    Claude Code is the main brain. It reads every intent and either writes the work itself (diffs, PRs) or dispatches to a specialist: Gemini for UI, Nano Banana for design, Seedance for video, DeepSeek for heavy reasoning. Results stitch back into the thread.

    • Claude
    • Gemini
    • Nano Banana
    • Seedance
    • DeepSeek

03 — Engineering note

One IMAdapter, many group chats.

adapters/base.js defines the contract. Each IM is one file that fulfils it. Slack and Lark ship today; Discord or Teams is a weekend.

Runtime reads profile.im.type, instantiates the adapter, and the rest of the pipeline never knows which IM it's talking to.

// adapters/base.js — the contract every IM implements
class IMAdapter {
  listRecentMessages(chat_id, since_ts) { }
  sendText(chat_id, text)             { }
  sendImage(chat_id, file_path)       { }
  downloadResource(file_id, out_path) { }
  getUser(user_id)                    { }
}

// runtime/poll.js — IM is a config field
const adapter = loadAdapter(profile.im.type)
// → 'slack' loads adapters/slack.js
// → 'lark'  loads adapters/lark.js

04 — Architecture

A small idea, drawn carefully.

A thin pipeline. Events in via Socket Mode (Lark polls HTTP). Dedupe ledger guarantees exactly-once. Scheduler hands the message to Claude Code under the right permission tier; Claude Code answers itself or dispatches to a specialist (Gemini · Nano Banana · Seedance · DeepSeek) as the intent demands. Result flows back to channel and HUD together.

IM Layer Slack Lark IMAdapter channels · threads Delivery Socket Mode push short-poll fallback dedupe ledger exactly-once delivery Scheduler slot · tag conflict matrix main-window hook permission tier check public / admin-auto / admin-confirm Output Claude Code session channel reply HUD broadcast terminal + Slack agree return: status + result
Events flow left → right; status returns along the dotted path. Slack uses Socket Mode; Lark falls back to HTTP polling.

Permission matrix

Tier
Who can call
Confirmation
Typical intent
public
any channel member
none
status · tail logs
admin-auto
admin_open_ids (Lark) / admin_user_ids (Slack)
none
compile_preview · run_tests
admin-confirm
admin_open_ids (Lark) / admin_user_ids (Slack)
reply yes
deploy_prod · db_migrate

05 — Slack setup

Four steps to a chat-driven repo.

/cc-bot:setup runs the whole flow inside Claude Code — idempotent, version-aware, auto-detects what it can.

  1. 01

    Install the cc-bot plugin

    # inside Claude Code
    /plugin marketplace add WaterTian/cc-bot
    /plugin install cc-bot@cc-bot

    Then run /cc-bot:setup in any project. When asked "which IM?", pick Slack.

  2. 02

    Create the Slack app from the manifest

    Open api.slack.com/appsCreate New AppFrom a manifest. Paste the YAML below.

    # templates/slack-manifest.yaml — bot scopes & Socket Mode
    display_information:
      name: cc-bot
      description: Claude Code-powered group project assistant
      background_color: "#1f3a2a"
    
    features:
      bot_user:
        display_name: cc-bot
        always_online: true
    
    oauth_config:
      scopes:
        bot:
          - app_mentions:read   # listen for @cc-bot
          - channels:history    # read public channels
          - channels:read
          - chat:write          # post messages
          - files:read          # download images
          - files:write
          - groups:history      # private channels
          - groups:read
          - users:read
    
    settings:
      event_subscriptions:
        bot_events:
          - message.channels
          - message.groups
          - app_mention
      interactivity:
        is_enabled: false
      org_deploy_enabled: false
      socket_mode_enabled: true  # no public webhook needed
      token_rotation_enabled: false
  3. 03

    Generate the two tokens

    In the new app's Basic Information page:

    • App-Level Token — name it cc-bot-socket, scope connections:write. Copy the xapp-1-… value.
    • Install to Workspace → Allow. Copy the Bot User OAuth Token (xoxb-…).

    Paste both when /cc-bot:setup prompts. cc-bot verifies via auth.test and writes them into .cc-bot/profiles/active.json.

  4. 04

    Invite cc-bot to a channel

    Paste the channel ID. In Slack, run /invite @cc-bot — bot sends a probe. Then bring it online:

    /cc-bot:start

    An "online" message lands in your channel. From here, talk to it like a teammate.

Slash commands

  • /cc-bot:setupinteractive Slack / Lark onboarding
  • /cc-bot:startbring the bot online
  • /cc-bot:stoptake it offline
  • /cc-bot:new-profile <name>clone the profile template
  • /cc-bot:switch <name>swap active profile
  • /cc-bot:doctorhealth check & diagnostics

Ship from where the team already talks.

MIT, runtime-free, on GitHub. Slack & Lark adapters both live on main.