Skip to content

flashcatcloud/flashduty-runner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

139 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Flashduty Runner

Go Lint Release Go Report Card License

English | δΈ­ζ–‡

Flashduty Runner is a lightweight, secure agent that runs in your environment to execute commands and access resources on behalf of Flashduty AI SRE platform.

How It Works

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”       WebSocket (TLS)       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Flashduty AI    β”‚ ◄─────────────────────────► β”‚  Flashduty Runner  β”‚
β”‚  SRE Platform    β”‚                             β”‚  (Your Server)     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                             β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                          β”‚
                                                          β–Ό
                                                 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                                 β”‚ β€’ Execute Commands β”‚
                                                 β”‚ β€’ Read/Write Files β”‚
                                                 β”‚ β€’ MCP Tool Calls   β”‚
                                                 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The runner establishes a persistent WebSocket connection to Flashduty cloud, receives task requests, executes them locally, and returns results.

Security

All code is open source - you can audit every line of code to verify exactly what the runner does.

Multi-layer Security Design

Layer Protection
Transport TLS-encrypted WebSocket, token authentication
Command Execution Shell parsing to prevent injection attacks (e.g., cmd1; cmd2)
Permission Control Configurable glob-based command whitelist/blacklist
File System Operations sandboxed to workspace root, symlink escape protection

Permission Configuration

The runner uses glob pattern matching for command permissions. You have full control over what commands can be executed.

Option 1: Strict Mode (Recommended for shared environments)

Only allow specific commands explicitly:

permission:
  bash:
    "*": "deny"                  # Deny all by default
    "kubectl get *": "allow"
    "kubectl describe *": "allow"
    "kubectl logs *": "allow"
    "cat *": "allow"
    "ls *": "allow"

Option 2: Trust Mode (For dedicated/isolated environments)

If the runner is deployed in an isolated environment dedicated to AI operations, you can choose to trust the AI model's judgment:

permission:
  bash:
    "*": "allow"                 # Trust AI model
    "rm -rf /": "deny"           # Block catastrophic commands if desired

This mode is suitable when:

  • The runner runs in an isolated VM/container with limited blast radius
  • You trust the AI model's capabilities and want maximum flexibility
  • Quick incident response is more important than restrictive permissions

Option 3: Read-Only Mode (For monitoring only)

permission:
  bash:
    "*": "deny"
    "cat *": "allow"
    "head *": "allow"
    "tail *": "allow"
    "ls *": "allow"
    "grep *": "allow"
    "ps *": "allow"
    "df *": "allow"
    "free *": "allow"

Quick Start

One-line Install / Update (Linux + macOS)

# Install or update (prompts for token if not already set)
curl -fsSL https://raw.githubusercontent.com/flashcatcloud/flashduty-runner/main/install.sh | sudo bash

# Non-interactive (pass token on the sudo line)
curl -fsSL https://raw.githubusercontent.com/flashcatcloud/flashduty-runner/main/install.sh | sudo TOKEN=wnt_xxx bash

# Pin a specific version
curl -fsSL https://raw.githubusercontent.com/flashcatcloud/flashduty-runner/main/install.sh | sudo VERSION=v0.0.5 bash

# Uninstall (keeps /etc/flashduty-runner/ config)
curl -fsSL https://raw.githubusercontent.com/flashcatcloud/flashduty-runner/main/install.sh | sudo bash -s -- --uninstall

# Uninstall and wipe everything (binary, config, workspace, service user)
curl -fsSL https://raw.githubusercontent.com/flashcatcloud/flashduty-runner/main/install.sh | sudo bash -s -- --purge

On Linux with systemd the script also creates a flashduty service user, writes /etc/flashduty-runner/env, installs a hardened unit, and runs systemctl enable --now. On macOS and non-systemd Linux it installs the binary only. Run with --help for all flags.

Runners upgrade themselves regardless of how they were installed. Flashduty pushes new releases over the runner's existing control channel; the runner verifies the download, atomically swaps its binary, and restarts into the new version β€” automatically rolling back if the new build can't reconnect within a probation window. When the runner's own directory is writable (the installer's /var/lib/flashduty-runner/bin layout, or any user-writable location), the swap happens in place. When it is not β€” e.g. a manual install in root-owned /usr/local/bin run as a regular user β€” the upgrade lands at the canonical state-home path (<runner home>/bin/flashduty-runner, default ~/.flashduty/bin/) instead, and on every later start the original binary hands off to the newest canonical version automatically. One consequence of that fallback: the file in /usr/local/bin keeps its installed timestamp/version on disk, while flashduty-runner version and the running service always reflect the current version.

The auto-update download URL is chosen by the backend, not remembered from how the runner was installed (the install-time MIRROR_URL is never persisted). A self-hosted or air-gapped deployment that installs via a private mirror must therefore also point the backend's install_script_url at that same mirror, or backend-pushed upgrades will resolve from the public GitHub release host.

Manual Binary Installation

# Linux (amd64)
curl -LO https://github.com/flashcatcloud/flashduty-runner/releases/latest/download/flashduty-runner_Linux_x86_64.tar.gz
tar -xzf flashduty-runner_Linux_x86_64.tar.gz
sudo mv flashduty-runner /usr/local/bin/

# Linux (arm64)
curl -LO https://github.com/flashcatcloud/flashduty-runner/releases/latest/download/flashduty-runner_Linux_arm64.tar.gz
tar -xzf flashduty-runner_Linux_arm64.tar.gz
sudo mv flashduty-runner /usr/local/bin/

# macOS (Apple Silicon)
curl -LO https://github.com/flashcatcloud/flashduty-runner/releases/latest/download/flashduty-runner_Darwin_arm64.tar.gz
tar -xzf flashduty-runner_Darwin_arm64.tar.gz
sudo mv flashduty-runner /usr/local/bin/

# macOS (Intel)
curl -LO https://github.com/flashcatcloud/flashduty-runner/releases/latest/download/flashduty-runner_Darwin_x86_64.tar.gz
tar -xzf flashduty-runner_Darwin_x86_64.tar.gz
sudo mv flashduty-runner /usr/local/bin/

Auto-upgrade works here too. A root-owned binary in /usr/local/bin cannot replace itself in place, so the first backend-pushed upgrade is installed to the runner's writable state home (~/.flashduty/bin/flashduty-runner by default) and the process restarts into it; from then on, starting /usr/local/bin/flashduty-runner transparently hands off to the newest self-updated version. To pin the installed version instead, run with --disable-auto-update.

Docker Installation

docker run -d \
  --name flashduty-runner \
  -e FLASHDUTY_RUNNER_TOKEN=ent_xxx \
  -v /var/flashduty/workspace:/workspace \
  registry.flashcat.cloud/public/flashduty-runner:latest

# With custom endpoint
docker run -d \
  --name flashduty-runner \
  -e FLASHDUTY_RUNNER_TOKEN=ent_xxx \
  -e FLASHDUTY_RUNNER_URL=wss://custom.example.com/safari/environment/ws \
  -v /var/flashduty/workspace:/workspace \
  registry.flashcat.cloud/public/flashduty-runner:latest

Running

# Basic usage (token required)
flashduty-runner run --token ent_xxx

# Specify workspace directory
flashduty-runner run --token ent_xxx --workspace ~/projects

# Specify custom WebSocket endpoint
flashduty-runner run --token ent_xxx --url wss://custom.example.com/safari/environment/ws

# Check version
flashduty-runner version

Systemd Service (Linux)

Create /etc/systemd/system/flashduty-runner.service:

[Unit]
Description=Flashduty Runner
After=network.target

[Service]
Type=simple
User=flashduty
EnvironmentFile=/etc/flashduty-runner/env
ExecStart=/usr/local/bin/flashduty-runner run
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Create /etc/flashduty-runner/env:

FLASHDUTY_RUNNER_TOKEN=ent_xxx
# FLASHDUTY_RUNNER_URL=wss://custom.example.com/safari/environment/ws
# FLASHDUTY_RUNNER_HOME=/var/flashduty
sudo mkdir -p /etc/flashduty-runner
sudo vim /etc/flashduty-runner/env   # add your token
sudo systemctl daemon-reload
sudo systemctl enable --now flashduty-runner

Skills

Skills are materialized lazily. When the agent calls the skill tool, the cloud sends sync_skill with (skill_name, checksum, zip_data?):

  • Empty zip_data = probe. The runner returns {cached: true, path} if <home>/skills/<name>/.checksum already matches the requested checksum and SKILL.md is present; otherwise {cached: false} and the cloud will retry with the bundle attached.
  • Non-empty zip_data = install. The runner wipes <home>/skills/<name>/, unzips, and writes .checksum. Each skill name has exactly one slot β€” no version retention. Builtin skills go through the same flow with their bundle sourced from the cloud's embedded FS instead of S3.

Inspect installed skills with ls ~/.flashduty/skills/.

Configuration Reference

Configuration is via command-line flags or environment variables (flags take precedence).

Flag Env Variable Required Default Description
--token FLASHDUTY_RUNNER_TOKEN Yes - Authentication token
--url FLASHDUTY_RUNNER_URL No wss://api.flashcat.cloud/safari/environment/ws WebSocket endpoint
--workspace FLASHDUTY_RUNNER_HOME No ~/.flashduty Runner home directory. Skills land at <home>/skills/<name>/. FLASHDUTY_RUNNER_WORKSPACE is accepted as a deprecated alias for back-compat.
--log-level FLASHDUTY_RUNNER_LOG_LEVEL No info Log level: debug, info, warn, error

Troubleshooting

Connection Issues

Symptom Cause Solution
failed to connect Network issue Check firewall allows outbound port 443
authentication failed Invalid token Verify token in Flashduty console
Runner not showing online Connection dropped Check logs, verify token matches account
# Test connectivity
curl -v https://api.flashcat.cloud/health

# Check runner logs
journalctl -u flashduty-runner -f

Permission Issues

Symptom Cause Solution
command denied Command not in whitelist Add pattern to permission.bash
path escapes workspace Path traversal blocked Use paths within workspace_root

Permission Pattern Rules:

  • Patterns are matched in order, last match wins
  • * matches any characters
  • Empty config defaults to deny all

Debug Mode

Enable debug logging to see detailed permission decisions:

flashduty-runner run --token ent_xxx --log-level debug

# Or via environment variable
export FLASHDUTY_RUNNER_LOG_LEVEL=debug

Contributing

We welcome contributions! Please see CONTRIBUTING.md.

License

Apache License 2.0 - see LICENSE.


Made with ❀️ by Flashcat

About

The Runner for Flashduty AI SRE πŸš€

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages