Files
gh-ce-dot-net-ce-claude-mar…/commands/ace-configure.md
2025-11-29 18:08:19 +08:00

594 lines
15 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
description: Configure ACE server connection settings interactively
argument-hint: [--global] [--project]
---
# Configure ACE Connection
Interactive configuration wizard using ce-ace CLI v1.0.2+ features with Claude Code native UI.
## What This Does
**Two-step configuration:**
1. **Global Config**: Uses `ce-ace config validate` + `ce-ace config` with flags
2. **Project Config**: Creates `.claude/settings.json` with orgId and projectId
## Instructions for Claude
When the user runs `/ace:configure`, follow these steps:
### Step 1: Check ce-ace CLI Version and Dependencies
```bash
#!/usr/bin/env bash
set -euo pipefail
# Check for jq (required for JSON parsing)
if ! command -v jq >/dev/null 2>&1; then
echo "❌ jq not found (required for JSON parsing)"
echo ""
echo "Installation instructions:"
echo " macOS: brew install jq"
echo " Linux: apt-get install jq or yum install jq"
echo " Windows: Download from https://stedolan.github.io/jq/download/"
echo ""
exit 1
fi
# Check for ce-ace CLI
if ! command -v ce-ace >/dev/null 2>&1; then
echo "❌ ce-ace CLI not found"
echo ""
echo "Installation required:"
echo " npm install -g @ace-sdk/cli"
echo ""
exit 1
fi
VERSION=$(ce-ace --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
echo "✅ ce-ace CLI found (version: $VERSION)"
# Check version >= 1.0.2
REQUIRED_VERSION="1.0.2"
if [ "$(printf '%s\n' "$REQUIRED_VERSION" "$VERSION" | sort -V | head -n1)" != "$REQUIRED_VERSION" ]; then
echo "⚠️ ce-ace v$VERSION found, but v1.0.2+ required for non-interactive config"
echo ""
echo "Please upgrade:"
echo " npm install -g @ace-sdk/cli@latest"
echo ""
exit 1
fi
echo ""
```
### Step 2: Detect Scope
```bash
# Parse arguments
SCOPE="both"
if [ "${1:-}" == "--global" ]; then
SCOPE="global"
elif [ "${1:-}" == "--project" ]; then
SCOPE="project"
else
# Auto-detect: If in a git repo, do both; otherwise just global
if git rev-parse --show-toplevel 2>/dev/null; then
SCOPE="both"
else
SCOPE="global"
fi
fi
echo "📋 Configuration scope: $SCOPE"
echo ""
```
### Step 3: Global Configuration (if needed)
**If SCOPE is "global" or "both", use AskUserQuestion to gather inputs, then configure:**
1. **Ask for Server URL**:
Use AskUserQuestion tool:
```javascript
{
questions: [
{
question: "ACE Server URL?",
header: "Server URL",
multiSelect: false,
options: [
{
label: "Production (ace-api.code-engine.app)",
description: "Official ACE production server (recommended)"
},
{
label: "Localhost (localhost:9000)",
description: "Local development server"
}
]
}
]
}
```
Map user selection to URL:
- "Production" → `https://ace-api.code-engine.app`
- "Localhost" → `http://localhost:9000`
- "Other" → Prompt for custom URL
2. **Ask for API Token**:
Use AskUserQuestion tool:
```javascript
{
questions: [
{
question: "Enter your ACE API token (starts with 'ace_')?",
header: "API Token",
multiSelect: false,
options: [
{
label: "I have a token",
description: "Enter token in the next step"
},
{
label: "I need to get a token",
description: "Visit https://ace.code-engine.app/settings/tokens"
}
]
}
]
}
```
If user selects "I have a token", they'll provide it in the "Other" field.
If "I need to get a token", show them the URL and exit.
3. **Validate Token and Get Org/Project Info**:
```bash
echo "🔍 Validating token with ACE server..."
echo " Server: $SERVER_URL"
echo ""
# Use subshell to avoid polluting parent environment
# Workaround: ce-ace config validate doesn't accept --server-url flag properly
# Use environment variables instead
VALIDATION_OUTPUT=$(
ACE_SERVER_URL="$SERVER_URL" \
ACE_API_TOKEN="$API_TOKEN" \
ce-ace config validate --json 2>&1
)
VALIDATION_EXIT_CODE=$?
if [ $VALIDATION_EXIT_CODE -ne 0 ]; then
echo "❌ Token validation failed"
echo ""
echo "Error details:"
echo "$VALIDATION_OUTPUT"
echo ""
echo "Common issues:"
echo " - Invalid or expired token"
echo " - Network connectivity problems"
echo " - Server URL incorrect"
echo ""
echo "Please verify your token at: https://ace.code-engine.app/settings"
exit 1
fi
# Verify we got valid JSON back
if ! echo "$VALIDATION_OUTPUT" | jq empty 2>/dev/null; then
echo "❌ Invalid response from ACE server (not valid JSON)"
echo ""
echo "Response:"
echo "$VALIDATION_OUTPUT"
exit 1
fi
# Parse validation response
ORG_ID=$(echo "$VALIDATION_OUTPUT" | jq -r '.org_id // empty')
ORG_NAME=$(echo "$VALIDATION_OUTPUT" | jq -r '.org_name // empty')
PROJECTS_JSON=$(echo "$VALIDATION_OUTPUT" | jq -c '.projects // []')
# Verify required fields
if [ -z "$ORG_ID" ] || [ -z "$ORG_NAME" ]; then
echo "❌ Validation response missing required fields (org_id, org_name)"
echo ""
echo "Response:"
echo "$VALIDATION_OUTPUT"
exit 1
fi
# Check if user has any projects
PROJECT_COUNT=$(echo "$PROJECTS_JSON" | jq 'length')
if [ "$PROJECT_COUNT" -eq 0 ]; then
echo "⚠️ No projects found for organization: $ORG_NAME"
echo ""
echo "Please create a project first at: https://ace.code-engine.app/projects"
exit 1
fi
echo "✅ Validated! Organization: $ORG_NAME ($ORG_ID)"
echo " Projects available: $PROJECT_COUNT"
echo ""
```
4. **Ask User to Select Project** (use AskUserQuestion):
```javascript
// Parse projects from PROJECTS_JSON
// Build options dynamically from project list
{
questions: [
{
question: "Which project should be configured?",
header: "Project",
multiSelect: false,
options: [
// For each project in PROJECTS_JSON:
{
label: "project.project_name",
description: "project.project_id"
}
// ... more projects
]
}
]
}
```
Extract project_id from user selection.
5. **Configure with ce-ace CLI**:
```bash
echo "💾 Saving global configuration..."
# Determine config location (respect XDG_CONFIG_HOME)
GLOBAL_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/ace/config.json"
GLOBAL_CONFIG_DIR=$(dirname "$GLOBAL_CONFIG")
# Ensure config directory exists
if [ ! -d "$GLOBAL_CONFIG_DIR" ]; then
echo "📁 Creating config directory: $GLOBAL_CONFIG_DIR"
mkdir -p "$GLOBAL_CONFIG_DIR"
if [ $? -ne 0 ]; then
echo "❌ Failed to create config directory: $GLOBAL_CONFIG_DIR"
exit 1
fi
fi
# Save configuration
ce-ace config \
--server-url "$SERVER_URL" \
--api-token "$API_TOKEN" \
--project-id "$PROJECT_ID" \
--json
if [ $? -ne 0 ]; then
echo "❌ Failed to save global configuration (ce-ace config command failed)"
exit 1
fi
# Verify config file was created
if [ ! -f "$GLOBAL_CONFIG" ]; then
echo "❌ Global config was not created at expected location"
echo " Expected: $GLOBAL_CONFIG"
echo " Please check ce-ace CLI logs for details"
exit 1
fi
# Verify config is valid JSON
if ! jq empty "$GLOBAL_CONFIG" 2>/dev/null; then
echo "❌ Global config is not valid JSON"
echo " Location: $GLOBAL_CONFIG"
echo " Please check file contents"
exit 1
fi
# Verify required fields are present
if ! jq -e '.serverUrl and .apiToken' "$GLOBAL_CONFIG" >/dev/null 2>&1; then
echo "❌ Global config is missing required fields (serverUrl, apiToken)"
echo " Location: $GLOBAL_CONFIG"
exit 1
fi
echo "✅ Global configuration saved and verified:"
echo " Location: $GLOBAL_CONFIG"
echo " Server: $SERVER_URL"
echo " Project: $PROJECT_ID"
echo ""
```
### Step 4: Project Configuration (if needed)
**If SCOPE is "project" or "both":**
1. **Get Project Root**:
```bash
PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
PROJECT_CONFIG="$PROJECT_ROOT/.claude/settings.json"
echo "📂 Project root: $PROJECT_ROOT"
echo ""
```
2. **Check Existing Config**:
```bash
if [ -f "$PROJECT_CONFIG" ]; then
EXISTING_ORG=$(jq -r '.env.ACE_ORG_ID // empty' "$PROJECT_CONFIG" 2>/dev/null || echo "")
EXISTING_PROJECT=$(jq -r '.env.ACE_PROJECT_ID // empty' "$PROJECT_CONFIG" 2>/dev/null || echo "")
if [ -n "$EXISTING_ORG" ] && [ -n "$EXISTING_PROJECT" ]; then
echo " Found existing project configuration:"
echo " Organization ID: $EXISTING_ORG"
echo " Project ID: $EXISTING_PROJECT"
echo ""
# Ask user what they want to do - STOP HERE AND PROMPT
EXISTING_CONFIG="true"
fi
fi
```
3. **Prompt for Action** (if existing config found):
If existing configuration was detected, use AskUserQuestion:
```javascript
{
questions: [
{
question: "Found existing ACE configuration. What would you like to do?",
header: "Config Action",
multiSelect: false,
options: [
{
label: "Keep existing configuration",
description: "No changes - use current org and project settings"
},
{
label: "Update project only",
description: "Keep organization, select a different project"
},
{
label: "Reconfigure everything",
description: "Fresh setup - change both organization and project"
}
]
}
]
}
```
Based on user's choice:
- **"Keep existing configuration"** → Exit early:
```bash
echo "✅ Keeping existing configuration"
echo " Organization: $EXISTING_ORG"
echo " Project: $EXISTING_PROJECT"
exit 0
```
- **"Update project only"** → Skip to Step 5 (project selection), reuse $EXISTING_ORG
- **"Reconfigure everything"** → Continue with Step 4 (full flow)
4. **Read Global Config**:
```bash
GLOBAL_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/ace/config.json"
if [ ! -f "$GLOBAL_CONFIG" ]; then
echo "⚠️ No global config found at $GLOBAL_CONFIG"
echo " Run /ace:configure --global first"
exit 1
fi
# Check if multi-org mode
HAS_ORGS=$(jq 'has("orgs")' "$GLOBAL_CONFIG" 2>/dev/null || echo "false")
```
4. **Multi-Org Mode** (if HAS_ORGS is true):
Use AskUserQuestion to select organization:
```javascript
// Parse orgs from global config
// For each org in config.orgs:
{
questions: [
{
question: "Which organization should this project use?",
header: "Organization",
multiSelect: false,
options: [
{
label: "org.orgName",
description: "org_id"
}
// ... more orgs
]
}
]
}
```
Then ask for project from that org's project list.
5. **Single-Org Mode** (if HAS_ORGS is false):
Just ask for project ID directly using AskUserQuestion.
6. **Write .claude/settings.json**:
```bash
mkdir -p "$PROJECT_ROOT/.claude"
if [ -n "$ORG_ID" ]; then
# Multi-org: include ACE_ORG_ID in env
cat > "$PROJECT_CONFIG" <<EOF
{
"env": {
"ACE_ORG_ID": "$ORG_ID",
"ACE_PROJECT_ID": "$PROJECT_ID"
}
}
EOF
echo "✅ Project configuration saved:"
echo " Organization ID: $ORG_ID"
echo " Project ID: $PROJECT_ID"
else
# Single-org: just ACE_PROJECT_ID in env
cat > "$PROJECT_CONFIG" <<EOF
{
"env": {
"ACE_PROJECT_ID": "$PROJECT_ID"
}
}
EOF
echo "✅ Project configuration saved:"
echo " Project ID: $PROJECT_ID"
fi
echo " Location: $PROJECT_CONFIG"
echo ""
```
### Step 5: Show Summary
```bash
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "✅ ACE Configuration Complete!"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
if [ "$SCOPE" = "global" ] || [ "$SCOPE" = "both" ]; then
GLOBAL_CONFIG="${XDG_CONFIG_HOME:-$HOME/.config}/ace/config.json"
echo "Global Config: $GLOBAL_CONFIG ✓"
fi
if [ "$SCOPE" = "project" ] || [ "$SCOPE" = "both" ]; then
PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
echo "Project Config: $PROJECT_ROOT/.claude/settings.json ✓"
fi
echo ""
echo "Next steps:"
echo "1. Run: /ace:status to verify connection"
echo "2. Optional: /ace:bootstrap to populate playbook from codebase"
echo "3. Start coding - hooks will auto-search patterns!"
echo ""
```
## Implementation Notes for Claude
**Key Points:**
1. **Always use AskUserQuestion** for user input (not bash read or prompts)
2. **Parse JSON responses** from `ce-ace config validate --json`
3. **Build dynamic options** from validation response (orgs/projects)
4. **Map user selections** to actual values (e.g., "Production" → URL)
5. **Handle both single-org and multi-org modes** based on global config
**Error Handling:**
- Check jq availability (required for JSON parsing)
- Check ce-ace version >= 1.0.2
- Validate token before saving (with detailed error messages)
- Verify global config file was created and is valid JSON
- Verify global config has required fields (serverUrl, apiToken)
- Check user has at least one project in organization
- Handle missing global config for project-only mode
- Use subshell for environment variables (avoid pollution)
**User Experience:**
- Show progress messages at each step
- Display org/project names (not just IDs) in selections
- Provide helpful error messages with next steps
- Summarize what was configured
## What Gets Configured
### Global Config (~/.config/ace/config.json)
**Single-Org Mode:**
```json
{
"serverUrl": "https://ace-api.code-engine.app",
"apiToken": "ace_xxxxx",
"projectId": "prj_xxxxx",
"cacheTtlMinutes": 120
}
```
**Multi-Org Mode:**
```json
{
"serverUrl": "https://ace-api.code-engine.app",
"orgs": {
"org_xxxxx": {
"orgName": "My Organization",
"apiToken": "ace_xxxxx",
"projects": ["prj_123", "prj_456"]
}
},
"cacheTtlMinutes": 120
}
```
### Project Config (.claude/settings.json)
**Multi-Org:**
```json
{
"env": {
"ACE_ORG_ID": "org_xxxxx",
"ACE_PROJECT_ID": "prj_xxxxx"
}
}
```
**Single-Org:**
```json
{
"env": {
"ACE_PROJECT_ID": "prj_xxxxx"
}
}
```
## Usage Examples
### First-Time Setup (Both Global + Project)
```
/ace:configure
```
**Flow:**
1. Asks for server URL (production/localhost/custom)
2. Asks for API token
3. Validates token, fetches org/projects
4. Asks which project to configure
5. Saves global config (~/.config/ace/config.json)
6. Saves project config (.claude/settings.json)
### Update Global Config Only
```
/ace:configure --global
```
**Flow:**
1. Reconfigures global settings
2. Validates token
3. Updates ~/.config/ace/config.json
### Update Project Config Only
```
/ace:configure --project
```
**Flow:**
1. Reads existing global config
2. Asks which org/project for THIS project
3. Updates .claude/settings.json
## See Also
- `/ace:status` - Verify configuration
- `/ace:bootstrap` - Initialize playbook
- `ce-ace config --help` - CLI config help
- `ce-ace config show` - View current config