clawdforge/clients/bash
Kayos 7ba7058cd5 clients/bash: apply audit findings — security hardening + correctness fixes (347fdde → new)
Security:
- S1: bearer via tmpfile/--config, not cmdline arg (no /proc/<pid>/cmdline leak)
- S2/S3: JSON-escape user input in --files, --ip-cidrs, token name
- S4: URL-encode token name in revoke
- S5: refuse to source cf.env unless 0600/0400 + owner-matched
- S6: reject ; in upload paths to defeat curl @ filename injection

Correctness:
- B1: refuse cf run - on TTY stdin
- B2: replace fragile files splice with proper JSON-array composer (raw: passthrough in _json_obj_from_assoc)
- B3: disable glob on comma-split (set -f around loop)
- B4: only create stdin tmpfile when actually used
- B5: EXIT trap (was RETURN; missed _die exit)
- B6/B7: --max-time + stderr capture on uploads
- B8: drop bare Bearer header on healthz when no token
- B9: validate admin subcommand before token
- B10: wire _extract_error into HTTP-error path
- U3: dedicated '# --- end help ---' sentinel for cmd_help

New: clients/bash/test/test_cf.sh (curl wrapper mock + 23 assertions covering
all of the above; fully shellcheck-clean).

Audit: memory/clawdforge-audits/bash-347fdde.md
2026-04-28 23:09:06 -07:00
..
test clients/bash: apply audit findings — security hardening + correctness fixes (347fdde → new) 2026-04-28 23:09:06 -07:00
cf clients/bash: apply audit findings — security hardening + correctness fixes (347fdde → new) 2026-04-28 23:09:06 -07:00
README.md clients/bash: cf — single-file bash CLI for clawdforge 2026-04-28 22:25:50 -07:00

cf — bash CLI for clawdforge

Single-file shell client for clawdforge. Wraps curl so you can drive clawdforge from cron jobs, deploy scripts, one-off pipes, or any shell where pulling in a Python/Go runtime is overkill.

Install

sudo install -m 755 cf /usr/local/bin/cf

Or just symlink into ~/bin:

ln -s "$(pwd)/cf" ~/bin/cf

No dependencies beyond curl + standard POSIX tools. jq is optional — used for prettier error output if available, never required.

Configuration

Reads from env or ~/.config/clawdforge/cf.env (env wins on conflict):

Variable Default Purpose
CLAWDFORGE_URL http://192.168.0.5:8800 clawdforge base URL
CLAWDFORGE_TOKEN per-app bearer; required for /run, /files
CLAWDFORGE_ADMIN_TOKEN bootstrap admin bearer; required for cf admin *

Example cf.env:

CLAWDFORGE_URL=http://192.168.0.5:8800
CLAWDFORGE_TOKEN=cf_AbCd...
CLAWDFORGE_ADMIN_TOKEN=...

Commands

cf healthz
cf run "<prompt>"  [--model sonnet] [--system "..."] [--timeout 60] [--files token1,token2]
cf run -                                     # read prompt from stdin (any size)
cf upload <path>   [--ttl 3600]
cf admin token-mint <name>  [--ip-cidrs cidr1,cidr2]
cf admin token-list
cf admin token-revoke <name>

Output is JSON to stdout — pipe to jq for shaping. Errors go to stderr.

Exit codes

Code Meaning
0 ok
1 curl/transport failure
2 usage error (bad/missing args)
3 missing required token
4 HTTP 4xx (auth, not found, bad request)
5 HTTP 5xx (server / claude failure)

Examples

Health check in a cron preamble

cf healthz | jq -e '.claude_present' >/dev/null || { echo "clawdforge not ready"; exit 1; }

One-shot prompt with JSON output

cf run 'Reply with JSON: {"city":"Lake Elsinore","feel":"summer"}' --model sonnet \
  | jq -r '.result.city'

Long prompt via stdin (anything bigger than the OS argv limit)

cat <<'PROMPT' | cf run - --timeout 180
You are a precise recipe parser. Given the following text…
PROMPT

The bash CLI doesn't do anything special for size — it relies on clawdforge's server-side stdin path for prompts > 64KB.

Upload a file then attach it to a run

ft=$(cf upload /tmp/recipe.png --ttl 3600 | jq -r '.file_token')
cf run "extract the recipe from this image as JSON" --files "$ft" --timeout 120

Mint a per-app token

cf admin token-mint johnny5 --ip-cidrs 172.24.0.0/16
# → {"name":"johnny5","token":"cf_...","ip_cidrs":["172.24.0.0/16"]}

Pattern: bash-only no-jq fallback

If you can't install jq, parse with read:

read -r status size < <(cf upload "$path" | grep -o '"file_token":"[^"]*"\|"size":[0-9]*' | tr '\n' ' ')

But really, install jq.

License

Same as the rest of clawdforge (MIT).