Skip to content
Merged
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
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ foundry profile activate --name <name> # Switch between environments
# App Development Lifecycle
foundry apps create --name "X" --no-prompt --no-git # Create new app
foundry apps run # Start full app locally in dev mode
FOUNDRY_FF_ENHANCED_UI=false foundry apps deploy --change-type Patch --change-log "msg" --no-prompt # Deploy to cloud
FOUNDRY_FF_ENHANCED_UI=false foundry apps release --change-type Patch --deployment-id <id> --notes "notes" # Release to app catalog
foundry apps deploy --change-type Patch --change-log "msg" --no-prompt # Deploy to cloud
foundry apps release --change-type Patch --deployment-id <id> --notes "notes" # Release to app catalog
foundry ui run # Local UI development server

# Scaffolding Commands (ALWAYS use --no-prompt)
Expand Down
14 changes: 8 additions & 6 deletions hooks/foundry-cli-guard.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
# 2. Running ui extensions create without --sockets (interactive picker hangs)
# 3. Using mkdir/touch to create app structure (causes invalid manifests)
# 4. Creating resources without user confirmation of the name
# 5. Running deploy/release/list-deployments without FOUNDRY_FF_ENHANCED_UI=false (TUI hangs)
# 5. Running deploy/release/list-deployments without FOUNDRY_UI_HEADLESS_MODE=true (TUI hangs)
# Note: The SessionStart hook (set-foundry-env.sh) sets this env var automatically.
# This guard is a fallback for edge cases where the env var isn't set.
#
# Receives JSON on stdin with hook_event_name and tool-specific fields.
# Outputs JSON with additionalContext (advisory nudge, not blocking).
Expand Down Expand Up @@ -94,16 +96,16 @@ if echo "$COMMAND" | grep -qE 'foundry\s+ui\s+extensions\b.*\bcreate\b'; then
fi
fi

# Check for foundry apps deploy/release/list-deployments without FOUNDRY_FF_ENHANCED_UI=false
# Check for foundry apps deploy/release/list-deployments without FOUNDRY_UI_HEADLESS_MODE=true
# Normally the SessionStart hook sets this env var, but this guard catches edge cases.
# The enhanced UI (TUI progress monitor) requires a TTY and hangs in non-interactive environments.
# Some developers set FOUNDRY_FF_ENHANCED_UI=true; future CLI versions may default to true.
# Skip advisory only when the env var is explicitly "false" — unset or "true" both need the prefix.
# Skip advisory only when the env var is explicitly "true" — unset or "false" both need the prefix.
if echo "$COMMAND" | grep -qE 'foundry\s+apps\s+(deploy|release|list-deployments)\b'; then
if [ "${FOUNDRY_FF_ENHANCED_UI:-}" != "false" ] && ! echo "$COMMAND" | grep -qF 'FOUNDRY_FF_ENHANCED_UI=false'; then
if [ "${FOUNDRY_UI_HEADLESS_MODE:-}" != "true" ] && ! echo "$COMMAND" | grep -qF 'FOUNDRY_UI_HEADLESS_MODE=true'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
additionalContext: "The command is missing FOUNDRY_FF_ENHANCED_UI=false. The enhanced UI (TUI progress monitor) requires a TTY and will hang in Claude Code. Prepend FOUNDRY_FF_ENHANCED_UI=false to the command. Example: FOUNDRY_FF_ENHANCED_UI=false foundry apps deploy --change-type Patch --change-log \"msg\""
additionalContext: "The command is missing FOUNDRY_UI_HEADLESS_MODE=true. The enhanced UI (TUI progress monitor) requires a TTY and will hang in Claude Code. Prepend FOUNDRY_UI_HEADLESS_MODE=true to the command. Example: FOUNDRY_UI_HEADLESS_MODE=true foundry apps deploy --change-type Patch --change-log \"msg\""
}
}'
exit 0
Expand Down
11 changes: 11 additions & 0 deletions hooks/hooks.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/set-foundry-env.sh",
"timeout": 5
}
]
}
],
"UserPromptSubmit": [
{
"hooks": [
Expand Down
15 changes: 15 additions & 0 deletions hooks/set-foundry-env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
#
# set-foundry-env.sh — SessionStart hook
#
# Sets FOUNDRY_UI_HEADLESS_MODE=true for the entire session so that
# deploy, release, and list-deployments commands work without a TTY.
# This eliminates the need to prefix each command manually.
#
set -euo pipefail

if [ -n "${CLAUDE_ENV_FILE:-}" ]; then
echo 'export FOUNDRY_UI_HEADLESS_MODE=true' >> "$CLAUDE_ENV_FILE"
fi

exit 0
27 changes: 11 additions & 16 deletions skills/foundry-development-workflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,8 @@ metadata:
>
> **CRITICAL: `--no-prompt` is supported by nearly all commands.** Always add `--no-prompt` to prevent interactive prompts that cause `Error: EOF` in non-interactive environments. Supported commands include: `apps create`, `apps deploy`, `apps release`, `apps delete` (also needs `--force-delete`, but may still prompt interactively in some CLI versions — delete via Falcon App Manager UI if it hangs), `functions create`, `collections create`, `ui pages create`, `ui extensions create`, `rtr-scripts create`, `profile create`, `workflows create`, and `api-integrations create`. When unsure, run `foundry <command> --help` to check. When a CLI command fails, MUST NOT fall back to `mkdir` — fix the command and retry.
>
> **CRITICAL: `FOUNDRY_FF_ENHANCED_UI=false` is required for non-TTY environments.**
> The enhanced UI (TUI progress monitor) requires a TTY and will hang or fail in Claude Code, CI/CD pipelines, and headless environments. **Always prepend `FOUNDRY_FF_ENHANCED_UI=false` to these commands:**
> - `foundry apps deploy`
> - `foundry apps release`
> - `foundry apps list-deployments`
>
> Example: `FOUNDRY_FF_ENHANCED_UI=false foundry apps deploy --change-type Patch --change-log "msg"`
> **NOTE: `FOUNDRY_UI_HEADLESS_MODE=true` is set automatically** by the plugin's SessionStart hook.
> You do not need to prefix `deploy`, `release`, or `list-deployments` commands with it.
>
> **Superpowers skills MAY supplement** (TDD discipline, code review) but MUST NOT replace this workflow.

Expand Down Expand Up @@ -127,7 +122,7 @@ foundry api-integrations create --name "MyApi" --description "desc" --spec /tmp/
foundry collections create --name "my_col" --schema /tmp/my_schema.json --description "desc" --no-prompt

# 3. DEPLOY EARLY — fail fast if specs or schemas are bad
FOUNDRY_FF_ENHANCED_UI=false foundry apps deploy --no-prompt --change-type Patch --change-log "Backend capabilities"
foundry apps deploy --no-prompt --change-type Patch --change-log "Backend capabilities"
# Poll with list-deployments — if still in progress, sleep 5 and retry
# If deploy fails, STOP. Fix the spec/schema — do not build UI on a broken backend.
# The adapt script should handle spec issues. If it didn't, improve the script.
Expand Down Expand Up @@ -166,12 +161,12 @@ The CLI scaffolds structure but cannot generate app logic. Delegate to sub-skill
cd ui/pages/my-page && npm install && npm run build && cd ../../..

# Final deploy (run ONCE, never re-deploy to check status)
FOUNDRY_FF_ENHANCED_UI=false foundry apps deploy --no-prompt --change-type Patch --change-log "Complete app"
foundry apps deploy --no-prompt --change-type Patch --change-log "Complete app"

# Poll deployment status — run immediately, do NOT prepend sleep
FOUNDRY_FF_ENHANCED_UI=false foundry apps list-deployments
foundry apps list-deployments
# If still in progress, wait 5s then poll again:
# sleep 5 && FOUNDRY_FF_ENHANCED_UI=false foundry apps list-deployments
# sleep 5 && foundry apps list-deployments

# Local UI development (deploy first if UI calls backend capabilities)
foundry ui run
Expand All @@ -181,7 +176,7 @@ foundry ui run

```bash
# Release (run ONCE after deploy succeeds)
FOUNDRY_FF_ENHANCED_UI=false foundry apps release --change-type Patch --deployment-id <id> --notes "Release notes"
foundry apps release --change-type Patch --deployment-id <id> --notes "Release notes"
```

**Note:** There is no `list-releases` command. After `release`, check status via the App Manager URL printed in the output, or wait ~30s and proceed to testing.
Expand Down Expand Up @@ -215,7 +210,7 @@ To deploy the same app to multiple clouds (US-1, US-2, EU-1, etc.):

When `manifest.yml` already exists, work is primarily editing existing files. Use CLI only for:
- `foundry apps run` / `foundry ui run` — local development
- `FOUNDRY_FF_ENHANCED_UI=false foundry apps deploy` / `FOUNDRY_FF_ENHANCED_UI=false foundry apps release` — deployment
- `foundry apps deploy` / `foundry apps release` — deployment
- `foundry api-integrations create` etc. — adding new capabilities

## Testing an Existing App Locally
Expand All @@ -225,11 +220,11 @@ When running e2e tests against an existing app:
1. **Update manifest name** if needed (to match `APP_NAME` in `e2e/.env`)
2. **Deploy and release:**
```bash
FOUNDRY_FF_ENHANCED_UI=false foundry apps deploy --change-type patch --change-log "e2e testing" --no-prompt
foundry apps deploy --change-type patch --change-log "e2e testing" --no-prompt
# Poll until successful
FOUNDRY_FF_ENHANCED_UI=false foundry apps list-deployments
foundry apps list-deployments
# Release
FOUNDRY_FF_ENHANCED_UI=false foundry apps release --deployment-id <id> --change-type patch --notes "e2e testing" --no-prompt
foundry apps release --deployment-id <id> --change-type patch --notes "e2e testing" --no-prompt
```
3. **Run tests:** `cd e2e && npx playwright test`
4. **Revert manifest:** `git checkout manifest.yml` (deploy writes IDs into the manifest)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ Commands that prompt for user input support `--no-prompt` to suppress prompts an
|---------|---------------------|
| `foundry apps create` | `foundry apps create --name "app" --description "desc" --no-prompt --no-git` |
| `foundry apps delete` | `foundry apps delete --force-delete --no-prompt` |
| `foundry apps deploy` | `FOUNDRY_FF_ENHANCED_UI=false foundry apps deploy --change-type minor --change-log "description" --no-prompt` |
| `foundry apps release` | `FOUNDRY_FF_ENHANCED_UI=false foundry apps release --deployment-id <id> --change-type minor --notes "notes"` |
| `foundry apps deploy` | `foundry apps deploy --change-type minor --change-log "description" --no-prompt` |
| `foundry apps release` | `foundry apps release --deployment-id <id> --change-type minor --notes "notes"` |
| `foundry profile create` | `foundry profile create --name <n> --api-client-id <id> --api-client-secret <s> --cid <c> --cloud-region <r> --no-prompt` |
| `foundry profile activate` | `foundry profile activate --name "profile-name"` |
| `foundry profile delete` | `foundry profile delete --name "profile-name" --no-prompt` |
Expand Down Expand Up @@ -85,12 +85,12 @@ Error: could not open a new TTY: open /dev/tty: device not configured

or hang and produce garbled output.

**Fix: Always prepend `FOUNDRY_FF_ENHANCED_UI=false`** to commands that trigger the TUI:
**Fix:** The plugin's SessionStart hook sets `FOUNDRY_UI_HEADLESS_MODE=true` automatically for all Bash commands. If running outside the plugin (CI/CD, scripts), set the env var manually:

```bash
FOUNDRY_FF_ENHANCED_UI=false foundry apps deploy --change-type Patch --change-log "description"
FOUNDRY_FF_ENHANCED_UI=false foundry apps release --deployment-id <id> --change-type Patch --notes "notes"
FOUNDRY_FF_ENHANCED_UI=false foundry apps list-deployments
foundry apps deploy --change-type Patch --change-log "description"
foundry apps release --deployment-id <id> --change-type Patch --notes "notes"
foundry apps list-deployments
```

This disables the TUI progress monitor and falls back to plain text output suitable for non-interactive environments.
Expand All @@ -115,7 +115,7 @@ When operating as a CLI agent:
3. **Never run `foundry login` without user confirmation:** The browser flow will hang in headless environments
4. **Always pass all required flags:** Never rely on interactive prompts — always include `--no-prompt` where supported
5. **Use `--no-git` on `foundry apps create`:** Prevents git init prompts in environments where git may not be configured
6. **Prepend `FOUNDRY_FF_ENHANCED_UI=false`** to `deploy`, `release`, and `list-deployments` commands to disable the TUI progress monitor
6. **`FOUNDRY_UI_HEADLESS_MODE=true`** is set automatically by the plugin's SessionStart hook. For standalone scripts/CI, export it manually.

## Counter-Rationalizations for Interactive Mode

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

```bash
# For apps with backend dependencies: deploy first, then iterate on UI
FOUNDRY_FF_ENHANCED_UI=false foundry apps deploy --change-type Patch --change-log "Initial deployment" --no-prompt
foundry apps deploy --change-type Patch --change-log "Initial deployment" --no-prompt
foundry ui run

# For pure UI work (no API integration/collection/function calls): no deploy needed
Expand Down
Loading