twitch-miner-go

module
v1.25.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 6, 2026 License: GPL-3.0

README ยถ

twitch-miner-go - Efficient Auto Drops & Points Claim for Twitch

GitHub Stars CI Latest Release Release Date Go Version Created At License

A high-performance Go rewrite of the Twitch Channel Points Miner v2. Mines channel points, claims bonuses, places predictions, joins raids, claims drops, and more โ€” all with a fraction of the resource usage.

โญ Star this repo to bookmark it and get notified about new releases โ€” the project is young, actively developed, and the best time to jump in is now.

1.1. Table of Contents

1.2. Features

  • ๐Ÿ‘ฅ Multi-account support โ€” run multiple Twitch accounts from a single binary; configs can be stored as YAML files or in a PostgreSQL database (hot-reloaded without restart)
  • โ›๏ธ Channel points mining โ€” automatic minute-watched events, bonus claims, watch streaks
  • ๐Ÿ”ฎ Predictions โ€” configurable betting strategies (SMART, HIGH_ODDS, MOST_VOTED, etc.)
  • ๐Ÿ“ฆ Drops โ€” automatic campaign sync and drop claiming
  • โš”๏ธ Raids โ€” automatic raid joining
  • ๐ŸŽ‰ Community moments โ€” automatic moment claiming
  • ๐ŸŽฏ Community goals โ€” automatic goal contributions
  • ๐ŸŽ Gift sub detection โ€” notifies when your account receives a gifted subscription
  • ๐Ÿท๏ธ Category watcher โ€” auto-discover streamers by game category
  • ๐Ÿค Team watcher โ€” auto-discover streamers by Twitch team membership
  • โญ Followers mode โ€” automatically watch all followed channels
  • ๐Ÿ”” Notifications โ€” Telegram, Discord, Webhook, Matrix, Pushover, Gotify
  • ๐Ÿšจ Lifecycle alerts โ€” start, stop, and crash notifications with version info
  • ๐Ÿ“Š Analytics dashboard โ€” built-in web UI for monitoring; see also twitch-miner-go-dashboard for a full management UI (DB mode)
  • ๐Ÿš€ Fly.io ready โ€” deploy with a single command; Docker Compose and systemd service also supported

1.3. Resource Comparison

Resource ๐Ÿ Python ๐Ÿน Go Go advantage
Memory >250 MB (spikes) ~80 MB (stable) 3ร— less
Docker image 200โ€“500 MB ~12 MB 20โ€“40ร— smaller
Startup time 5โ€“10 s ~2โ€“3 s 2โ€“4ร— faster
Streamer loading ~4 500 ms / 5 streamers ~260 ms / 5 streamers (concurrent) ~17ร— faster
OS threads 60+ ~4โ€“5 / ~25 goroutines 12ร— fewer

Impressed by the difference? A โญ star helps the next person find this instead of running the bloated Python image. Already using the miner? That one click keeps you in the loop for what ships next.

1.4. Running Locally

Prerequisites: Go 1.25+

Unix (macOS/Linux):

./_run.sh

Windows:

_run.bat

With custom flags:

./_run.sh -config configs -port 9090 -log-level debug

The scripts build the binary and run it in one step. You can also build manually with go build -o twitch-miner-go ./cmd/twitch-miner-go.

Console window: _run.sh / _run.bat pass -no-console, so on Windows the terminal window hides once the miner is running (bring it back with tray menu Show Terminal). Use _run-localdev.sh / _run-localdev.bat for local development โ€” they keep the console visible and add dev-friendly flags (-no-lifecycle-notify -skip-unauth -no-banner).

1.4.1. Flags
Flag Default Description
-config configs Path to the configuration directory
-port 8080 Port for the health/analytics server
-log-level INFO Log level: DEBUG, INFO, WARN, ERROR (effective default: INFO)
-log-format text Output format: text (colored logfmt) or json (structured, Stdout and files)
-log-dir (none) Enable file logging; write .log files named with startup timestamp to this directory
-healthcheck-url (none) Probe the given HTTP URL and exit 0 on HTTP 200
-version false Print version and exit
-auto-update false Download and apply the latest release automatically on startup
-no-lifecycle-notify false Suppress MINER_STARTED, MINER_STOPPED, MINER_CRASHED notifications for this run
-skip-unauth false Skip accounts with no valid credentials instead of prompting for device code login
-no-banner false Suppress the startup banner animation
-log-no-time false Omit timestamps in console logs (useful when the platform adds its own, e.g. Fly.io)
-config-editor-port 8070 Port for the embedded config editor (bound to localhost only)
-no-tray false Disable the system tray icon (e.g. headless/service environments)
-no-console false Hide the console window on startup (Windows only; used by autostart entries and the _run scripts, which pass it by default)

1.5. Configuration

Create one YAML file per account in the configs/ directory. The filename (without extension) becomes the Twitch username โ€” no username field is needed in the YAML.

For example, to add an account for Twitch user guliveer_, create configs/guliveer_.yaml.

# Copy the example and customize for your account
cp configs/example.yaml.example configs/your_twitch_username.yaml

See configs/example.yaml.example for the full schema. Files with a .yaml.example extension are not loaded as configs โ€” only .yaml and .yml files are loaded.

Prefer a GUI? Run tools\edit-config.bat (Windows) or ./tools/edit-config.sh (Linux/macOS) to open a visual config editor in your browser. No additional runtimes required โ€” the editor is a self-contained Go binary. See Config Editor below for details.

After cloning: The repository includes the maintainer's own account configs (e.g. guliveer_.yaml). These are skipped automatically unless RUN_OWNER_ACCOUNTS=true is set โ€” so they will not run on your machine and you do not need to delete or disable them. Just create your own config from the example template.

1.5.1. Quick Start
# configs/your_twitch_username.yaml
# The filename IS the username โ€” no username field needed.

# Set 'false' to disable this account without deleting the config (default: true)
enabled: true

features:
  claim_drops_startup: false
  enable_analytics: true

max_watch_streams: 2

# While any live channel still owes a watch streak, the watch set narrows to
# this many streams so the streak actually lands (Twitch only credits about two
# concurrent streams; a wider set lets Twitch pick and no streak sticks).
# Each channel holds its slot until the streak arrives or watch_streak_minutes
# elapse, then the next pending channel takes over. Set to 0 to disable.
#
# Collected streaks are persisted to {DATA_DIR}/streaks/{account}.json, keyed by
# broadcast ID, so a restart does not spend slot time chasing streaks Twitch has
# already paid out. A channel that starts a new broadcast is chased again.
streak_watch_streams: 2
watch_streak_minutes: 10

# Channels the PREFERRED priority picks first, in this order.
preferred_streamers:
  - jimpanse
  - insym

priority:
  - STREAK
  - PREFERRED
  - DROPS
  - ORDER

streamer_defaults:
  make_predictions: true
  follow_raid: true
  claim_drops: true
  claim_moments: true
  watch_streak: true
  community_goals: false
  chat: "ONLINE"
  bet:
    strategy: "SMART"
    percentage: 5
    max_points: 50000
    delay: 6
    delay_mode: "FROM_END"

streamers:
  - username: "streamer1"
  - username: "streamer2"
    settings:
      make_predictions: false

# Blacklisted streamers excluded even if followed
blacklist:
  - "unwanted_streamer"

# Follow mode โ€” also watch all followed channels
followers:
  enabled: false
  order: "ASC"
1.5.2. Config Editor

The twitch-miner-go binary itself embeds the config editor. When the miner is running in file mode, the editor is always available at http://localhost:8070 (bound to localhost only โ€” no other device on your network can reach it), so you can manage account configs while the miner is running without a separate program. In DB mode the editor is not started (port 8070 stays closed) โ€” account configs are managed via the REST API and twitch-miner-go-dashboard instead.

On Windows, Linux and macOS desktops a system tray icon is shown with quick links: left-click opens the dashboard, right-click shows a menu with Dashboard, Config Editor (hidden in DB mode), a Service submenu (install/start/stop/ restart/status/uninstall, delegating to the platform installer script), a Startup submenu (start on logon, start at boot via the service installer), Hide/Show Terminal (Windows only, toggles the terminal window), and Exit (to stop the miner gracefully). The tray is skipped automatically when running as a Windows service (session 0 has no desktop) or when -no-tray is set. The embedded editor's port can be changed with -config-editor-port. Note that on macOS the tray requires cgo, so the binary must be built with cgo enabled (release binaries build it on a macOS runner; see Auto-Update).

The config editor is also available as a separate self-contained Go binary for environments where the full miner isn't needed:

  • Web GUI (default) โ€” opens a browser-based editor at http://localhost:3000
  • TUI โ€” interactive terminal forms, no browser required

Quick start:

# Windows
tools\edit-config.bat

# Linux / macOS
./tools/edit-config.sh

The script builds the binary on first run (requires Go), then launches it. The web editor opens automatically in your browser and reads/writes YAML files directly in configs/.

Options:

Flag Default Description
--config configs/ Path to the config directory
--port 3000 Port for the web server
--tui (off) Launch TUI mode instead of the web server
--no-browser (off) Web mode: don't auto-open the browser

TUI mode provides an interactive terminal interface โ€” useful in headless environments or when a browser isn't available:

./tools/edit-config.sh --tui
# or
config-editor --tui --config /path/to/configs

Note: In file mode the miner hot-reloads YAML changes automatically โ€” no restart needed. See Database Mode for the PostgreSQL-backed alternative.

1.5.3. Database Mode (optional)

By default the miner loads account configs from YAML files. You can optionally store them in a PostgreSQL database instead โ€” useful when managing accounts programmatically via REST API (e.g. from a dashboard) without file system access.

Enable DB mode:

DB_ENABLED=true
DB_DSN=postgresql://user:password@host:5432/dbname?sslmode=require

The schema and migrations run automatically on first connection (via goose).

Note: In DB mode the embedded config editor is not started (port 8070 stays closed) and the tray menu does not offer Config Editor โ€” account configs are managed exclusively through the database.

Migrate existing YAML configs to DB:

go run ./cmd/db-seed              # seed from configs/ (default)
go run ./cmd/db-seed --dry-run    # preview without writing
go run ./cmd/db-seed --config /path/to/configs

How it works: The Poller watches the accounts table using PostgreSQL LISTEN/NOTIFY (instant) and a periodic ticker (default 30s). When a row changes, the corresponding miner is started, restarted, or stopped automatically. Changes via the REST API (POST/PUT/DELETE /api/accounts) are picked up within milliseconds.

REST API endpoints (only available when DB_ENABLED=true):

Method Endpoint Description
GET /api/accounts List all accounts (username, enabled, updated_at, last_started_at)
POST /api/accounts Create account (body: full config JSON)
GET /api/accounts/{username} Get single account with full config
PUT /api/accounts/{username} Update account config
DELETE /api/accounts/{username} Delete account

All endpoints return 501 Not Implemented when DB_ENABLED=false. Auth follows the same HTTP Basic Auth as the dashboard (DASHBOARD_USER / DASHBOARD_PASSWORD_SHA256).

Config Generation API (always available):

Method Endpoint Description
GET /api/config/schema Returns validation schema and default values
POST /api/config/validate Validates config JSON without saving (body: AccountConfig JSON)
POST /api/config/generate Generates YAML from config JSON (body: AccountConfig JSON)

These endpoints are used by twitch-miner-go-dashboard to generate config files server-side, ensuring format consistency with the Go parser. The generate endpoint returns:

{
  "username": "alice",
  "filename": "alice.yaml",
  "yaml": "enabled: true\nfeatures:\n  claim_drops_startup: false\n...",
  "generated_at": "2025-01-15T10:30:00Z"
}

twitch-miner-go-dashboard โ€” a dedicated management UI for DB mode: add, edit, and disable accounts without touching YAML files or the API directly.

1.6. Environment Variables

Secrets and auth tokens are injected via environment variables. Per-account variables use a _<USERNAME> suffix (uppercase) to scope them to the correct account. Notification secrets also support a global fallback โ€” if the per-account variable is not set, the miner checks for the key without the suffix (e.g. TELEGRAM_TOKEN), allowing all accounts to share one notification channel.

Use the configs/ directory for per-account behavior such as watched streamers, betting strategy, and feature toggles. Use environment variables or .env for secrets and global runtime values that should not be duplicated per account.

For example, for user guliveer_ the Telegram token variable is TELEGRAM_TOKEN_GULIVEER_ and the auth token variable is TWITCH_AUTH_TOKEN_GULIVEER_.

๐Ÿ“ก Telemetry notice: This project collects anonymous usage data by default โ€” instance ID, version, OS, architecture, and running account count โ€” to track adoption and prioritize development. No personal data, channel names, IP addresses, or identifying information is sent. To disable, set TELEMETRY_AGREE=false in your environment.

The instance ID is a random UUID v4 generated on first run and persisted in DATA_DIR/.instance_id โ€” the same instance keeps the same ID across restarts. The file is created hidden and read-only, so it is never overwritten while the ID stays stable. When running in Docker or on Fly.io, ensure DATA_DIR is a mounted/persistent volume so the ID survives container rebuilds.

Source code for the telemetry server: github.com/Guliveer/twitch-miner-go-telemetry

1.6.1. Global
Variable Description Default
LOG_LEVEL Log level (DEBUG, INFO, WARN, ERROR) INFO
LOG_FORMAT Output format: text (colored logfmt) or json (structured, Stdout and files) text
LOG_NO_TIME Set to true to omit timestamps in console logs (avoids duplication when the platform adds timestamps, e.g. Fly.io) false
SKIP_UNAUTH Set to true to skip accounts with no valid credentials instead of prompting for device code login false
NO_BANNER Set to true to suppress the startup banner animation false
NO_TRAY Set to true to disable the system tray icon (headless/service/container environments) false
LOG_DIR Enable file logging; directory for .log files named with startup timestamp. In Docker use a path under the /data volume (e.g. /data/logs) โ€” a relative path lands in the container layer and is lost on redeploy. Files are not rotated. (disabled)
PORT HTTP server port for health/analytics 8080
DATA_DIR Persistent data directory (cookies, state) .
TWITCH_CLIENT_ID_TV Twitch TV client ID (falls back to built-in default if unset; override recommended) built-in default
TWITCH_CLIENT_ID_BROWSER Twitch browser client ID (falls back to built-in default if unset; override recommended) built-in default
TWITCH_CLIENT_VERSION Twitch browser client version (falls back to built-in default if unset; override recommended) built-in default
TWITCH_CLIENT_ID_MOBILE Twitch mobile web client ID (falls back to built-in default if unset) built-in default
TWITCH_CLIENT_ID_ANDROID Twitch Android client ID (falls back to built-in default if unset) built-in default
TWITCH_CLIENT_ID_IOS Twitch iOS client ID (falls back to built-in default if unset) built-in default
DASHBOARD_USER Username for analytics dashboard HTTP basic auth (disabled)
DASHBOARD_PASSWORD_SHA256 SHA-256 hash of the dashboard password (none)
RUN_OWNER_ACCOUNTS Set to true to also run the maintainer's own account configs included in the repository false
DB_ENABLED Set to true to use PostgreSQL-backed account store instead of YAML files false
DB_DSN PostgreSQL connection string (required when DB_ENABLED=true) (unset)
DB_POLL_INTERVAL How often the DB Poller syncs when no NOTIFY is received (e.g. 30s, 2m) 30s
FILE_POLL_INTERVAL How often the file watcher checks configs/ for YAML changes (file mode only) 5s
TELEMETRY_AGREE Set to false to disable anonymous telemetry heartbeats (enabled by default) true
TELEMETRY_URL Override the compiled-in telemetry server URL (forks running their own server) (compiled-in)
HEARTBEAT_API_KEY API key for the telemetry server heartbeat endpoint (X-API-Key header) (none)
TELEMETRY_INTERVAL How often to send heartbeats (e.g. 30m, 1h, 2h) 10m
COOKIE_ENCRYPTION_KEY Base64-encoded 32-byte AES-256 key for encrypting cookie values at rest (optional) (disabled)

Note: Twitch client IDs and versions have compiled-in defaults (from internal/constants) that are used when the corresponding environment variables are unset. These defaults may become stale as Twitch updates their clients, so it is recommended to set these environment variables explicitly.

1.6.2. Per-Account Authentication
Variable Description
TWITCH_AUTH_TOKEN_<USERNAME> OAuth token (fallback for headless auth)
TWITCH_PASSWORD_<USERNAME> Twitch password (last-resort auth, may require 2FA)
1.6.3. Notification Secrets

Notification credentials support two levels: global (KEY) and per-account (KEY_<USERNAME>). Per-account takes precedence โ€” if set, the global value is ignored for that account. Use global variables to send all accounts' notifications to a single channel.

Global variable Per-account override Description
TELEGRAM_TOKEN TELEGRAM_TOKEN_<USERNAME> Telegram bot token
TELEGRAM_CHAT_ID TELEGRAM_CHAT_ID_<USERNAME> Telegram chat ID
DISCORD_WEBHOOK DISCORD_WEBHOOK_<USERNAME> Discord webhook URL
WEBHOOK_URL WEBHOOK_URL_<USERNAME> Generic webhook URL
MATRIX_HOMESERVER MATRIX_HOMESERVER_<USERNAME> Matrix homeserver URL
MATRIX_ROOM_ID MATRIX_ROOM_ID_<USERNAME> Matrix room ID
MATRIX_ACCESS_TOKEN MATRIX_ACCESS_TOKEN_<USERNAME> Matrix access token
PUSHOVER_TOKEN PUSHOVER_TOKEN_<USERNAME> Pushover API token
PUSHOVER_USER_KEY PUSHOVER_USER_KEY_<USERNAME> Pushover user key
GOTIFY_URL GOTIFY_URL_<USERNAME> Gotify server URL
GOTIFY_TOKEN GOTIFY_TOKEN_<USERNAME> Gotify app token
1.6.4. .env File Support

The project supports loading environment variables from a .env file at startup using joho/godotenv. This is optional โ€” if no .env file is present, the app runs normally using YAML configs and/or standard environment variables.

Environment variables (whether from .env or the system) override the corresponding values from YAML config files for notification secrets only. This allows you to keep sensitive tokens out of version-controlled YAML files.

Example .env file:

# Global
LOG_LEVEL=DEBUG
PORT=9090

# Required Twitch runtime identifiers
TWITCH_CLIENT_ID_TV=your_tv_client_id
TWITCH_CLIENT_ID_BROWSER=your_browser_client_id
TWITCH_CLIENT_VERSION=your_client_version

# Optional Twitch client identifiers for future compatibility
TWITCH_CLIENT_ID_MOBILE=your_mobile_client_id
TWITCH_CLIENT_ID_ANDROID=your_android_client_id
TWITCH_CLIENT_ID_IOS=your_ios_client_id

# Global notification secrets (shared by all accounts)
TELEGRAM_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
TELEGRAM_CHAT_ID=987654321

# Per-account override (this account uses a different chat)
# TELEGRAM_CHAT_ID_GULIVEER_=111222333
# DISCORD_WEBHOOK_GULIVEER_=https://discord.com/api/webhooks/...

See .env.example for the starter template.

1.6.4.1. How To Obtain Twitch Runtime Identifiers

The safest way to obtain these values is from real Twitch client requests that you control. Do not assume older values stay valid forever.

Browser values

  1. Open https://www.twitch.tv in your browser.
  2. Open DevTools and go to the Network tab.
  3. Filter for gql.
  4. Open a request to https://gql.twitch.tv/gql.
  5. Copy these request headers:
    • Client-Id -> TWITCH_CLIENT_ID_BROWSER
    • Client-Version -> TWITCH_CLIENT_VERSION

TV client ID without owning a TV

You do not need a physical television. Practical options:

  1. Use an Android TV emulator and inspect Twitch app traffic with a local proxy.
  2. Use an Android phone emulator and the Twitch TV/device-login flow if you already proxy mobile traffic.
  3. Reuse the TV client ID from a previously working setup and only replace it when Twitch invalidates it.

For this project today, the most important runtime values are:

  • TWITCH_CLIENT_ID_TV
  • TWITCH_CLIENT_ID_BROWSER
  • TWITCH_CLIENT_VERSION

The mobile and platform-specific IDs are kept for future compatibility, but the current runtime path depends primarily on the TV and browser values.

Cookie files store authentication tokens in plaintext by default. You can optionally encrypt cookie values at rest using AES-256-GCM.

Setup:

# Generate an encryption key
./tools/gen-cookie-key.sh

# Add the key to your .env file
echo 'COOKIE_ENCRYPTION_KEY=<generated_key>' >> .env

Behavior:

  • Without COOKIE_ENCRYPTION_KEY โ€” cookies are stored and loaded as plaintext (default, unchanged behavior).
  • With COOKIE_ENCRYPTION_KEY โ€” cookie values are encrypted when saved and transparently decrypted when loaded. Existing plaintext cookie files are automatically migrated to encrypted on the first save after enabling encryption.

Note: The encryption key is a Base64-encoded 32-byte AES-256 key. Generate it with ./tools/gen-cookie-key.sh or openssl rand -base64 32. Keep this key safe โ€” losing it means losing access to stored cookies (you will need to re-authenticate).

1.7. Notifications

The miner supports multiple notification providers. Configure them in your account YAML file under the notifications key. Sensitive credentials (tokens, API keys) are injected via environment variables โ€” see Notification Secrets above.

1.7.1. Supported Providers
Provider Config key Required env vars
Telegram telegram TELEGRAM_TOKEN_*, TELEGRAM_CHAT_ID_*
Discord discord DISCORD_WEBHOOK_*
Gotify gotify GOTIFY_URL_*, GOTIFY_TOKEN_*
Pushover pushover PUSHOVER_TOKEN_*, PUSHOVER_USER_KEY_*
Matrix matrix MATRIX_HOMESERVER_*, MATRIX_ROOM_ID_*, MATRIX_ACCESS_TOKEN_*
Webhook webhook WEBHOOK_URL_*

* = _<USERNAME> suffix (uppercase) or global (without suffix). Per-account takes precedence. For example, TELEGRAM_TOKEN_GULIVEER_ overrides TELEGRAM_TOKEN. See the full variable list in Notification Secrets.

1.7.2. Example: Telegram
notifications:
  telegram:
    enabled: true
    token: "YOUR_BOT_TOKEN"
    chat_id: "YOUR_CHAT_ID"
    events:
      - "DROP_CLAIM"
      - "DROP_STATUS"
      - "STREAMER_ONLINE"
      - "STREAMER_OFFLINE"
      - "BET_WIN"
      - "BET_LOSE"
    disable_notification: false

Tip: The token and chat_id fields in YAML are optional โ€” if omitted, the miner reads them from TELEGRAM_TOKEN_<USERNAME> and TELEGRAM_CHAT_ID_<USERNAME> environment variables instead. This is the recommended approach for production/headless deployments.

1.7.3. Event Filtering

The events list controls which events trigger a notification for a given provider. Events are configured per notification provider in the YAML config under notifications > {provider} > events.

  • If the events list is empty or omitted, all events are sent to that provider.
  • If specific events are listed, only those events trigger notifications for that provider.

Available events:

Event Emoji Description
STREAMER_ONLINE ๐ŸŸข Streamer goes online
STREAMER_OFFLINE โšซ Streamer goes offline
GAIN_FOR_RAID ๐Ÿ’ต Points gained from a raid
GAIN_FOR_CLAIM ๐Ÿ’ต Points gained from claiming bonus
GAIN_FOR_WATCH ๐Ÿ’ต Points gained from watching
GAIN_FOR_WATCH_STREAK ๐Ÿ’ต Points gained from watch streak
BET_WIN ๐Ÿ† Prediction bet won
BET_LOSE ๐Ÿ’ธ Prediction bet lost
BET_REFUND โ†ฉ๏ธ Prediction bet refunded
BET_FILTERS ๐ŸŽฐ Prediction filtered by settings
BET_GENERAL ๐ŸŽฐ General prediction info
BET_FAILED ๐ŸŽฐ Prediction bet failed
BET_START ๐ŸŽฐ Prediction started
BONUS_CLAIM ๐Ÿ’ต Bonus claimed
MOMENT_CLAIM ๐ŸŽ‰ Community moment claimed
JOIN_RAID โš”๏ธ Joined a raid
DROP_CLAIM ๐Ÿ“ฆ Drop claimed
DROP_CLAIM_AVAILABLE ๐Ÿ“ฆ Drop available to claim (one-time notification per drop)
DROP_STATUS ๐Ÿ“ฆ Drop progress status
CHAT_MENTION ๐Ÿ’ฌ Mentioned in chat
GIFTED_SUB ๐ŸŽ Received a gifted sub (via IRC)
MINER_STARTED ๐Ÿš€ Miner started (with version info)
MINER_STOPPED ๐Ÿ›‘ Miner stopped gracefully
MINER_CRASHED ๐Ÿ’ฅ Miner crashed (with error details); miner auto-restarts with exponential backoff
ACCOUNT_CONFIG_RELOADED ๐Ÿ”„ Account config changed in DB or YAML and miner was restarted (DB mode and file mode)
TEST โ€” Test notification (see below)

Note: Emojis are prepended to log messages and notifications automatically. The emoji mappings are defined in eventEmoji. The event type constants are defined in internal/model/settings.go.

Note: Lifecycle events (MINER_STARTED, MINER_STOPPED, MINER_CRASHED, ACCOUNT_CONFIG_RELOADED) are always sent immediately โ€” they bypass notification batching entirely.

Note: Use --no-lifecycle-notify flag to suppress MINER_STARTED, MINER_STOPPED, and MINER_CRASHED for a single run โ€” useful when restarting the process frequently (e.g. during deploys).

Example โ€” send only specific events to Telegram:

notifications:
  telegram:
    enabled: true
    token: "..."
    chat_id: "..."
    events:
      - "GIFTED_SUB"
      - "BET_WIN"
      - "BET_LOSE"
      - "DROP_CLAIM"
1.7.4. Notification Batching

Instead of receiving a separate notification for every single event, you can enable batching to group events by streamer or category and deliver them as a single message at a configurable interval.

Global defaults with per-provider overrides:

notifications:
  batch:
    enabled: true
    interval: 30m # flush buffered events every 30 minutes
    max_entries: 15 # max lines per message; splits into multiple if exceeded
    immediate_events: # these bypass batching (empty list = batch everything)
      - "BET_WIN"
      - "BET_LOSE"
      - "DROP_CLAIM"

  discord:
    enabled: true
    batch:
      interval: 15m # override: Discord flushes every 15 minutes
  telegram:
    enabled: true
    batch:
      enabled: false # override: Telegram sends instantly

How it works:

  • Events are grouped by their notification title (e.g. oliwer | xQc, oliwer | Valorant).
  • At each interval, all buffered events for a group are joined as newline-separated lines and sent as one message.
  • If a single event arrives in a batch window, it is sent as a regular (unbatched) message.
  • If the buffer exceeds max_entries, the message is split into multiple sends.
  • On graceful shutdown, all pending batched events are flushed before the process exits.
  • Events listed in immediate_events are always sent instantly, bypassing the buffer.
  • If immediate_events is empty or omitted, all events are batched.
  • Per-provider batch config overrides the global defaults. Omitted fields inherit from global.
1.7.5. Testing Notifications

The miner exposes a POST /api/test-notification endpoint on the analytics server to verify your notification setup. It sends a test message to all enabled notification providers, bypassing event filters.

curl -X POST http://localhost:8080/api/test-notification

A successful response looks like:

{
  "status": "ok",
  "message": "Test notification sent to all enabled notifiers"
}

If some providers fail, you'll get a partial status with error details:

{
  "status": "partial",
  "errors": ["telegram: 401 Unauthorized"]
}

Note: Replace 8080 with your configured port (the -port flag or PORT env var). This endpoint is useful for verifying that tokens, chat IDs, and webhook URLs are correctly configured before relying on notifications in production.

1.8. Authentication

Authentication is automatic โ€” on first run the miner walks through a priority chain until one method succeeds:

Priority Method Description
1 Cookie file Saved from a previous successful login. Reused automatically. If expired, a refresh token flow is attempted first.
2 Auth token from config Token set directly in the YAML config file (auth_token field).
3 TWITCH_AUTH_TOKEN_* env Fallback โ€” read via os.Getenv().
4 TWITCH_PASSWORD_* env Last resort โ€” password login via os.Getenv(). May require 2FA.
5 Device code flow Interactive โ€” displays a code in the terminal and waits for activation at twitch.tv/activate. (RECOMMENDED)

Once authenticated, the token is validated against the Twitch OAuth2 endpoint to confirm it belongs to the expected user (derived from the config filename). If there's a mismatch โ€” for example, you completed the device code flow with the wrong Twitch account โ€” the system will show a clear error like:

authenticated as "wrong_user" but config expects "your_username" โ€” please log in with the correct account

The validated token is then saved to a cookie file and reused on subsequent starts โ€” so the device code flow is typically a one-time step.

See internal/auth/auth.go for the full authentication implementation.

Warning: Password login (priority 4) may trigger Twitch's two-factor authentication (2FA) prompt, making it less reliable in fully headless environments. Prefer TWITCH_AUTH_TOKEN_<USERNAME> over TWITCH_PASSWORD_<USERNAME> whenever possible. Use the password method only as a last resort when you cannot obtain an OAuth token.

1.8.1. When to use the env vars

The TWITCH_AUTH_TOKEN_<USERNAME> env var is the recommended fallback when the interactive device code flow is impractical:

  • Headless deployments โ€” servers or containers without interactive terminal access (e.g., Fly.io, Docker hosts, cloud VMs)
  • Multi-account setups โ€” pre-seed tokens for several accounts without running the device flow for each
  • CI/CD environments โ€” automated pipelines where no human is present to complete the device flow

The variable name is TWITCH_AUTH_TOKEN_ followed by the uppercase username with hyphens replaced by underscores. Examples:

Username Env var
guliveer_ TWITCH_AUTH_TOKEN_GULIVEER_
my-user TWITCH_AUTH_TOKEN_MY_USER

Note: Both TWITCH_AUTH_TOKEN_<USERNAME> and TWITCH_PASSWORD_<USERNAME> are read directly in the auth flow (os.Getenv()), not through the config layer or applyEnvOverrides().

1.9. Docker

# Build
docker build -t twitch-miner-go .

# Run (DATA_DIR is required to persist cookies across container restarts)
docker run -d \
  -p 8080:8080 \
  -v miner_data:/data \
  -v $(pwd)/configs:/configs:ro \
  -e DATA_DIR=/data \
  --env-file .env \
  twitch-miner-go

# Run with auth token (recommended โ€” for headless environments)
docker run -d \
  -p 8080:8080 \
  -v miner_data:/data \
  -v $(pwd)/configs:/configs:ro \
  -e DATA_DIR=/data \
  --env-file .env \
  -e TWITCH_AUTH_TOKEN_YOUR_USERNAME=your_oauth_token \
  twitch-miner-go

# Run with password (optional โ€” last resort, may require 2FA)
docker run -d \
  -p 8080:8080 \
  -v miner_data:/data \
  -v $(pwd)/configs:/configs:ro \
  -e DATA_DIR=/data \
  --env-file .env \
  -e TWITCH_PASSWORD_YOUR_USERNAME=your_twitch_password \
  twitch-miner-go
1.9.1. Docker Compose
docker compose up -d

The included docker-compose.yml uses the published GHCR image by default:

ghcr.io/guliveer/twitch-miner-go:latest

Set TWITCH_MINER_IMAGE in .env if you want to pin a version or use a different registry/tag.

The compose setup mounts:

  • ./configs to /configs as read-only account configuration
  • a named volume to /data for cookies and persisted session state
  • .env for required Twitch client identifiers, dashboard auth, and account secrets
1.9.2. GitHub Container Registry

This repository publishes Docker images to GHCR with GitHub Actions.

  • main pushes publish latest and a short SHA tag
  • version tags such as v1.2.3 publish 1.2.3 and 1.2

Example image references:

  • ghcr.io/guliveer/twitch-miner-go:latest
  • ghcr.io/guliveer/twitch-miner-go:1.2.3
  • ghcr.io/guliveer/twitch-miner-go:sha-abcdef1

1.10. Linux Service (systemd / OpenRC)

Run twitch-miner-go as a native Linux service with automatic restarts and boot startup. The interactive installer auto-detects the init system (systemd or OpenRC/Alpine).

# Build the binary first
./_run.sh   # Ctrl+C after build completes

# Run the installer wizard
sudo ./tools/install-service.sh install

The wizard will prompt for service name, paths, port, user, and optionally enable + start the service.

1.10.1. Managing the Service
# systemd
systemctl status twitch-miner-go
systemctl restart twitch-miner-go
journalctl -u twitch-miner-go -f     # follow logs

# OpenRC (Alpine)
rc-service twitch-miner-go status
rc-service twitch-miner-go restart
tail -f /var/log/twitch-miner-go.log  # follow logs
1.10.2. Uninstalling
sudo ./tools/install-service.sh uninstall
1.10.3. Default File Locations
Item Path
Binary /usr/local/bin/twitch-miner-go
Configs /etc/twitch-miner-go/configs/
Environment /etc/twitch-miner-go/.env
Data (cookies) /var/lib/twitch-miner-go/

See DEPLOYMENT.md for the full Linux service deployment guide.

1.11. Windows Service

Run twitch-miner-go as a Windows service with automatic restarts. The binary is rebuilt from source on every start, so config and code changes are always picked up. Uses NSSM (auto-downloaded if not installed).

REM Right-click and select "Run as administrator"
tools\install-service.bat install

The wizard will prompt for config directory, port, and log level.

1.11.1. Managing the Service
tools\install-service.bat start       REM starts (rebuilds the binary first)
tools\install-service.bat stop
tools\install-service.bat restart     REM restart with a fresh rebuild
tools\install-service.bat status
1.11.2. Uninstalling
tools\install-service.bat uninstall

See DEPLOYMENT.md for the full Windows service deployment guide.

1.12. Deploy to Fly.io

The repo includes fly.toml โ€” the Fly.io deployment config. Fly.io is a personal preference and comes pre-configured, but the miner is portable and runs on any platform that supports Go (AWS, GCP, Azure, DigitalOcean, etc.).

1.12.1. Setup
# 1. Copy the example account config and customize (filename = your Twitch username)
cp configs/example.yaml.example configs/your_twitch_username.yaml

# 2. Install flyctl
curl -L https://fly.io/install.sh | sh

# 3. Login
fly auth login

# 4. Create the app (first time only)
fly launch --no-deploy

# 5. Create a volume for persistent data
fly volumes create miner_data --region fra --size 1

# 6. Set required Twitch runtime identifiers
fly secrets set TWITCH_CLIENT_ID_TV=your_tv_client_id
fly secrets set TWITCH_CLIENT_ID_BROWSER=your_browser_client_id
fly secrets set TWITCH_CLIENT_VERSION=your_client_version

# 7. (Optional) Set auth token for headless login โ€” skips the interactive device code flow (recommended)
fly secrets set TWITCH_AUTH_TOKEN_YOUR_USERNAME=your_oauth_token

# 8. (Optional) Set password for last-resort login โ€” less reliable than auth token, may require 2FA
fly secrets set TWITCH_PASSWORD_YOUR_USERNAME=your_twitch_password

# 9. Set notification secrets (replace YOUR_USERNAME with your Twitch username in uppercase)
fly secrets set TELEGRAM_TOKEN_YOUR_USERNAME=your_bot_token
fly secrets set TELEGRAM_CHAT_ID_YOUR_USERNAME=your_chat_id
1.12.2. CI/CD Auto-Deploy

Pushes to main are automatically deployed via the CI workflow after build and version bump succeed. This requires a FLY_API_TOKEN GitHub secret:

# 1. Generate a deploy token scoped to your app
flyctl tokens create deploy -a twitch-miner-go

# 2. Set it as a GitHub repo secret
gh secret set FLY_API_TOKEN --repo <owner>/<repo>
# (paste the token when prompted)

If FLY_API_TOKEN is not set, the deployment step is skipped gracefully โ€” build and version bump still run normally.

1.12.3. Manual Deploy
fly deploy

# View logs
fly logs

# Check health
curl https://your-app-name.fly.dev/health
1.12.4. Alternative Deployment

For self-hosted deployments, Docker Compose is also supported โ€” see the Docker Compose section above and DEPLOYMENT.md for a comprehensive guide covering both Fly.io and Docker workflows.

1.13. Development

This project uses Conventional Commits and automated versioning. See CONTRIBUTING.md for the full commit convention, git hooks setup, and versioning workflow.

1.14. Auto-Update

On startup, the miner automatically checks for new releases in the background. If a newer version is available, a notification is printed to the terminal. This check is non-blocking and does not affect startup time.

1.14.1. Automatic updates

Pass -auto-update to have the miner download and apply the update itself:

./_run.sh -auto-update

When a new release is detected:

  1. The platform-specific binary is downloaded from GitHub Releases.
  2. The current binary is replaced atomically.
  3. The process exits with code 0 โ€” your service manager (systemd, NSSM, OpenRC) restarts it automatically with the new binary.

If the download or replacement fails (e.g. no write permission, Docker read-only filesystem), the miner continues running and prints the usual update notification instead.

To enable in a systemd unit, add -auto-update to ExecStart:

ExecStart=/usr/local/bin/twitch-miner-go -config /etc/twitch-miner-go/configs -auto-update

To enable in a Windows NSSM service, re-run the installer or edit the service arguments in NSSM GUI to include -auto-update.

Note: Auto-update is opt-in and disabled by default. It is not useful for Docker or Fly.io deployments where the image is the unit of update.

1.15. License

This project is licensed under the GNU GPL v3.0 License. See the LICENSE file for details.

1.16. FAQ

Quick answers to the questions users ask most. A more detailed version โ€” with longer walk-throughs and context โ€” lives in the project wiki FAQ.

Can I use this without installing Go?

Yes. To run the miner, download the release binary for your OS from GitHub Releases. Go is only required when you build from source (_run.sh / _run.bat) or build the standalone config editor (tools/edit-config.sh / .bat).

Do I have to log in in the terminal on first run?

That is the device-code flow โ€” it prints a code to activate at twitch.tv/activate and only needs to be done once; the token is then saved to a cookie and reused. On headless servers (Docker, Fly.io, VPS) set TWITCH_AUTH_TOKEN_<USERNAME> instead โ€” see Authentication.

What are `configs/guliveer_.yaml` and `guliveer_2.yaml`?

Those are the repo owner's own account configs. They are skipped by default and will not run on your machine unless you set RUN_OWNER_ACCOUNTS=true. You can leave them or delete them.

How do I add another account?

Create a file named configs/<your_twitch_username>.yaml. The filename (minus extension) is the username โ€” no username field needed. The file watcher picks up the new file and starts the miner automatically; no restart required.

I edited my YAML and nothing happened.

Hot-reload is on by default. Make sure you actually saved the file โ€” the log shows config changed, restarting miner on change. If the config is invalid or the account is disabled (enabled: false), the change is skipped or the miner is stopped with a message in the log.

How do I disable an account without deleting its config?

Set enabled: false in that account's YAML. The watcher stops the miner and it won't restart; keep the file for later.

How do I open the editor without the terminal?

While the miner is running in file mode, the editor is always at http://localhost:8070 (localhost only; not started in DB mode). Or right-click the system tray icon โ†’ Config Editor (hidden in DB mode). A standalone editor also exists: tools/edit-config.sh / .bat (web on :3000, or --tui).

Why don't I see the tray icon?

Several causes: running as a Windows service (session 0 has no desktop), running headless/in a container (Docker, Fly.io), an explicit -no-tray / NO_TRAY=true, or โ€” on macOS โ€” a binary built without cgo (release binaries build on a macOS runner, so this is automatic). See Config Editor.

Can I change the editor port?

Yes โ€” pass -config-editor-port <port> (default 8070). The tray links use the same port automatically. There is no environment variable for it.

What is `.instance_id` and why don't I see it in the folder?

It is an anonymous telemetry instance ID. The file is created hidden and read-only (on Unix the leading dot hides it; on Windows the Hidden attribute is set), so it is easy to miss in a file browser. It lives in DATA_DIR (defaults to .). Leave it alone if you want a stable ID across restarts. You can disable telemetry entirely with TELEMETRY_AGREE=false.

Does the program send my data anywhere?

Anonymous telemetry is on by default: instance ID, version, OS, architecture, and the number of running accounts โ€” no usernames, channel names, IPs, or tokens. Source is public. Disable with TELEMETRY_AGREE=false. See Environment Variables.

Why do I lose my configs/accounts after a Docker restart?

Your configs (/configs) and data (/data) are volumes. Cookies, state and the instance ID must live on a persistent volume (-v miner_data:/data), or they vanish on rebuild. See Docker and the wiki FAQ for details.

Why does it peak at ~80 MB RAM when the Python miner needs >250 MB?

Go is compiled and memory-efficient; the miner runs on a handful of OS threads instead of dozens. See the comparison table.

1.17. Advanced Guide

Everything you need to go beyond the FAQ โ€” how the strategies, connection limits, background loops, recovery and storage actually work under the hood. The full, code-accurate deep-dive lives in the project wiki: Advanced Guide.

How do prediction strategies like SMART, HIGH_ODDS and MOST_VOTED decide?

MOST_VOTED bets the outcome with the most voters, HIGH_ODDS the highest odds, PERCENTAGE the highest odds percentage, and SMART_MONEY the highest "top predictor" points. SMART (the default) is a hybrid โ€” it picks high odds only when the field is close, otherwise it plays the crowd. An unknown strategy string falls back to SMART.

What do `delay` and `delay_mode` actually control?

The bet waits delay seconds before being placed, and delay_mode decides what is measured from: FROM_START (N seconds after the window starts), FROM_END (N seconds before it ends, default), or PERCENTAGE (delay as a fraction of the window duration).

Can I filter which predictions I bet on?

Yes โ€” bet accepts filter conditions that target an outcome field (e.g. outcomePercentage, totalVotes) with a comparison operator and threshold. Predictions that fail the filter are skipped (BET_FILTERS).

How does the miner "watch" a stream?

It does not play video. It sends minute-watched events on a fixed cadence (20 s). Each tick it selects up to max_watch_streams streamers (applying your priority list) and sends the watch event for each โ€” so the watch credit keeps flowing while branches run concurrently.

How often are streamers checked for being online?

A monitor loop checks each streamer on a randomised 20โ€“60 s interval (jittered to avoid hammering Twitch's API on a fixed cadence).

How often are drops synced and what happens each sync?

Every 10 minutes the miner claims everything claimable from inventory first, then pulls the drop dashboard, keeps only in-window campaigns with unclaimed drops, cross-references inventory for progress, and pre-populates campaign IDs for streamers with drops enabled.

What are vanished, synthetic, and duplicate drops?

A vanished drop is missing from inventory across 3 polls โ€” it is flagged so claims are not retried against a transient API glitch. A synthetic drop is one a campaign advertises but never lands in inventory โ€” it is marked so the miner stops treating it as claimable. Duplicate definitions across campaigns are deduped; Twitch marks the rest claimed server-side.

Why do some drops fail with "PRECONDITIONS_NOT_MET"?

The drop needs an external account link first (e.g. a game account connected to Twitch). It is not a bug โ€” claim it after linking, and the miner logs a clear hint.

How many streams can I watch before connections split?

Each PubSub WebSocket holds up to 50 topics; the pool opens more connections up to a maximum of 10. With two topics per streamer (channel-points + video-playback), a single connection covers ~25 streamers and the pool handles far more.

What keeps PubSub alive and resurrects it?

A PING is sent every 4 minutes; missing a PONG for 5+ minutes tears the dead connection down. A server RECONNECT closes and reopens it. Duplicate messages (identical identifier + timestamp) are dropped on reconnect. On ERR_BADAUTH the connection refreshes its token and re-subscribes.

What happens in detail when a miner crashes?

The manager restarts it with exponential backoff โ€” 10 s, 20 s, 40 s โ€ฆ capped at 5 minutes โ€” and dispatches MINER_CRASHED. A clean stop (config disabled) unwinds without restarting; ErrSkippedUnauth also gives up (no point retrying headless).

Why does editing config restart only that account?

The file watcher mtime-compares each YAML and calls RestartChanged(username), stopping only the changed account's miner and starting it fresh โ€” other accounts keep running.

How is my cookie/token stored, and can it be encrypted?

Tokens are stored in a cookie file reused on later starts, plaintext by default. Set COOKIE_ENCRYPTION_KEY (Base64 32-byte AES-256 key) to encrypt at rest with AES-256-GCM; existing cookies migrate on the first save. Losing the key loses access to the cookies.

What is the difference between file mode and DB mode?

File mode watches YAML files for changes. DB mode (DB_ENABLED=true) stores configs in PostgreSQL, reacting via LISTEN/NOTIFY plus a 30 s fallback ticker, and exposes the REST /api/accounts endpoints (these return 501 in file mode).

Why is the analytics port separate from the config editor port?

-port (default 8080) serves the analytics dashboard โ€” optionally behind your own HTTP basic auth. -config-editor-port (default 8070) serves the embedded editor, bound to localhost only, never exposed to the network.


The hand-held explanations live in the wiki. For the internal package map and data flow, see Architecture.

Directories ยถ

Path Synopsis
cmd
config-editor command
db-seed command
db-seed loads YAML account configs and upserts them into the database.
db-seed loads YAML account configs and upserts them into the database.
twitch-miner-go command
Command miner is the entry point for the Twitch Channel Points Miner.
Command miner is the entry point for the Twitch Channel Points Miner.
internal
auth
Package auth handles Twitch authentication, cookie persistence, and credential management for the miner.
Package auth handles Twitch authentication, cookie persistence, and credential management for the miner.
config
Package config handles loading, parsing, and validating YAML configuration files for the Twitch miner.
Package config handles loading, parsing, and validating YAML configuration files for the Twitch miner.
constants
Package constants defines all Twitch API endpoints, client identifiers, GQL operation hashes, user-agent strings, PubSub topic formats, and default timeout/interval values used throughout the miner.
Package constants defines all Twitch API endpoints, client identifiers, GQL operation hashes, user-agent strings, PubSub topic formats, and default timeout/interval values used throughout the miner.
encryption
Package encryption provides AES-256-GCM encryption and decryption for sensitive values stored on disk.
Package encryption provides AES-256-GCM encryption and decryption for sensitive values stored on disk.
gql
Package gql provides a typed GraphQL client for the Twitch GQL API.
Package gql provides a typed GraphQL client for the Twitch GQL API.
jsonutil
Package jsonutil provides helper functions for extracting typed values from unstructured JSON maps (map[string]any).
Package jsonutil provides helper functions for extracting typed values from unstructured JSON maps (map[string]any).
logger
Package logger provides structured logging with colored console output, optional file output, and per-account logger prefixing using log/slog.
Package logger provides structured logging with colored console output, optional file output, and per-account logger prefixing using log/slog.
managedminer
Package managedminer provides dynamic lifecycle management for Miner goroutines.
Package managedminer provides dynamic lifecycle management for Miner goroutines.
miner
Package miner implements the core mining orchestrator for a single Twitch account.
Package miner implements the core mining orchestrator for a single Twitch account.
model
Package model defines pure data types for all Twitch miner entities.
Package model defines pure data types for all Twitch miner entities.
notify
Package notify provides notification dispatching to multiple providers (Telegram, Discord, Webhook, Matrix, Pushover, Gotify) based on event filtering.
Package notify provides notification dispatching to multiple providers (Telegram, Discord, Webhook, Matrix, Pushover, Gotify) based on event filtering.
pubsub
Package pubsub implements the Twitch PubSub WebSocket protocol, providing a connection pool that manages multiple WebSocket connections, automatic topic distribution, ping/pong keepalive, and reconnection with exponential backoff.
Package pubsub implements the Twitch PubSub WebSocket protocol, providing a connection pool that manages multiple WebSocket connections, automatic topic distribution, ping/pong keepalive, and reconnection with exponential backoff.
server
Package server provides a lightweight HTTP analytics server that exposes streamer data, statistics, and a simple dashboard.
Package server provides a lightweight HTTP analytics server that exposes streamer data, statistics, and a simple dashboard.
store
Package store defines the persistence interface for account configurations.
Package store defines the persistence interface for account configurations.
streakstore
Package streakstore persists which watch streaks have already been earned, so a restart does not spend slot time chasing streaks Twitch has already paid out.
Package streakstore persists which watch streaks have already been earned, so a restart does not spend slot time chasing streaks Twitch has already paid out.
telemetry
Package telemetry sends periodic heartbeats to a telemetry server to track active instances, versions, and platforms.
Package telemetry sends periodic heartbeats to a telemetry server to track active instances, versions, and platforms.
tray
Package tray provides a system tray icon for the miner binary so users can open the dashboard and config editor and trigger a graceful exit without needing the terminal/console.
Package tray provides a system tray icon for the miner binary so users can open the dashboard and config editor and trigger a graceful exit without needing the terminal/console.
twitch
Package twitch provides a high-level Twitch API client that combines authentication, GQL operations, and business logic for the miner.
Package twitch provides a high-level Twitch API client that combines authentication, GQL operations, and business logic for the miner.
utils
Package utils provides general-purpose utility functions for the Twitch miner, including number formatting and text slugification.
Package utils provides general-purpose utility functions for the Twitch miner, including number formatting and text slugification.
watcher
Package watcher provides the CategoryWatcher that automatically discovers and tracks streamers based on configured game categories.
Package watcher provides the CategoryWatcher that automatically discovers and tracks streamers based on configured game categories.
workerpool
Package workerpool provides a generic bounded worker pool for running a function over a slice of items concurrently.
Package workerpool provides a generic bounded worker pool for running a function over a slice of items concurrently.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL