{
  "markdown": "# FURLOW\n\n**Declarative Discord Bot Framework**\n\n[![Maintained by @virgilvox](https://img.shields.io/badge/maintained%20by-%40virgilvox-5865F2)](https://github.com/virgilvox)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nBuild powerful Discord bots with YAML. No code required.\n\n```yaml\ncommands:\n  - name: ping\n    description: Check bot latency\n    actions:\n      - reply:\n          content: \"Pong! ${client.ws.ping}ms\"\n```\n\n## Features\n\n- **85 Actions**: messages, moderation, voice, channels, and more\n- **71 Expression Functions**: date, math, string, array manipulation\n- **50 Transforms**: pipe-based data transformations\n- **59 Events** across Discord gateway, voice transitions, component interactions, and high-level FURLOW events (automod, scheduler, pipes)\n- **Scoped State**: global, guild, channel, user, and member scopes\n- **Flows**: reusable action sequences with parameters\n- **External Integrations**: HTTP, WebSocket, MQTT, TCP/UDP, webhooks\n\n## Quick Start\n\n```bash\n# Install the CLI\nnpm install -g @furlow/cli\n\n# Create a bot\nfurlow init my-bot\ncd my-bot\n\n# Add your Discord credentials to .env\necho \"DISCORD_TOKEN=your_token_here\" > .env\necho \"DISCORD_CLIENT_ID=your_client_id_here\" >> .env\n\n# Start\nfurlow start\n```\n\n## Example\n\n```yaml\nversion: \"0.1\"\n\nidentity:\n  name: \"My Bot\"\n\npresence:\n  status: online\n  activity:\n    type: playing\n    text: \"with FURLOW\"\n\ncommands:\n  - name: hello\n    description: Greet someone\n    options:\n      - name: user\n        type: user\n        description: Who to greet\n    actions:\n      - reply:\n          content: \"Hello, ${options.user.display_name || options.user.username}!\"\n\n  - name: roll\n    description: Roll a dice\n    options:\n      - name: sides\n        type: integer\n        description: Number of sides\n        min_value: 2\n        max_value: 100\n    actions:\n      - reply:\n          content: \"🎲 You rolled **${random(1, options.sides || 6)}**\"\n\nevents:\n  - event: member_join\n    actions:\n      - send_message:\n          channel: \"${env.WELCOME_CHANNEL}\"\n          content: \"Welcome ${member.displayName}!\"\n```\n\n## CLI Commands\n\n| Command | Description |\n|---------|-------------|\n| `furlow init [name]` | Create a new bot project |\n| `furlow start [path]` | Run the bot |\n| `furlow dev [path]` | Development mode with hot reload |\n| `furlow validate <path>` | Validate YAML specification |\n| `furlow add <builtin>` | Add builtin module |\n| `furlow build [path]` | Bundle for deployment |\n| `furlow export <path>` | Export Discord command JSON |\n\n## Documentation\n\n| Guide | Description |\n|-------|-------------|\n| [Installation](docs/guides/installation.md) | Setup and requirements |\n| [Quick Start](docs/guides/quickstart.md) | Your first bot |\n| [Configuration](docs/guides/configuration.md) | YAML specification |\n| [Actions Reference](docs/reference/actions/) | All 85 actions |\n| [Expressions Reference](docs/reference/expressions/) | Functions and transforms |\n| [Events Reference](docs/reference/events.md) | Event types |\n| [CLI Reference](docs/reference/cli.md) | Command-line interface |\n| [Pipes Reference](docs/packages/pipes/README.md) | External integrations |\n| [Examples](docs/examples/) | Complete bot examples |\n\n## Packages\n\n| Package | Description |\n|---------|-------------|\n| `furlow` | CLI tool |\n| `@furlow/core` | Runtime engine |\n| `@furlow/discord` | Discord.js adapter |\n| `@furlow/schema` | TypeScript types |\n| `@furlow/storage` | Database adapters |\n| `@furlow/builtins` | Pre-built modules |\n| `@furlow/pipes` | HTTP, WebSocket, MQTT, TCP/UDP, webhooks, database, file |\n| `@furlow/testing` | Test utilities |\n\n## Production deployment\n\nA short checklist for shipping a bot to production. Each item lines up with\na runtime guarantee — skipping one usually shows up later as silent data\nloss, an unscheduled feature, or a publicly forgeable session.\n\n### Required environment\n\n```bash\n# Discord\nDISCORD_TOKEN=...\nDISCORD_CLIENT_ID=...\n\n# Storage (pick one)\nDATABASE_URL=postgres://user:pass@host:5432/furlow   # production\n# or for single-server bots:\nSQLITE_PATH=/var/lib/furlow/bot.db\n\n# Dashboard (only if running the web UI)\nDASHBOARD_SECRET=$(openssl rand -hex 32)             # required in NODE_ENV=production\nDISCORD_CLIENT_SECRET=...\nDISCORD_CALLBACK_URL=https://dashboard.example.com/auth/discord/callback\n```\n\nThe dashboard refuses to start in `NODE_ENV=production` without\n`DASHBOARD_SECRET` — there is no fallback default. WebSocket connections\nalso require an authenticated session; unauthenticated clients are rejected\nat upgrade time and cannot subscribe to guild streams.\n\n### Storage\n\n- Use Postgres for any deployment that runs more than one process or needs\n  point-in-time recovery. The SQLite adapter is fine for single-server bots\n  and tests, but write contention degrades quickly past a few thousand\n  active users.\n- Run database migrations on deploy. The SQLite adapter creates tables on\n  demand; Postgres deployments should pre-create the tables defined in your\n  `state.tables:` block.\n- Back up the database. Builtins persist real state (warnings, levels, AFK\n  status, ticket transcripts); none of this is reconstructible.\n\n### Scheduling and voice\n\n- The CLI starts a `CronScheduler` that emits `scheduler_tick` every 60s.\n  Builtins that rely on it (`giveaways`, `polls`, `reminders`) need the\n  scheduler running — there is no separate cron process.\n- Voice playback requires the `@discordjs/voice` peer plus `ffmpeg` on the\n  PATH. The `voice_track_start` / `voice_track_end` events used by the\n  `music` builtin only fire when the voice manager is initialized.\n\n### Process supervision\n\n- Run `furlow start` under a process supervisor (`systemd`, `pm2`,\n  Kubernetes Deployment) that restarts on exit. The bot does not\n  self-daemonize.\n- Forward `SIGTERM` so the gateway connection closes cleanly. The CLI\n  flushes pending state on shutdown; killing with `SIGKILL` can lose the\n  last batched writes.\n\n### Dashboard hardening\n\n- Terminate TLS in front of the dashboard (nginx, Caddy, a load balancer).\n  The session cookie sets `secure: true` in production and will not be\n  delivered over plain HTTP.\n- Restrict the OAuth callback URL in the Discord developer portal to the\n  exact `DISCORD_CALLBACK_URL` you ship.\n- POST endpoints whitelist their accepted fields and reject unknown or\n  wrong-typed keys with 400. If you extend a settings shape, update the\n  whitelist in `apps/dashboard/server/routes/api.ts`.\n\n### Observability\n\n- `/health` returns process uptime; wire it to your liveness probe.\n- `/metrics` exposes Prometheus-format counters. Add a scrape job pointed\n  at the dashboard process.\n- The CLI honors `--verbose` for structured per-event logging during\n  incident triage.\n\n## License\n\nMIT\n",
  "bytes": 6819,
  "sha": "eed78210a5c3be3432923a10beade7cbf520e3c9c9d880b6ce340f9c988d6526",
  "repo_slug": "virgilvox/discord-furlow",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_virgilvox_furlow_mcp_b218bd6b/readme"
}