Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"name": "chorus",
"source": "./public/chorus-plugin",
"description": "Chorus AI-DLC collaboration platform plugin. Automates session lifecycle, provides MCP tools for PM/Developer/Admin workflows, and enables multi-agent team observability.",
"version": "0.5.2",
"version": "0.6.0",
"category": "project-management",
"tags": ["ai-dlc", "collaboration", "mcp", "session", "multi-agent"]
}
Expand Down
19 changes: 17 additions & 2 deletions public/chorus-plugin/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "chorus",
"description": "Chorus AI-DLC collaboration platform plugin for Claude Code. Automates session lifecycle, provides MCP tools for PM/Developer/Admin workflows, and enables multi-agent team observability.",
"version": "0.5.2",
"version": "0.6.0",
"author": {
"name": "Chorus-AIDLC"
},
Expand All @@ -16,5 +16,20 @@
"session",
"multi-agent",
"collaboration"
]
],
"userConfig": {
"CHORUS_URL": {
"type": "string",
"title": "Chorus Server URL",
"description": "Your Chorus instance URL (e.g., https://chorus.example.com). Get this from your Chorus admin.",
"required": true
},
"CHORUS_API_KEY": {
"type": "string",
"title": "Chorus API Key",
"description": "Agent API key starting with cho_ (get it from Chorus Settings > API Keys)",
"required": true,
"sensitive": true
}
}
}
4 changes: 2 additions & 2 deletions public/chorus-plugin/.mcp.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"mcpServers": {
"chorus": {
"type": "http",
"url": "${CHORUS_URL}/api/mcp",
"url": "${user_config.CHORUS_URL}/api/mcp",
"headers": {
"Authorization": "Bearer ${CHORUS_API_KEY}"
"Authorization": "Bearer ${user_config.CHORUS_API_KEY}"
}
}
}
Expand Down
23 changes: 18 additions & 5 deletions public/chorus-plugin/bin/chorus-api.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@
# chorus-api.sh — Lightweight REST API wrapper for Chorus session management
# Used by hook scripts to communicate with Chorus backend.
#
# Environment variables:
# Environment variables (either source works, env vars take priority):
# CHORUS_URL — Chorus base URL (e.g., http://localhost:3000)
# CHORUS_API_KEY — Agent API key (cho_xxx)
# Or via Claude Code plugin userConfig (auto-injected as CLAUDE_PLUGIN_OPTION_*):
# CLAUDE_PLUGIN_OPTION_CHORUS_URL
# CLAUDE_PLUGIN_OPTION_CHORUS_API_KEY
#
# State file: $CLAUDE_PROJECT_DIR/.chorus/state.json (gitignored)

set -euo pipefail

# ===== Configuration =====

CHORUS_URL="${CHORUS_URL:-}"
CHORUS_API_KEY="${CHORUS_API_KEY:-}"
# Resolve config: env var > userConfig (CLAUDE_PLUGIN_OPTION_*) > empty
CHORUS_URL="${CHORUS_URL:-${CLAUDE_PLUGIN_OPTION_CHORUS_URL:-}}"
CHORUS_API_KEY="${CHORUS_API_KEY:-${CLAUDE_PLUGIN_OPTION_CHORUS_API_KEY:-}}"
STATE_DIR="${CLAUDE_PROJECT_DIR:-.}/.chorus"
STATE_FILE="${STATE_DIR}/state.json"

Expand All @@ -25,8 +29,16 @@ die() {
}

require_env() {
[ -n "$CHORUS_URL" ] || die "CHORUS_URL is not set"
[ -n "$CHORUS_API_KEY" ] || die "CHORUS_API_KEY is not set"
[ -n "$CHORUS_URL" ] || die "CHORUS_URL is not set. Run /plugin to configure Chorus, or export CHORUS_URL."
[ -n "$CHORUS_API_KEY" ] || die "CHORUS_API_KEY is not set. Run /plugin to configure Chorus, or export CHORUS_API_KEY."
}

# Resolve configuration from env vars or userConfig.
# Callable as subcommand: chorus-api.sh resolve-config
# Outputs shell assignments that can be eval'd by hook scripts.
chorus_resolve_config() {
echo "CHORUS_URL=\"${CHORUS_URL}\""
echo "CHORUS_API_KEY=\"${CHORUS_API_KEY}\""
}

# Make an authenticated API request to Chorus
Expand Down Expand Up @@ -341,6 +353,7 @@ cmd="${1:-}"
shift || true

case "$cmd" in
resolve-config) chorus_resolve_config ;;
checkin) cmd_checkin "$@" ;;
mcp-tool) cmd_mcp_tool "$@" ;;
state-get) state_get "${1:-}" ;;
Expand Down
4 changes: 3 additions & 1 deletion public/chorus-plugin/bin/on-pre-enter-plan.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

set -euo pipefail

[ -z "${CHORUS_URL:-}" ] && exit 0
# Resolve config: env var > userConfig (CLAUDE_PLUGIN_OPTION_*)
CHORUS_URL="${CHORUS_URL:-${CLAUDE_PLUGIN_OPTION_CHORUS_URL:-}}"
[ -z "$CHORUS_URL" ] && exit 0

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
API="${SCRIPT_DIR}/chorus-api.sh"
Expand Down
4 changes: 3 additions & 1 deletion public/chorus-plugin/bin/on-pre-exit-plan.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

set -euo pipefail

[ -z "${CHORUS_URL:-}" ] && exit 0
# Resolve config: env var > userConfig (CLAUDE_PLUGIN_OPTION_*)
CHORUS_URL="${CHORUS_URL:-${CLAUDE_PLUGIN_OPTION_CHORUS_URL:-}}"
[ -z "$CHORUS_URL" ] && exit 0

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
API="${SCRIPT_DIR}/chorus-api.sh"
Expand Down
4 changes: 3 additions & 1 deletion public/chorus-plugin/bin/on-pre-spawn-agent.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

set -euo pipefail

[ -z "${CHORUS_URL:-}" ] && exit 0
# Resolve config: env var > userConfig (CLAUDE_PLUGIN_OPTION_*)
CHORUS_URL="${CHORUS_URL:-${CLAUDE_PLUGIN_OPTION_CHORUS_URL:-}}"
[ -z "$CHORUS_URL" ] && exit 0

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
API="${SCRIPT_DIR}/chorus-api.sh"
Expand Down
10 changes: 7 additions & 3 deletions public/chorus-plugin/bin/on-session-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@ if [ ! -t 0 ]; then
EVENT=$(cat)
fi

# Resolve config: env var > userConfig (CLAUDE_PLUGIN_OPTION_*)
CHORUS_URL="${CHORUS_URL:-${CLAUDE_PLUGIN_OPTION_CHORUS_URL:-}}"
CHORUS_API_KEY="${CHORUS_API_KEY:-${CLAUDE_PLUGIN_OPTION_CHORUS_API_KEY:-}}"

# Check if Chorus environment is configured
if [ -z "${CHORUS_URL:-}" ] || [ -z "${CHORUS_API_KEY:-}" ]; then
if [ -z "$CHORUS_URL" ] || [ -z "$CHORUS_API_KEY" ]; then
"$API" hook-output \
"Chorus plugin: not configured (set CHORUS_URL and CHORUS_API_KEY)" \
"Chorus environment not configured. Set CHORUS_URL and CHORUS_API_KEY to enable Chorus integration." \
"Chorus plugin: not configured. Run /plugin to set up, or export CHORUS_URL and CHORUS_API_KEY." \
"Chorus not configured. Run /plugin to configure Chorus, or set CHORUS_URL and CHORUS_API_KEY env vars." \
"SessionStart"
exit 0
fi
Expand Down
6 changes: 5 additions & 1 deletion public/chorus-plugin/bin/on-subagent-start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
API="${SCRIPT_DIR}/chorus-api.sh"

# Resolve config: env var > userConfig (CLAUDE_PLUGIN_OPTION_*)
CHORUS_URL="${CHORUS_URL:-${CLAUDE_PLUGIN_OPTION_CHORUS_URL:-}}"
CHORUS_API_KEY="${CHORUS_API_KEY:-${CLAUDE_PLUGIN_OPTION_CHORUS_API_KEY:-}}"

# Check environment
if [ -z "${CHORUS_URL:-}" ] || [ -z "${CHORUS_API_KEY:-}" ]; then
if [ -z "$CHORUS_URL" ] || [ -z "$CHORUS_API_KEY" ]; then
exit 0
fi

Expand Down
6 changes: 5 additions & 1 deletion public/chorus-plugin/bin/on-subagent-stop.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
API="${SCRIPT_DIR}/chorus-api.sh"

# Resolve config: env var > userConfig (CLAUDE_PLUGIN_OPTION_*)
CHORUS_URL="${CHORUS_URL:-${CLAUDE_PLUGIN_OPTION_CHORUS_URL:-}}"
CHORUS_API_KEY="${CHORUS_API_KEY:-${CLAUDE_PLUGIN_OPTION_CHORUS_API_KEY:-}}"

# Check environment
if [ -z "${CHORUS_URL:-}" ] || [ -z "${CHORUS_API_KEY:-}" ]; then
if [ -z "$CHORUS_URL" ] || [ -z "$CHORUS_API_KEY" ]; then
exit 0
fi

Expand Down
6 changes: 5 additions & 1 deletion public/chorus-plugin/bin/on-task-completed.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
API="${SCRIPT_DIR}/chorus-api.sh"

# Resolve config: env var > userConfig (CLAUDE_PLUGIN_OPTION_*)
CHORUS_URL="${CHORUS_URL:-${CLAUDE_PLUGIN_OPTION_CHORUS_URL:-}}"
CHORUS_API_KEY="${CHORUS_API_KEY:-${CLAUDE_PLUGIN_OPTION_CHORUS_API_KEY:-}}"

# Check environment
if [ -z "${CHORUS_URL:-}" ] || [ -z "${CHORUS_API_KEY:-}" ]; then
if [ -z "$CHORUS_URL" ] || [ -z "$CHORUS_API_KEY" ]; then
exit 0
fi

Expand Down
6 changes: 5 additions & 1 deletion public/chorus-plugin/bin/on-teammate-idle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
API="${SCRIPT_DIR}/chorus-api.sh"

# Resolve config: env var > userConfig (CLAUDE_PLUGIN_OPTION_*)
CHORUS_URL="${CHORUS_URL:-${CLAUDE_PLUGIN_OPTION_CHORUS_URL:-}}"
CHORUS_API_KEY="${CHORUS_API_KEY:-${CLAUDE_PLUGIN_OPTION_CHORUS_API_KEY:-}}"

# Check environment
if [ -z "${CHORUS_URL:-}" ] || [ -z "${CHORUS_API_KEY:-}" ]; then
if [ -z "$CHORUS_URL" ] || [ -z "$CHORUS_API_KEY" ]; then
exit 0
fi

Expand Down
6 changes: 5 additions & 1 deletion public/chorus-plugin/bin/on-user-prompt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
STATE_DIR="${CLAUDE_PROJECT_DIR:-.}/.chorus"
SESSIONS_DIR="${STATE_DIR}/sessions"

# Resolve config: env var > userConfig (CLAUDE_PLUGIN_OPTION_*)
CHORUS_URL="${CHORUS_URL:-${CLAUDE_PLUGIN_OPTION_CHORUS_URL:-}}"
CHORUS_API_KEY="${CHORUS_API_KEY:-${CLAUDE_PLUGIN_OPTION_CHORUS_API_KEY:-}}"

# Skip entirely if Chorus is not configured
if [ -z "${CHORUS_URL:-}" ] || [ -z "${CHORUS_API_KEY:-}" ]; then
if [ -z "$CHORUS_URL" ] || [ -z "$CHORUS_API_KEY" ]; then
exit 0
fi

Expand Down
2 changes: 2 additions & 0 deletions public/chorus-plugin/bin/test-syntax.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ echo ""
# we only care about bash syntax/substitution errors before the API call.
export CHORUS_URL="http://localhost:0"
export CHORUS_API_KEY="cho_test"
export CLAUDE_PLUGIN_OPTION_CHORUS_URL="http://localhost:0"
export CLAUDE_PLUGIN_OPTION_CHORUS_API_KEY="cho_test"
export CLAUDE_PROJECT_DIR="/tmp/chorus-test-$$"
mkdir -p "$CLAUDE_PROJECT_DIR"

Expand Down
55 changes: 31 additions & 24 deletions public/chorus-plugin/skills/chorus/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,47 +221,54 @@ Use @mentions to notify specific users or agents. Mention syntax: `@[DisplayName

## Setup

### 1. Obtain API Key
### Option A: Plugin Install (Recommended)

API Keys must be created manually by the user in the Chorus Web UI.
When the Chorus plugin is installed or enabled, Claude Code automatically prompts for:
- **Chorus Server URL** — your Chorus instance (e.g., `https://chorus.example.com`)
- **Chorus API Key** — agent API key starting with `cho_` (stored securely in system keychain)

**Ask the user to:**
1. Open the Chorus settings page (e.g., `http://localhost:3000/settings`)
To obtain an API Key, **ask the user to:**
1. Open the Chorus settings page (e.g., `https://chorus.example.com/settings`)
2. Click **Create API Key**
3. Enter Agent name, select role (Developer / PM / Admin)
4. Click create and **immediately copy the key** (shown only once)

**Security notes:**
- Each Agent should have its own API Key with the minimum required role
- API Keys should not be committed to version control
To reconfigure later, use `/plugin` in Claude Code.

### 2. MCP Server Configuration
### Option B: Environment Variables (Headless / CI / Docker)

Config file: `.mcp.json` in the project root (or globally at `~/.claude/.mcp.json`).
For environments without a system keychain, set environment variables directly:

```json
{
"mcpServers": {
"chorus": {
"type": "http",
"url": "<BASE_URL>/api/mcp",
"headers": {
"Authorization": "Bearer <your-api-key>"
}
}
}
}
```bash
export CHORUS_URL="https://chorus.example.com"
export CHORUS_API_KEY="cho_your_key_here"
```

Environment variables always take priority over plugin userConfig. This is the recommended approach for CI/CD pipelines, Docker containers, and remote servers.

### Optional: Default Project

Set `CHORUS_DEFAULT_PROJECT` to auto-select a project (per working directory):

```bash
export CHORUS_DEFAULT_PROJECT="<project-uuid>"
```

Restart Claude Code after configuration.
This is an environment variable only — not part of plugin userConfig, since it varies per project directory.

### Security Notes

- Each Agent should have its own API Key with the minimum required role
- API Keys should not be committed to version control
- With plugin userConfig, the API Key is stored in the system keychain (not in settings files)

### 3. Verify Connection
### Verify Connection

```
chorus_checkin()
```

If it fails, check: API Key correct (`cho_` prefix)? URL reachable? Claude Code restarted?
If it fails, check: API Key correct (`cho_` prefix)? URL reachable? Claude Code restarted after config?

### 4. Role-Specific Tool Access

Expand Down
Loading