15 KiB
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:
- Global Config: Uses
ce-ace config validate+ce-ace configwith flags - Project Config: Creates
.claude/settings.jsonwith orgId and projectId
Instructions for Claude
When the user runs /ace:configure, follow these steps:
Step 1: Check ce-ace CLI Version and Dependencies
#!/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
# 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:
-
Ask for Server URL: Use AskUserQuestion tool:
{ 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
- "Production" →
-
Ask for API Token: Use AskUserQuestion tool:
{ 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.
-
Validate Token and Get Org/Project Info:
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 "" -
Ask User to Select Project (use AskUserQuestion):
// 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.
-
Configure with ce-ace CLI:
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":
-
Get Project Root:
PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd) PROJECT_CONFIG="$PROJECT_ROOT/.claude/settings.json" echo "📂 Project root: $PROJECT_ROOT" echo "" -
Check Existing Config:
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 -
Prompt for Action (if existing config found):
If existing configuration was detected, use AskUserQuestion:
{ 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:
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)
- "Keep existing configuration" → Exit early:
-
Read Global Config:
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") -
Multi-Org Mode (if HAS_ORGS is true):
Use AskUserQuestion to select organization:
// 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.
-
Single-Org Mode (if HAS_ORGS is false):
Just ask for project ID directly using AskUserQuestion.
-
Write .claude/settings.json:
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:
- Always use AskUserQuestion for user input (not bash read or prompts)
- Parse JSON responses from
ce-ace config validate --json - Build dynamic options from validation response (orgs/projects)
- Map user selections to actual values (e.g., "Production" → URL)
- 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:
{
"serverUrl": "https://ace-api.code-engine.app",
"apiToken": "ace_xxxxx",
"projectId": "prj_xxxxx",
"cacheTtlMinutes": 120
}
Multi-Org Mode:
{
"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:
{
"env": {
"ACE_ORG_ID": "org_xxxxx",
"ACE_PROJECT_ID": "prj_xxxxx"
}
}
Single-Org:
{
"env": {
"ACE_PROJECT_ID": "prj_xxxxx"
}
}
Usage Examples
First-Time Setup (Both Global + Project)
/ace:configure
Flow:
- Asks for server URL (production/localhost/custom)
- Asks for API token
- Validates token, fetches org/projects
- Asks which project to configure
- Saves global config (~/.config/ace/config.json)
- Saves project config (.claude/settings.json)
Update Global Config Only
/ace:configure --global
Flow:
- Reconfigures global settings
- Validates token
- Updates ~/.config/ace/config.json
Update Project Config Only
/ace:configure --project
Flow:
- Reads existing global config
- Asks which org/project for THIS project
- Updates .claude/settings.json
See Also
/ace:status- Verify configuration/ace:bootstrap- Initialize playbookce-ace config --help- CLI config helpce-ace config show- View current config