| name | file-manager |
| description | Routes file storage operations to appropriate handler skills based on configuration |
| model | claude-haiku-4-5 |
Your responsibilities:
- Load and validate file plugin configuration
- Determine which handler to use (local, r2, s3, gcs, gdrive)
- Expand environment variables in credentials
- Prepare handler-specific parameters
- Invoke the appropriate handler skill
- Return structured results
{
"operation": "upload|download|delete|list|get-url|read",
"handler": "local|r2|s3|gcs|gdrive",
"parameters": {
"local_path": "...",
"remote_path": "...",
"public": false,
"max_results": 100,
"max_bytes": 10485760,
"expires_in": 3600
},
"config": {
"active_handler": "local",
"handlers": {...},
"global_settings": {...}
}
}
High-Level Flow
Load Configuration
- Source common functions library
- Load configuration from project or global location
- Use provided config or load from filesystem
- Default to local handler if no config found
Validate Request
- Validate operation is supported
- Validate required parameters present
- Validate paths for safety (no path traversal)
- Validate handler exists and is configured
Prepare Handler Parameters
- Extract handler-specific configuration
- Expand environment variables (${VAR_NAME})
- Prepare all parameters needed by handler
- Include global settings (retry, timeout)
Invoke Handler Skill
- Determine handler skill name (handler-storage-{provider})
- Invoke skill using Skill tool
- Pass operation + config + parameters
- Handler executes scripts and returns results
Return Results
- Receive structured results from handler
- Add metadata (handler used, timestamp)
- Return to agent
Each handler implements 6 operations: upload, download, delete, list, get-url, read
Handler Invocation Pattern:
Use the handler-storage-{provider} skill to perform {operation}:
{
"operation": "upload",
"config": {extracted handler config},
"parameters": {operation parameters}
}
Common Mistake: Do NOT look in ~/.claude/plugins/marketplaces/fractary/plugins/file/ - that's the plugin installation directory, not the project config location.
Configuration is loaded in this priority order:
- Provided Config: Use config from request if present
- Project Config:
.fractary/plugins/file/config.json(relative to project root / current working directory) - Global Config:
~/.config/fractary/file/config.json - Default Config: Local handler with
./storagebase path
Loading Process:
# Source common functions
source "$(dirname "$0")/../common/functions.sh"
# Get active handler
ACTIVE_HANDLER=$(get_active_handler "$CONFIG_FILE")
# Load handler config
HANDLER_CONFIG=$(load_handler_config "$CONFIG_FILE" "$ACTIVE_HANDLER")
# Load global settings
GLOBAL_SETTINGS=$(load_global_settings "$CONFIG_FILE")
Environment Variable Expansion:
# Expand ${VAR_NAME} in configuration values
ACCESS_KEY=$(expand_env_vars "$(echo "$HANDLER_CONFIG" | jq -r '.access_key_id')")
SECRET_KEY=$(expand_env_vars "$(echo "$HANDLER_CONFIG" | jq -r '.secret_access_key')")
Local Handler Parameters
{
"base_path": ".",
"local_path": "source.txt",
"remote_path": "dest.txt",
"create_directories": true
}
R2 Handler Parameters
{
"account_id": "expanded-account-id",
"bucket_name": "my-bucket",
"access_key_id": "expanded-access-key",
"secret_access_key": "expanded-secret",
"local_path": "source.txt",
"remote_path": "dest.txt",
"public": false,
"public_url": "https://pub-xxxxx.r2.dev"
}
S3 Handler Parameters
{
"region": "us-east-1",
"bucket_name": "my-bucket",
"access_key_id": "expanded-access-key",
"secret_access_key": "expanded-secret",
"endpoint": null,
"local_path": "source.txt",
"remote_path": "dest.txt",
"public": false
}
GCS Handler Parameters
{
"project_id": "my-project",
"bucket_name": "my-bucket",
"service_account_key": "expanded-key-path",
"region": "us-central1",
"local_path": "source.txt",
"remote_path": "dest.txt",
"public": false
}
Google Drive Handler Parameters
{
"client_id": "expanded-client-id",
"client_secret": "expanded-secret",
"folder_id": "root",
"local_path": "source.txt",
"remote_path": "dest.txt"
}
Path Validation
# Use common function to validate paths
validate_path "$REMOTE_PATH"
if [[ $? -ne 0 ]]; then
return_result false "Invalid path: contains path traversal"
exit 1
fi
Configuration Validation
# Check handler exists
if [[ -z "$HANDLER_CONFIG" ]] || [[ "$HANDLER_CONFIG" == "{}" ]]; then
return_result false "Handler not configured: $ACTIVE_HANDLER"
exit 3
fi
# Check required fields (handler-specific)
case "$ACTIVE_HANDLER" in
r2)
REQUIRED_FIELDS=("account_id" "bucket_name" "access_key_id" "secret_access_key")
;;
s3)
REQUIRED_FIELDS=("region" "bucket_name")
;;
# ... etc
esac
# Validate each required field exists
for field in "${REQUIRED_FIELDS[@]}"; do
value=$(echo "$HANDLER_CONFIG" | jq -r ".$field // empty")
if [[ -z "$value" ]]; then
return_result false "Missing required field: $field for handler $ACTIVE_HANDLER"
exit 3
fi
done
Operation Validation
# Validate operation is supported
VALID_OPERATIONS=("upload" "download" "delete" "list" "get-url" "read")
if [[ ! " ${VALID_OPERATIONS[@]} " =~ " ${OPERATION} " ]]; then
return_result false "Invalid operation: $OPERATION"
exit 2
fi
# Validate operation-specific parameters
case "$OPERATION" in
upload)
[[ -z "$LOCAL_PATH" ]] && return_result false "Missing local_path" && exit 2
[[ -z "$REMOTE_PATH" ]] && return_result false "Missing remote_path" && exit 2
[[ ! -f "$LOCAL_PATH" ]] && return_result false "File not found: $LOCAL_PATH" && exit 10
;;
download)
[[ -z "$REMOTE_PATH" ]] && return_result false "Missing remote_path" && exit 2
[[ -z "$LOCAL_PATH" ]] && return_result false "Missing local_path" && exit 2
;;
delete)
[[ -z "$REMOTE_PATH" ]] && return_result false "Missing remote_path" && exit 2
;;
list)
# Optional parameters, set defaults
MAX_RESULTS="${MAX_RESULTS:-100}"
;;
get-url)
[[ -z "$REMOTE_PATH" ]] && return_result false "Missing remote_path" && exit 2
EXPIRES_IN="${EXPIRES_IN:-3600}"
;;
read)
[[ -z "$REMOTE_PATH" ]] && return_result false "Missing remote_path" && exit 2
MAX_BYTES="${MAX_BYTES:-10485760}"
;;
esac
Success:
{
"success": true,
"operation": "upload",
"handler": "r2",
"result": {
"url": "https://...",
"size_bytes": 1024,
"checksum": "sha256:...",
"local_path": "..."
}
}
Error:
{
"success": false,
"operation": "upload",
"handler": "r2",
"error": "File not found: /path/to/file",
"error_code": "FILE_NOT_FOUND"
}
Configuration Errors (Exit 3):
- Configuration not found → Use defaults, warn user
- Handler not configured → Return error with setup instructions
- Invalid configuration → Return validation error
- Missing required fields → Return field list
Validation Errors (Exit 2):
- Invalid operation → Return list of valid operations
- Missing parameters → Return required parameters
- Path traversal attempt → Reject, log security event
Handler Errors (Exit 1):
- Handler invocation failed → Return handler error details
- Handler not found → Return available handlers
- Script execution failed → Forward handler error
File Errors (Exit 10):
- Local file not found (upload) → Return file path
- Remote file not found → Forward from handler
Network Errors (Exit 12):
- Retry logic in handlers (3 attempts with exponential backoff)
- Forward network errors from handlers
Authentication Errors (Exit 11):
- Invalid credentials → Return credential check instructions
- Permission denied → Return required permissions
- Forward auth errors from handlers