Skip to main content

Bridge Claude Code sessions to Slack channels

Project description

summon-claude

Bridge Claude Code sessions to Slack channels. Run summon start in a terminal, authenticate from Slack, and interact with Claude entirely through a dedicated Slack channel.

Installation

The package is summon-claude on PyPI; once installed, the CLI command is summon.

Option A: uv tool (Recommended)

uv tool install summon-claude

Option B: pipx

pipx install summon-claude

Option C: Homebrew (macOS/Linux)

brew install wgordon17/summon/summon-claude

Keeping up to date

summon checks for new versions on summon start and notifies you when an update is available.

To upgrade to the latest version:

Installation method Upgrade command
uv tool uv tool upgrade summon-claude
pipx pipx upgrade summon-claude
Homebrew brew upgrade summon-claude

To disable update checks, set the environment variable:

export SUMMON_NO_UPDATE_CHECK=1

Quick Start

# 1. Set up your Slack app (see Slack App Setup below)

# 2. Run the interactive setup wizard
summon init

# 3. Start a session
summon start

Slack App Setup

Import the manifest (recommended)

  1. Go to api.slack.com/apps
  2. Click Create New AppFrom an app manifest
  3. Select your workspace
  4. Paste the contents of slack-app-manifest.yaml
  5. Click Create, then Install to Workspace

Collect your tokens

Token Where to find it
Bot Token (xoxb-...) OAuth & Permissions → Bot User OAuth Token
App Token (xapp-...) SettingsBasic Information → App-Level Tokens → Generate one with connections:write scope
Signing Secret SettingsBasic Information → App Credentials

Auth Flow

  1. Run summon start in your terminal
  2. The terminal prints:
    ==================================================
      SUMMON CODE: ABC123
      Type in Slack: /summon ABC123
      Expires in 5 minutes
    ==================================================
    
  3. In Slack, type /summon ABC123
  4. The bot verifies the code, creates a session channel, and posts a header
  5. All further interaction happens in that Slack channel

The code expires in 5 minutes. Run summon start again to get a new one.

Commands

Command Description
summon --version Show CLI version
summon version Show version and environment info (Python, platform, paths)
summon init Interactive setup wizard — creates config file with your tokens
summon start Start a new session (prints auth code, waits for /summon in Slack)
summon session list Show active sessions (use --all for all recent)
summon session info SESSION_ID Show detailed view of one session
summon session stop SESSION_ID Send SIGTERM to a running session
summon session logs [SESSION_ID] View session logs (list files, or tail a specific session)
summon session cleanup Mark sessions with dead processes as errored
summon config show Show current config file (tokens masked)
summon config set KEY VALUE Set a single config value
summon config path Print the config file path
summon config edit Open config file in $EDITOR
summon config check Validate config file (keys, token format, DB writability, Slack API connectivity)

Alias: summon s is shorthand for summon session (e.g., summon s list).

summon start flags

Flag Description
--cwd PATH Working directory for Claude (default: current directory)
--name NAME Session name used for Slack channel naming
--model MODEL Override the default Claude model
--resume SESSION_ID Resume an existing Claude Code session by ID
-b, --background Run session in background as daemon (logs accessible via summon session logs)

Global flags

Flag Description
-h, --help Show help message and exit
--version Show version and exit
-v, --verbose Enable verbose logging
-q, --quiet Suppress non-essential output (mutually exclusive with --verbose)
--no-color Disable colored output (respects NO_COLOR environment variable)
--config PATH Override config file location (default: XDG-aware path)

-o, --output {json|table} is available on version, session list, and session info (default: table).

In-Session Commands

Once a session is active in Slack, type !-prefixed commands to control the session without reaching Claude:

Command Description
!help Show all available commands
!status Show session status (model, turns, cost, uptime)
!end End the current session
!model Show the active model
!model <name> Switch model (takes effect on next session start)

Aliases: !quit, !exit, and !logout all map to !end.

Passthrough commands: Claude SDK slash commands (e.g., /compact, /clear) are also available as !compact, !clear, etc. — they are forwarded to the SDK as their / equivalents.

Blocked commands: !login is blocked in Slack sessions.

Use !help in a session to see the full list, including any passthrough commands discovered from the SDK.

Configuration

Config is loaded in priority order: environment variables → config file → local .env.

Config file path (XDG-aware)

$XDG_CONFIG_HOME/summon/config.env   # if XDG_CONFIG_HOME is set
~/.config/summon/config.env          # default on most systems
~/.summon/config.env                 # fallback if ~/.config doesn't exist

Use summon config path to see which path is active. Use summon init to create the file interactively.

Required variables

Variable Description
SUMMON_SLACK_BOT_TOKEN Bot token (xoxb-...) from OAuth & Permissions
SUMMON_SLACK_APP_TOKEN App-level token (xapp-...) for Socket Mode
SUMMON_SLACK_SIGNING_SECRET Signing secret from Basic Information

Optional variables

Variable Default Description
SUMMON_DEFAULT_MODEL (SDK default) Default Claude model
SUMMON_CHANNEL_PREFIX summon Prefix for created session channels
SUMMON_PERMISSION_DEBOUNCE_MS 500 Debounce window for batching permission requests (ms)
SUMMON_MAX_INLINE_CHARS 2500 Threshold for inline vs file upload display
SUMMON_NO_UPDATE_CHECK (unset) Set to 1 to disable update notifications on summon start

A local .env in the project directory overrides the config file.

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                          Slack                                  │
│  (channels, messages, files, interactive buttons, slash cmd)    │
└──────────────────────────┬──────────────────────────────────────┘
                           │ Socket Mode
                           ▼
┌─────────────────────────────────────────────────────────────────┐
│                    SummonSession (Orchestrator)                  │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │ Claude SDK  │  Slack Bolt  │  Auth  │  Permissions       │   │
│  └──────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────┘
           │                               │
           ▼                               ▼
┌──────────────────────┐      ┌──────────────────────┐
│   Claude SDK         │      │   ChatProvider       │
│   (streaming)        │      │   (Slack adapter)    │
└──────────────────────┘      └──────────────────────┘

Threading Model

Messages are organized into threads to keep the main channel clean:

  • Main channel: Opens with the initial prompt and closes with Claude's final conclusion
  • Turn threads: Each Claude turn's tool calls post to a dedicated turn thread with a summary like "🔧 Turn 3: 5 tool calls · session.py, config.py"
  • Subagent threads: When Claude spawns subagents, their activity posts to dedicated subagent threads
  • Permissions: Permission requests broadcast to all threads with <!channel> notifications

This structure keeps the main conversation readable while preserving full context in threads.

Provider Abstraction

All Slack API calls go through a ChatProvider protocol, enabling future support for Discord, Teams, or CLI providers without changing core routing logic. The SlackChatProvider implements this protocol for Slack.

Modules

Module Purpose
cli.py CLI entry point: global flags (--version, --quiet, --no-color, --config), subcommands
cli_config.py Config subcommand handlers: show, path, edit, set, check
config.py pydantic-settings config with XDG path resolution and plugin discovery
auth.py 8-char hex short codes with 5-min TTL, brute-force protection (5 attempts)
registry.py SQLite session registry with WAL mode, heartbeat, audit log
channel_manager.py Slack channel create/archive/header with collision handling
permissions.py Debounced permission batching with Slack interactive buttons
content_display.py Hybrid inline/file upload display with diff formatting
streamer.py Claude response streaming to Slack with threaded routing
thread_router.py Routes content to main channel, turn threads, and subagent threads
commands.py !-prefixed command dispatch: local handlers, passthrough, blocking, aliasing
session.py Core orchestrator: ties all modules together
mcp_tools.py In-process MCP server: slack_upload_file, slack_create_thread, slack_react, slack_post_snippet
providers/base.py ChatProvider protocol and message/channel abstractions
providers/slack.py SlackChatProvider implementation for Slack API calls
rate_limiter.py Per-key cooldown rate limiter for slash command spam protection
update_check.py PyPI update checker with 24h cache, shown on summon start
_formatting.py Slack mrkdwn formatting helpers and tool argument extraction

Security

Authentication

  1. summon start generates a short code (8 hex characters)
  2. Short code is printed to the terminal only — it is never sent to Slack automatically
  3. You type /summon <code> in Slack; the bot verifies the code against the registry
  4. Code expires after 5 minutes; locked after 5 failed attempts
  5. /summon has a 2-second per-user rate limit

Permission handling

  • Auto-approved tools: Read, Grep, Glob, WebSearch, WebFetch, LSP, and other read-only operations
  • User-approved tools: Write, Edit, Bash, and other destructive operations
  • Approval requests are debounced (default 500ms) and batched into a single Slack message
  • Timeout: 5 minutes — unanswered permission requests are denied automatically

Audit logging

All session events (session_created, auth_attempted, auth_succeeded, auth_failed, session_active, session_ended, session_errored, session_stopped) are written to the SQLite registry for audit purposes.

Development

make install            # uv sync + install git hooks
make lint               # ruff check + format (auto-fix)
make test               # pytest with asyncio
make build              # build sdist and wheel
make clean              # remove build artifacts and cache
make all                # install → lint → test
make py-typecheck       # pyright type checking
make py-test-quick      # fast tests (exclude slow, fail-fast)
make repo-hooks-install # install prek pre-commit hooks
make repo-hooks-clean   # remove hooks and cache

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

summon_claude-0.1.1.tar.gz (200.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

summon_claude-0.1.1-py3-none-any.whl (64.0 kB view details)

Uploaded Python 3

File details

Details for the file summon_claude-0.1.1.tar.gz.

File metadata

  • Download URL: summon_claude-0.1.1.tar.gz
  • Upload date:
  • Size: 200.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for summon_claude-0.1.1.tar.gz
Algorithm Hash digest
SHA256 f90aefcfe2759dc812242909ce7e020ef491bcae23c21d5950f1354a151671bb
MD5 c00002960419042d24c73e558e84c1f3
BLAKE2b-256 41f4700fbc7dee218c992bce34c6c1598a50c87dcc4ade0301447f18fa2891e9

See more details on using hashes here.

Provenance

The following attestation bundles were made for summon_claude-0.1.1.tar.gz:

Publisher: publish.yaml on wgordon17/summon-claude

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file summon_claude-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: summon_claude-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 64.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for summon_claude-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e67f8a9a9f4abf040195656c0a091da9e3f182a5b3b5de56eede801250ceba83
MD5 c3a0860ecfd2f5430ebc53364e79dbcc
BLAKE2b-256 9a47cfdfff9ceded574f2e96c5a94a1cf492efd0dc256ee17351b82e9ef30bc1

See more details on using hashes here.

Provenance

The following attestation bundles were made for summon_claude-0.1.1-py3-none-any.whl:

Publisher: publish.yaml on wgordon17/summon-claude

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page