Back to skills
SkillHub ClubWrite Technical DocsFull StackTech WriterSecurity

static-files

Host static files on subdomains with optional authentication. Use when you need to serve HTML, images, CSS, JS, or any static content on a dedicated subdomain. Supports file upload, basic auth, quota management, and automatic SSL via Caddy. Commands include sf sites (create/list/delete), sf upload (files/directories), sf files (list/delete).

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
3,090
Hot score
99
Updated
March 20, 2026
Overall rating
C0.0
Composite score
0.0
Best-practice grade
B81.2

Install command

npx @skill-hub/cli install openclaw-skills-kleo-static-files

Repository

openclaw/skills

Skill path: skills/awaaate/kleo-static-files

Host static files on subdomains with optional authentication. Use when you need to serve HTML, images, CSS, JS, or any static content on a dedicated subdomain. Supports file upload, basic auth, quota management, and automatic SSL via Caddy. Commands include sf sites (create/list/delete), sf upload (files/directories), sf files (list/delete).

Open repository

Best for

Primary workflow: Write Technical Docs.

Technical facets: Full Stack, Tech Writer, Security.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: openclaw.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install static-files into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/openclaw/skills before adding static-files to shared team environments
  • Use static-files for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: static-files
description: >
  Host static files on subdomains with optional authentication. Use when you need to
  serve HTML, images, CSS, JS, or any static content on a dedicated subdomain. Supports
  file upload, basic auth, quota management, and automatic SSL via Caddy. Commands
  include sf sites (create/list/delete), sf upload (files/directories), sf files (list/delete).
---

# Static Files Hosting

Host static content on `*.{domain}` subdomains with automatic SSL.

## Quick Reference

```bash
# Create site
sf sites create mysite
# → https://mysite.498as.com

# Upload file
sf upload ./index.html mysite

# Upload directory  
sf upload ./dist mysite

# Add authentication
sf sites auth mysite admin:secretpass123

# List files
sf files mysite

# Delete file
sf files mysite delete path/to/file.txt

# Delete site
sf sites delete mysite
```

## Environment Setup

```bash
export SF_API_URL=http://localhost:3000   # API endpoint
export SF_API_KEY=sk_xxxxx                # Your API key
```

## Workflows

### Deploy a Static Website

```bash
# 1. Create the site
sf sites create docs

# 2. Upload the build directory
sf upload ./build docs

# 3. Verify
curl -I https://docs.498as.com
```

### Protected File Sharing

```bash
# 1. Create site with auth
sf sites create private
sf sites auth private user:strongpassword

# 2. Upload sensitive files
sf upload ./reports private

# 3. Share URL + credentials
# https://private.498as.com (user / strongpassword)
```

### Update Existing Files

```bash
# Overwrite existing file
sf upload ./new-version.pdf mysite --overwrite

# Or delete and re-upload
sf files mysite delete old-file.pdf
sf upload ./new-file.pdf mysite
```

## CLI Commands

### sites

| Command | Description |
|---------|-------------|
| `sf sites list` | List all sites |
| `sf sites create <name>` | Create new site |
| `sf sites delete <name>` | Delete site and all files |
| `sf sites auth <name> <user:pass>` | Set basic auth |
| `sf sites auth <name> --remove` | Remove auth |

### upload

```bash
sf upload <path> <site> [subdir] [--overwrite] [--json]
```

- `path`: File or directory to upload
- `site`: Target site name
- `subdir`: Optional subdirectory
- `--overwrite`: Replace existing files
- `--json`: Output JSON

### files

| Command | Description |
|---------|-------------|
| `sf files <site>` | List all files |
| `sf files <site> delete <path>` | Delete specific file |

### stats

```bash
sf stats              # Global stats
sf stats <site>       # Site-specific stats
```

## API Endpoints

Base: `$SF_API_URL` with `Authorization: Bearer $SF_API_KEY`

| Method | Path | Description |
|--------|------|-------------|
| GET | `/sites` | List sites |
| POST | `/sites` | Create site |
| DELETE | `/sites/{name}` | Delete site |
| PATCH | `/sites/{name}` | Update auth |
| GET | `/sites/{name}/files` | List files |
| POST | `/sites/{name}/files` | Upload file |
| DELETE | `/sites/{name}/files/{path}` | Delete file |
| GET | `/stats` | Global stats |
| GET | `/stats/{name}` | Site stats |
| GET | `/health` | Health check |

## Constraints

- **Site names**: lowercase, alphanumeric, hyphens only (max 63 chars)
- **File size**: 50MB default (configurable)
- **Quota**: 100MB per site default
- **Rate limit**: 100 requests/minute per API key

## Troubleshooting

### "Cannot connect to API"
```bash
# Check service status
systemctl status kleo-static-files

# Check if port is listening
curl http://localhost:3000/health
```

### "Invalid API key"
```bash
# Verify key is set
echo $SF_API_KEY

# Create new key if needed
bun run /opt/kleo-static-files/scripts/create-key.ts "new-key"
```

### "Quota exceeded"
```bash
# Check current usage
sf stats mysite

# Delete unused files
sf files mysite delete large-file.zip
```

### Site not accessible via HTTPS
```bash
# Verify DNS points to server
dig mysite.498as.com

# Check Caddy config
cat /etc/caddy/sites.d/static-files.caddy

# Resync Caddy
bun run /opt/kleo-static-files/scripts/sync-caddy.ts --reload
```

## Installation

### Server Installation (run once on host)

```bash
curl -fsSL https://raw.githubusercontent.com/498AS/kleo-static-files/main/install.sh | sudo bash
```

The installer outputs JSON with connection details between `KLEO_SF_CONFIG_BEGIN` and `KLEO_SF_CONFIG_END` markers. Parse this to get `api_url` and `api_key`.

### After Installation

```bash
export SF_API_URL=http://localhost:3000
export SF_API_KEY=sk_xxxxx  # from installer output
```

### Check Status

```bash
sudo /opt/kleo-static-files/install.sh --status
```

See [references/install.md](references/install.md) for manual installation.


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### references/install.md

```markdown
# Installation Guide

## Requirements

- Linux server (Ubuntu/Debian recommended)
- [Bun](https://bun.sh) runtime
- [Caddy](https://caddyserver.com) web server
- Git

## Quick Install

```bash
curl -fsSL https://raw.githubusercontent.com/498AS/kleo-static-files/main/install.sh | sudo bash
```

## Manual Install

### 1. Install Dependencies

```bash
# Bun
curl -fsSL https://bun.sh/install | bash

# Caddy (Ubuntu/Debian)
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update && sudo apt install caddy
```

### 2. Clone Repository

```bash
sudo git clone https://github.com/498AS/kleo-static-files.git /opt/kleo-static-files
cd /opt/kleo-static-files
bun install
```

### 3. Configure

Create `/opt/kleo-static-files/.env`:

```bash
SF_PORT=3000
SF_DOMAIN=yourdomain.com
SF_SITES_ROOT=/var/lib/kleo-static-files/sites
SF_DB_PATH=/var/lib/kleo-static-files/data/static-files.db
SF_CADDY_SNIPPET=/etc/caddy/sites.d/static-files.caddy
SF_BIND_IPS=YOUR_SERVER_IP

# Limits
SF_RATE_LIMIT_WINDOW=60000
SF_RATE_LIMIT_MAX=100
SF_MAX_FILE_MB=50
```

### 4. Create Directories

```bash
sudo mkdir -p /var/lib/kleo-static-files/{data,sites}
sudo mkdir -p /etc/caddy/sites.d
sudo mkdir -p /var/log/caddy
```

### 5. Update Caddyfile

Add to `/etc/caddy/Caddyfile`:

```caddy
import /etc/caddy/sites.d/*.caddy
```

### 6. Create Systemd Service

Create `/etc/systemd/system/kleo-static-files.service`:

```ini
[Unit]
Description=Kleo Static Files API
After=network.target caddy.service

[Service]
Type=simple
WorkingDirectory=/opt/kleo-static-files
EnvironmentFile=/opt/kleo-static-files/.env
ExecStart=/root/.bun/bin/bun run server/index.ts
ExecStartPost=/opt/kleo-static-files/scripts/sync-caddy.ts --reload
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
```

### 7. Start Service

```bash
sudo systemctl daemon-reload
sudo systemctl enable kleo-static-files
sudo systemctl start kleo-static-files
```

### 8. Create API Key

```bash
cd /opt/kleo-static-files
source .env
bun run scripts/create-key.ts "admin"
# Save the key!
```

## DNS Setup

For each subdomain to work, configure a wildcard DNS record:

| Type | Name | Value |
|------|------|-------|
| A | *.yourdomain.com | YOUR_SERVER_IP |
| AAAA | *.yourdomain.com | YOUR_IPV6 (optional) |

## Verification

```bash
# Check service
systemctl status kleo-static-files

# Check API
curl http://localhost:3000/health

# Test site creation
export SF_API_URL=http://localhost:3000
export SF_API_KEY=sk_your_key
sf sites create test
curl -I https://test.yourdomain.com
```

## Uninstall

```bash
sudo /opt/kleo-static-files/install.sh --uninstall
```

```



---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### _meta.json

```json
{
  "owner": "awaaate",
  "slug": "kleo-static-files",
  "displayName": "Kleo Static files",
  "latest": {
    "version": "1.0.0",
    "publishedAt": 1769885567722,
    "commit": "https://github.com/clawdbot/skills/commit/ec71a5e9000eda73893b312f110acb6410df15c6"
  },
  "history": []
}

```

### scripts/sf-helper.sh

```bash
#!/bin/bash
#
# sf-helper.sh - Static Files helper for AI agents
#
# Provides high-level operations that combine multiple sf commands.
#
# Usage: sf-helper.sh <command> [args]
#

set -e

# Ensure sf is available (it's just the CLI)
SF_CLI="${SF_CLI:-sf}"

# Check environment
check_env() {
  if [ -z "$SF_API_URL" ] || [ -z "$SF_API_KEY" ]; then
    echo "Error: SF_API_URL and SF_API_KEY must be set"
    echo ""
    echo "Example:"
    echo "  export SF_API_URL=http://localhost:3000"
    echo "  export SF_API_KEY=sk_xxxxx"
    exit 1
  fi
}

# Deploy a directory as a new site
# Usage: sf-helper.sh deploy <site-name> <directory> [--auth user:pass]
cmd_deploy() {
  local site="$1"
  local dir="$2"
  local auth="$3"

  if [ -z "$site" ] || [ -z "$dir" ]; then
    echo "Usage: sf-helper.sh deploy <site-name> <directory> [user:pass]"
    exit 1
  fi

  if [ ! -d "$dir" ]; then
    echo "Error: Directory not found: $dir"
    exit 1
  fi

  echo "Deploying $dir to $site..."

  # Create site if it doesn't exist
  if ! $SF_CLI sites list --json 2>/dev/null | grep -q "\"name\":\"$site\""; then
    echo "Creating site: $site"
    $SF_CLI sites create "$site"
  fi

  # Set auth if provided
  if [ -n "$auth" ]; then
    echo "Setting authentication..."
    $SF_CLI sites auth "$site" "$auth"
  fi

  # Upload directory
  echo "Uploading files..."
  $SF_CLI upload "$dir" "$site" --overwrite

  echo ""
  echo "Deployed! URL: https://$site.$SF_DOMAIN"
}

# Clean deploy - delete existing files before uploading
# Usage: sf-helper.sh clean-deploy <site-name> <directory>
cmd_clean_deploy() {
  local site="$1"
  local dir="$2"

  if [ -z "$site" ] || [ -z "$dir" ]; then
    echo "Usage: sf-helper.sh clean-deploy <site-name> <directory>"
    exit 1
  fi

  echo "Clean deploying $dir to $site..."

  # Delete and recreate site
  $SF_CLI sites delete "$site" 2>/dev/null || true
  $SF_CLI sites create "$site"

  # Upload
  $SF_CLI upload "$dir" "$site"

  echo ""
  echo "Deployed! URL: https://$site.$SF_DOMAIN"
}

# Quick share - upload a single file and return URL
# Usage: sf-helper.sh share <file> [site-name]
cmd_share() {
  local file="$1"
  local site="${2:-quick-share}"

  if [ -z "$file" ]; then
    echo "Usage: sf-helper.sh share <file> [site-name]"
    exit 1
  fi

  if [ ! -f "$file" ]; then
    echo "Error: File not found: $file"
    exit 1
  fi

  # Create site if needed
  if ! $SF_CLI sites list --json 2>/dev/null | grep -q "\"name\":\"$site\""; then
    $SF_CLI sites create "$site" >/dev/null
  fi

  # Upload and get URL
  local filename=$(basename "$file")
  $SF_CLI upload "$file" "$site" --overwrite >/dev/null

  echo "https://$site.${SF_DOMAIN:-498as.com}/$filename"
}

# List all sites with their URLs
# Usage: sf-helper.sh list
cmd_list() {
  local domain="${SF_DOMAIN:-498as.com}"
  
  echo "Sites:"
  echo ""
  
  $SF_CLI sites list --json 2>/dev/null | \
    grep -o '"name":"[^"]*"' | \
    cut -d'"' -f4 | \
    while read -r site; do
      echo "  https://$site.$domain"
    done
}

# Show help
cmd_help() {
  cat << EOF
sf-helper.sh - Static Files helper for AI agents

Commands:
  deploy <site> <dir> [user:pass]  Deploy directory to site
  clean-deploy <site> <dir>        Delete all files and deploy fresh
  share <file> [site]              Quick share a single file
  list                             List all sites with URLs

Environment:
  SF_API_URL   API endpoint (required)
  SF_API_KEY   API key (required)
  SF_DOMAIN    Domain for URLs (default: 498as.com)

Examples:
  sf-helper.sh deploy docs ./build
  sf-helper.sh deploy private ./files admin:secret123
  sf-helper.sh share ./report.pdf
  sf-helper.sh clean-deploy mysite ./dist
EOF
}

# Main
check_env

case "${1:-help}" in
  deploy) shift; cmd_deploy "$@" ;;
  clean-deploy) shift; cmd_clean_deploy "$@" ;;
  share) shift; cmd_share "$@" ;;
  list) cmd_list ;;
  help|--help|-h) cmd_help ;;
  *) echo "Unknown command: $1"; cmd_help; exit 1 ;;
esac

```