Add CLI standard documentation for reference
This commit is contained in:
parent
97494a8775
commit
70f4d78c0c
210
CLI_STANDARD.md
Normal file
210
CLI_STANDARD.md
Normal file
@ -0,0 +1,210 @@
|
||||
# CLI Integration Standard
|
||||
|
||||
Standard for adding programmatic CLI access to all projects so AI agents can work without browser automation.
|
||||
|
||||
## Rule: CLI Tools Live INSIDE the Project
|
||||
|
||||
**Location:** `{project-root}/scripts/`
|
||||
|
||||
**Why:**
|
||||
- Version controlled with the project
|
||||
- Self-documenting (API + CLI in same repo)
|
||||
- Portable (clone repo, CLI works immediately)
|
||||
- Project-specific logic stays with project
|
||||
- No hunting around workspace folders
|
||||
|
||||
## Required File Structure
|
||||
|
||||
```
|
||||
project-root/
|
||||
├── scripts/
|
||||
│ ├── crud.sh # Main CRUD operations
|
||||
│ ├── attach-file.sh # File attachments
|
||||
│ ├── README.md # Usage documentation
|
||||
│ └── .env.example # Required environment variables
|
||||
├── api/ # REST API routes (used by CLI)
|
||||
│ └── items/
|
||||
│ ├── route.ts
|
||||
│ └── [id]/
|
||||
│ ├── route.ts
|
||||
│ └── attachments/
|
||||
│ └── route.ts
|
||||
└── README.md # Project README with CLI section
|
||||
```
|
||||
|
||||
## Required CLI Commands
|
||||
|
||||
Every project MUST implement these:
|
||||
|
||||
```bash
|
||||
# From project root:
|
||||
./scripts/crud.sh list [filters] # List all items
|
||||
./scripts/crud.sh get <id> # Get single item
|
||||
./scripts/crud.sh create <json> # Create item
|
||||
./scripts/crud.sh update <id> <field> <value> # Update field
|
||||
./scripts/crud.sh delete <id> # Delete item
|
||||
./scripts/attach-file.sh <id> <path> # Attach file to item
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Each project's CLI needs these in `scripts/.env` (gitignored):
|
||||
|
||||
```bash
|
||||
# Supabase direct access (for bypassing auth)
|
||||
SUPABASE_URL=https://xxxx.supabase.co
|
||||
SUPABASE_SERVICE_ROLE_KEY=eyJ...
|
||||
|
||||
# Or API-based access
|
||||
API_URL=http://localhost:3000/api
|
||||
API_KEY=secret_key_for_cli_access
|
||||
```
|
||||
|
||||
## Supabase Direct Pattern (Recommended)
|
||||
|
||||
For Supabase projects, use direct DB access with service role key:
|
||||
|
||||
**File:** `scripts/crud.sh`
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Load env from scripts/.env
|
||||
source "$(dirname "$0")/.env"
|
||||
|
||||
action=$1
|
||||
shift
|
||||
|
||||
case $action in
|
||||
list)
|
||||
curl -s "${SUPABASE_URL}/rest/v1/items?select=*" \
|
||||
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
|
||||
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}" | jq '.'
|
||||
;;
|
||||
get)
|
||||
id=$1
|
||||
curl -s "${SUPABASE_URL}/rest/v1/items?id=eq.${id}" \
|
||||
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
|
||||
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}" | jq '.[0]'
|
||||
;;
|
||||
create)
|
||||
data=$1
|
||||
curl -s -X POST "${SUPABASE_URL}/rest/v1/items" \
|
||||
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
|
||||
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$data" | jq '.'
|
||||
;;
|
||||
update)
|
||||
id=$1
|
||||
field=$2
|
||||
value=$3
|
||||
curl -s -X PATCH "${SUPABASE_URL}/rest/v1/items?id=eq.${id}" \
|
||||
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
|
||||
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"${field}\": \"${value}\"}" | jq '.'
|
||||
;;
|
||||
delete)
|
||||
id=$1
|
||||
curl -s -X DELETE "${SUPABASE_URL}/rest/v1/items?id=eq.${id}" \
|
||||
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
|
||||
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}"
|
||||
echo "Deleted ${id}"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {list|get <id>|create <json>|update <id> <field> <value>|delete <id>}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
```
|
||||
|
||||
## File Attachment Pattern
|
||||
|
||||
**File:** `scripts/attach-file.sh`
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
source "$(dirname "$0")/.env"
|
||||
|
||||
ITEM_ID=$1
|
||||
FILE_PATH=$2
|
||||
|
||||
if [ -z "$ITEM_ID" ] || [ -z "$FILE_PATH" ]; then
|
||||
echo "Usage: $0 <item-id> <file-path>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$FILE_PATH" ]; then
|
||||
echo "Error: File not found: $FILE_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Read and encode file
|
||||
mime=$(file -b --mime-type "$FILE_PATH")
|
||||
base64=$(base64 -i "$FILE_PATH")
|
||||
filename=$(basename "$FILE_PATH")
|
||||
size=$(stat -f%z "$FILE_PATH" 2>/dev/null || stat -c%s "$FILE_PATH")
|
||||
|
||||
# Build attachment JSON
|
||||
attachment=$(jq -n \
|
||||
--arg id "$(uuidgen | tr '[:upper:]' '[:lower:]')" \
|
||||
--arg name "$filename" \
|
||||
--arg type "$mime" \
|
||||
--arg data "data:${mime};base64,${base64}" \
|
||||
--argjson size "$size" \
|
||||
'{id: $id, name: $name, type: $type, dataUrl: $data, size: $size}')
|
||||
|
||||
# Get current attachments, append new one
|
||||
current=$(curl -s "${SUPABASE_URL}/rest/v1/items?id=eq.${ITEM_ID}&select=attachments" \
|
||||
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
|
||||
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}" | jq '.[0].attachments // []')
|
||||
|
||||
updated=$(echo "$current" | jq ". + [$attachment]")
|
||||
|
||||
# Update item
|
||||
curl -s -X PATCH "${SUPABASE_URL}/rest/v1/items?id=eq.${ITEM_ID}" \
|
||||
-H "apikey: ${SUPABASE_SERVICE_ROLE_KEY}" \
|
||||
-H "Authorization: Bearer ${SUPABASE_SERVICE_ROLE_KEY}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"attachments\": $updated}" | jq '.'
|
||||
|
||||
echo "✅ Attached ${filename} (${size} bytes) to item ${ITEM_ID}"
|
||||
```
|
||||
|
||||
## Per-Project Reference
|
||||
|
||||
### Gantt Board
|
||||
- **Location:** `/Users/mattbruce/Documents/Projects/OpenClaw/Web/gantt-board/scripts/`
|
||||
- **Scripts:** `gantt-task-crud.sh`, `attach-file.sh`, `view-attachment.sh`
|
||||
- **Auth:** Supabase service role key
|
||||
- **Table:** `public.tasks`
|
||||
|
||||
### Adding CLI to a New Project
|
||||
|
||||
1. Create `scripts/` directory in project root
|
||||
2. Copy template scripts from gantt-board
|
||||
3. Update table names and fields for your project
|
||||
4. Create `scripts/.env` with Supabase credentials
|
||||
5. Test: `./scripts/crud.sh list`
|
||||
6. Commit to git: `git add scripts/ && git commit -m "Add CLI tools for AI access"`
|
||||
7. Update project's README.md with CLI usage section
|
||||
|
||||
## Agent Instructions
|
||||
|
||||
When working on a project:
|
||||
1. Check for `scripts/` directory in project root
|
||||
2. If CLI exists, use it: `./scripts/crud.sh list`
|
||||
3. If CLI doesn't exist, create it using patterns above
|
||||
4. NEVER create files in workspace scripts folder for project-specific tools
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
Before saying a task is done:
|
||||
- [ ] CLI tools are in `{project}/scripts/`, NOT workspace
|
||||
- [ ] Scripts are executable (`chmod +x`)
|
||||
- [ ] `.env` file exists with credentials (gitignored)
|
||||
- [ ] Scripts work: `./scripts/crud.sh list` returns data
|
||||
- [ ] Changes are committed to git
|
||||
- [ ] Project README documents CLI usage
|
||||
Loading…
Reference in New Issue
Block a user