|
13 | 13 | # <N> continue Resume session with --continue flag |
14 | 14 | # restart Auto-detect workspace from cwd + restart |
15 | 15 | # continue Auto-detect workspace from cwd + resume |
16 | | -# init Minimal config setup (2 questions) |
| 16 | +# init Setup config (auto-detects project type) |
17 | 17 | # config Show current configuration |
18 | 18 | # config scan Auto-detect .env files and ports |
19 | 19 | # doctor Diagnose common issues |
@@ -2664,10 +2664,9 @@ tk_upload_slack() { |
2664 | 2664 |
|
2665 | 2665 | # Otherwise use curl with Slack API |
2666 | 2666 | if [ -z "$slack_token" ]; then |
2667 | | - error "Slack not configured. Add to ~/.crabcode/config.yaml:" |
| 2667 | + error "Slack not configured. Set CRAB_SLACK_BOT_TOKEN env var:" |
2668 | 2668 | echo "" |
2669 | | - echo "slack:" |
2670 | | - echo " bot_token: xoxb-your-bot-token" |
| 2669 | + echo " export CRAB_SLACK_BOT_TOKEN=xoxb-your-bot-token" |
2671 | 2670 | return 1 |
2672 | 2671 | fi |
2673 | 2672 |
|
@@ -3024,9 +3023,13 @@ handle_tk_command() { |
3024 | 3023 | # Slack Integration |
3025 | 3024 | # ============================================================================= |
3026 | 3025 |
|
3027 | | -# Get Slack bot token from config |
| 3026 | +# Get Slack bot token from env var (preferred) or config |
3028 | 3027 | slack_get_token() { |
3029 | | - config_get "slack.bot_token" "" |
| 3028 | + if [ -n "${CRAB_SLACK_BOT_TOKEN:-}" ]; then |
| 3029 | + echo "$CRAB_SLACK_BOT_TOKEN" |
| 3030 | + else |
| 3031 | + config_get "slack.bot_token" "" |
| 3032 | + fi |
3030 | 3033 | } |
3031 | 3034 |
|
3032 | 3035 | # Get display name for messages (git config or override) |
@@ -3206,7 +3209,7 @@ slack_chat() { |
3206 | 3209 | local token=$(slack_get_token) |
3207 | 3210 |
|
3208 | 3211 | if [ -z "$token" ]; then |
3209 | | - error "Slack not configured. Add bot_token to ~/.crabcode/config.yaml" |
| 3212 | + error "Slack not configured. Set CRAB_SLACK_BOT_TOKEN env var" |
3210 | 3213 | return 1 |
3211 | 3214 | fi |
3212 | 3215 |
|
@@ -3313,7 +3316,7 @@ slack_send() { |
3313 | 3316 | local token=$(slack_get_token) |
3314 | 3317 |
|
3315 | 3318 | if [ -z "$token" ]; then |
3316 | | - error "Slack not configured. Add bot_token to ~/.crabcode/config.yaml" |
| 3319 | + error "Slack not configured. Set CRAB_SLACK_BOT_TOKEN env var" |
3317 | 3320 | return 1 |
3318 | 3321 | fi |
3319 | 3322 |
|
@@ -3362,7 +3365,7 @@ slack_read() { |
3362 | 3365 | local token=$(slack_get_token) |
3363 | 3366 |
|
3364 | 3367 | if [ -z "$token" ]; then |
3365 | | - error "Slack not configured. Add bot_token to ~/.crabcode/config.yaml" |
| 3368 | + error "Slack not configured. Set CRAB_SLACK_BOT_TOKEN env var" |
3366 | 3369 | return 1 |
3367 | 3370 | fi |
3368 | 3371 |
|
@@ -3497,17 +3500,158 @@ show_slack_help() { |
3497 | 3500 | echo " crab slack read @michael" |
3498 | 3501 | echo " crab slack chat @michael" |
3499 | 3502 | echo "" |
3500 | | - echo "Configuration (~/.crabcode/config.yaml):" |
| 3503 | + echo "Configuration:" |
| 3504 | + echo " export CRAB_SLACK_BOT_TOKEN=xoxb-your-token # add to shell profile" |
| 3505 | + echo "" |
| 3506 | + echo "Optional (~/.crabcode/config.yaml):" |
3501 | 3507 | echo " slack:" |
3502 | | - echo " bot_token: xoxb-your-token" |
3503 | | - echo " display_name: \"Your Name\" # optional, defaults to git config" |
| 3508 | + echo " display_name: \"Your Name\" # defaults to git config" |
3504 | 3509 | } |
3505 | 3510 |
|
3506 | 3511 | # ============================================================================= |
3507 | 3512 | # Init / Config / Doctor |
3508 | 3513 | # ============================================================================= |
3509 | 3514 |
|
| 3515 | +# -- Template System ---------------------------------------------------------- |
| 3516 | + |
| 3517 | +template_promptfoo_cloud() { |
| 3518 | + cat << 'TEMPLATE_EOF' |
| 3519 | +# Crabcode Configuration - Promptfoo Cloud Template |
| 3520 | +# Generated by 'crabcode init --template promptfoo-cloud' |
| 3521 | +
|
| 3522 | +session_name: crab |
| 3523 | +workspace_base: WORKSPACE_BASE_PLACEHOLDER |
| 3524 | +main_repo: MAIN_REPO_PLACEHOLDER |
| 3525 | +
|
| 3526 | +workspaces: |
| 3527 | + prefix: cloud-workspace |
| 3528 | + branch_pattern: workspace-{N} |
| 3529 | +
|
| 3530 | +layout: |
| 3531 | + panes: |
| 3532 | + - name: terminal |
| 3533 | + command: "" |
| 3534 | + - name: server |
| 3535 | + command: pnpm dev |
| 3536 | + - name: main |
| 3537 | + command: claude --dangerously-skip-permissions --chrome |
| 3538 | +
|
| 3539 | +install_command: pnpm install |
| 3540 | +install_env: PROMPTFOO_NODE_MODULES_CACHED=true |
| 3541 | +
|
| 3542 | +submodules: |
| 3543 | + - path: promptfoo |
| 3544 | + reset_to: origin/main |
| 3545 | + install_command: pnpm install |
| 3546 | +
|
| 3547 | +env_sync: |
| 3548 | + port_spacing: 10 |
| 3549 | + files: |
| 3550 | + - path: server/.env |
| 3551 | + copy_from: server/.env.example |
| 3552 | + ports: [API_URL, APP_URL] |
| 3553 | + refs: |
| 3554 | + API_PORT: API_URL:port |
| 3555 | + - path: app/.env |
| 3556 | + copy_from: app/.env.example |
| 3557 | + refs: |
| 3558 | + VITE_API_BASE_URL: API_URL |
| 3559 | + PORT: APP_URL:port |
| 3560 | + - path: admin-app/.env |
| 3561 | + copy_from: admin-app/.env.example |
| 3562 | + refs: |
| 3563 | + VITE_API_BASE_URL: API_URL |
| 3564 | + - path: promptfoo/.env |
| 3565 | + refs: |
| 3566 | + PROMPTFOO_REMOTE_GENERATION_URL: API_URL |
| 3567 | + PROMPTFOO_UNALIGNED_INFERENCE_ENDPOINT: API_URL |
| 3568 | + API_HOST: API_URL |
| 3569 | +
|
| 3570 | +cleanup: |
| 3571 | + preserve_files: ".env" |
| 3572 | + kill_pattern: "cloud-workspace-{N}.*pnpm|cloud-workspace-{N}.*node" |
| 3573 | +
|
| 3574 | +shared_volume: |
| 3575 | + enabled: true |
| 3576 | + path: ~/.crabcode/shared |
| 3577 | + link_as: .local |
| 3578 | +TEMPLATE_EOF |
| 3579 | +} |
| 3580 | + |
| 3581 | +detect_template() { |
| 3582 | + local repo_path="${1:-.}" |
| 3583 | + |
| 3584 | + # Check for promptfoo-cloud: has .gitmodules with "promptfoo" AND server/.env.example |
| 3585 | + if [ -f "$repo_path/.gitmodules" ] && grep -q "promptfoo" "$repo_path/.gitmodules" 2>/dev/null \ |
| 3586 | + && [ -f "$repo_path/server/.env.example" ]; then |
| 3587 | + echo "promptfoo-cloud" |
| 3588 | + return |
| 3589 | + fi |
| 3590 | + |
| 3591 | + # Fallback: directory name contains "promptfoo-cloud" |
| 3592 | + if [[ "$(basename "$repo_path")" == *"promptfoo-cloud"* ]]; then |
| 3593 | + echo "promptfoo-cloud" |
| 3594 | + return |
| 3595 | + fi |
| 3596 | + |
| 3597 | + echo "" |
| 3598 | +} |
| 3599 | + |
| 3600 | +apply_template() { |
| 3601 | + local template_name="$1" |
| 3602 | + local main_repo="$2" |
| 3603 | + local workspace_base="$3" |
| 3604 | + |
| 3605 | + local template_content="" |
| 3606 | + case "$template_name" in |
| 3607 | + "promptfoo-cloud") |
| 3608 | + template_content="$(template_promptfoo_cloud)" |
| 3609 | + ;; |
| 3610 | + *) |
| 3611 | + error "Unknown template: $template_name" |
| 3612 | + return 1 |
| 3613 | + ;; |
| 3614 | + esac |
| 3615 | + |
| 3616 | + mkdir -p "$CONFIG_DIR" |
| 3617 | + echo "$template_content" \ |
| 3618 | + | sed "s|MAIN_REPO_PLACEHOLDER|$main_repo|g" \ |
| 3619 | + | sed "s|WORKSPACE_BASE_PLACEHOLDER|$workspace_base|g" \ |
| 3620 | + > "$CONFIG_FILE" |
| 3621 | +} |
| 3622 | + |
| 3623 | +show_templates() { |
| 3624 | + echo -e "${CYAN}Available Templates${NC}" |
| 3625 | + echo "" |
| 3626 | + echo -e " ${GREEN}promptfoo-cloud${NC} Full config for promptfoo-cloud repos" |
| 3627 | + echo " Includes env_sync, submodules, port_spacing, install_env" |
| 3628 | + echo "" |
| 3629 | + echo "Usage:" |
| 3630 | + echo " crab init --template promptfoo-cloud" |
| 3631 | + echo " crab init -t promptfoo-cloud" |
| 3632 | +} |
| 3633 | + |
| 3634 | +# -- End Template System ------------------------------------------------------ |
| 3635 | + |
3510 | 3636 | show_init() { |
| 3637 | + # Parse arguments |
| 3638 | + local template_name="" |
| 3639 | + while [ $# -gt 0 ]; do |
| 3640 | + case "$1" in |
| 3641 | + --template|-t) |
| 3642 | + template_name="$2" |
| 3643 | + shift 2 |
| 3644 | + ;; |
| 3645 | + --list-templates) |
| 3646 | + show_templates |
| 3647 | + return |
| 3648 | + ;; |
| 3649 | + *) |
| 3650 | + shift |
| 3651 | + ;; |
| 3652 | + esac |
| 3653 | + done |
| 3654 | + |
3511 | 3655 | echo -e "${CYAN}Crabcode Setup${NC}" |
3512 | 3656 | echo "" |
3513 | 3657 |
|
@@ -3564,7 +3708,6 @@ show_init() { |
3564 | 3708 | fi |
3565 | 3709 |
|
3566 | 3710 | echo "Let's set up crabcode for your project." |
3567 | | - echo "(Minimal setup - run 'crab config scan' after to detect ports)" |
3568 | 3711 | echo "" |
3569 | 3712 |
|
3570 | 3713 | # Main repo |
@@ -3603,10 +3746,56 @@ show_init() { |
3603 | 3746 | # Expand ~ |
3604 | 3747 | workspace_base="${workspace_base/#\~/$HOME}" |
3605 | 3748 |
|
3606 | | - # Create config directory |
| 3749 | + # Template handling: explicit flag or auto-detection |
| 3750 | + if [ -n "$template_name" ]; then |
| 3751 | + # Validate the explicit template name |
| 3752 | + case "$template_name" in |
| 3753 | + "promptfoo-cloud"|"pf") |
| 3754 | + template_name="promptfoo-cloud" |
| 3755 | + ;; |
| 3756 | + *) |
| 3757 | + error "Unknown template: $template_name" |
| 3758 | + echo "Run 'crab init --list-templates' to see available templates." |
| 3759 | + return 1 |
| 3760 | + ;; |
| 3761 | + esac |
| 3762 | + echo "" |
| 3763 | + echo -e "Applying ${GREEN}$template_name${NC} template..." |
| 3764 | + apply_template "$template_name" "$main_repo" "$workspace_base" |
| 3765 | + echo "" |
| 3766 | + success "Config created at $CONFIG_FILE (template: $template_name)" |
| 3767 | + echo "" |
| 3768 | + echo -e "${CYAN}Next steps:${NC}" |
| 3769 | + echo " 1. Review config: crab config" |
| 3770 | + echo " 2. Run 'crab ws 1' to create your first workspace" |
| 3771 | + return |
| 3772 | + fi |
| 3773 | + |
| 3774 | + # Auto-detect template from repo contents |
| 3775 | + local detected |
| 3776 | + detected=$(detect_template "$main_repo") |
| 3777 | + if [ -n "$detected" ]; then |
| 3778 | + echo "" |
| 3779 | + echo -e "Detected ${GREEN}$detected${NC} project." |
| 3780 | + read -p "Use template? [Y/n]: " use_tpl |
| 3781 | + if [ "$use_tpl" != "n" ] && [ "$use_tpl" != "N" ]; then |
| 3782 | + echo "" |
| 3783 | + echo -e "Applying ${GREEN}$detected${NC} template..." |
| 3784 | + apply_template "$detected" "$main_repo" "$workspace_base" |
| 3785 | + echo "" |
| 3786 | + success "Config created at $CONFIG_FILE (template: $detected)" |
| 3787 | + echo "" |
| 3788 | + echo -e "${CYAN}Next steps:${NC}" |
| 3789 | + echo " 1. Review config: crab config" |
| 3790 | + echo " 2. Run 'crab ws 1' to create your first workspace" |
| 3791 | + return |
| 3792 | + fi |
| 3793 | + echo "" |
| 3794 | + fi |
| 3795 | + |
| 3796 | + # No template - generate minimal config |
3607 | 3797 | mkdir -p "$CONFIG_DIR" |
3608 | 3798 |
|
3609 | | - # Generate minimal config file |
3610 | 3799 | cat > "$CONFIG_FILE" << EOF |
3611 | 3800 | # Crabcode Configuration |
3612 | 3801 | # Generated by 'crabcode init' |
@@ -5793,7 +5982,9 @@ show_help() { |
5793 | 5982 | echo " tk share --serve Local HTTP server" |
5794 | 5983 | echo "" |
5795 | 5984 | echo "Other Commands:" |
5796 | | - echo " init Minimal config setup (2 questions)" |
| 5985 | + echo " init Setup config (auto-detects project type)" |
| 5986 | + echo " init -t <name> Setup with template (e.g., promptfoo-cloud)" |
| 5987 | + echo " init --list-templates Show available templates" |
5797 | 5988 | echo " config Show configuration" |
5798 | 5989 | echo " config scan Auto-detect .env files and ports" |
5799 | 5990 | echo " doctor Diagnose issues" |
@@ -6039,7 +6230,7 @@ main() { |
6039 | 6230 | handle_ws_command "${@:2}" |
6040 | 6231 | ;; |
6041 | 6232 | "init") |
6042 | | - show_init |
| 6233 | + show_init "${@:2}" |
6043 | 6234 | ;; |
6044 | 6235 | "config") |
6045 | 6236 | if [ "${2:-}" = "scan" ]; then |
|
0 commit comments