{"id":47679883,"url":"https://github.com/mh4gf/tq","last_synced_at":"2026-05-16T13:01:25.076Z","repository":{"id":345058779,"uuid":"1170399482","full_name":"MH4GF/tq","owner":"MH4GF","description":"Job Queue for Claude Code","archived":false,"fork":false,"pushed_at":"2026-05-16T12:10:02.000Z","size":15771,"stargazers_count":14,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-16T12:14:24.198Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MH4GF.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-02T04:34:52.000Z","updated_at":"2026-05-16T12:09:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"bd15cddf-36b8-48db-af1e-c645bb603213","html_url":"https://github.com/MH4GF/tq","commit_stats":null,"previous_names":["mh4gf/tq"],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/MH4GF/tq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MH4GF%2Ftq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MH4GF%2Ftq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MH4GF%2Ftq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MH4GF%2Ftq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MH4GF","download_url":"https://codeload.github.com/MH4GF/tq/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MH4GF%2Ftq/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33103970,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-16T04:41:52.686Z","status":"ssl_error","status_checked_at":"2026-05-16T04:41:52.009Z","response_time":115,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-02T13:56:08.053Z","updated_at":"2026-05-16T13:01:25.068Z","avatar_url":"https://github.com/MH4GF.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tq — Task Queue\n\nJob-queue based orchestration system for Claude Code. Combines a CLI/TUI with a Claude Code Plugin to manage multiple sessions via tmux.\n\nHumans give instructions in natural language and monitor progress via TUI. The manager agent handles task breakdown, prompt tuning, and dispatching actions to worker sessions.\n\n![tq demo](docs/tq.gif)\n\n## Highlights\n\n- **Job queue model** — actions are queued and processed asynchronously by workers, with independent concurrency caps for user-facing modes (interactive + experimental_bg share the same pool, default: 3) and noninteractive execution (default: 5)\n- **Manager agent** — one Claude Code session manages others; humans just talk to it\n- **Delegates to Claude Code** — no custom workflow language; just runs `claude` in tmux, so skills, sub-agents, worktrees, and remote execution all work as-is\n- **CLI is for agents** — JSON-only output, `--jq` flag, agent-oriented `--help`; humans don't need to learn the CLI\n- **Schedule support** — cron-based action generation for recurring tasks\n\n## Install\n\nPrerequisites: [tmux](https://github.com/tmux/tmux) (required for dispatching interactive sessions)\n\n```bash\n# Homebrew (macOS / Linux)\nbrew install MH4GF/tap/tq\n\n# Claude Code Plugin\nclaude plugin marketplace add MH4GF/tq\nclaude plugin install tq@tq-marketplace\n```\n\nOr download a binary from [GitHub Releases](https://github.com/MH4GF/tq/releases).\n\n## Quick Start\n\n```bash\n# Register a project (sets working directory for tasks)\ntq project create myapp ~/src/myapp\n\n# Create a task under the project\ntq task create \"Implement feature X\" --project 1\n\n# Launch the TUI (starts the queue worker)\ntq ui\n```\n\nThen open Claude Code in another terminal and talk to the manager agent:\n\n```\n/tq:manager\n```\n\nTo create an action (spawns a new Claude Code session):\n\n```\n/tq:create-action Implement feature X and create a PR\n```\n\nThe agent will tune the instruction, associate it with the right task, create the action, and the queue worker will automatically pick it up.\n\nSee [CLI Reference](docs/cli-reference.md) for the full command list.\n\n## Configuration\n\nThe database lives at `~/.config/tq/tq.db` by default. Override with:\n\n- `--db \u003cpath-or-url\u003e` flag (highest precedence)\n- `TQ_DB_URL` environment variable\n\nBoth accept either a local sqlite file path or a libsql URL\n(`libsql://...?authToken=...`), so the same binary can talk to a remote\n[Turso](https://turso.tech) database (or any libsql-compatible endpoint\nsuch as a self-hosted [sqld](https://github.com/tursodatabase/libsql)).\nVerified against Turso. Embed the auth token in the URL query string;\nno separate env var is read.\n\nUseful for running multiple isolated queues (e.g. a separate DB for demos or testing).\n\n## Data Model\n\n```\nproject → task → action\n```\n\n- **project**: groups tasks, sets default working directory\n- **task**: unit of work (status: open, done, archived)\n- **action**: dispatchable unit of work with an instruction (status: pending, running, dispatched, done, failed, cancelled)\n\n### Design Principles\n\n- **SQLite is SSOT** — the database is the canonical state store\n- **Queue Worker** — interactive actions dispatch into tmux (one at a time per slot); noninteractive actions run concurrently in goroutines so a long-running `claude -p` does not block the dispatch loop\n- **AI is hands only** — Go handles orchestration; AI executes as a `claude` worker\n- **TUI is read-only** — humans observe via TUI; operations are issued through CLI\n\n### Action State Machine\n\n```\n         dispatch        worker claim\n pending ────────► running ───────────► dispatched\n\n  Terminal transitions (each reachable from the states noted):\n\n  done   (from pending, running, or dispatched)\n                              │\n                              ▼\n                        ┌────────┐\n                        │  done  │\n                        └────────┘\n\n  fail   (from pending, running, or dispatched)\n                              │\n                              ▼\n              reset       ┌────────┐\n    pending ◄──────────── │ failed │\n                          └────────┘\n\n  cancel (from pending, running, dispatched, or failed)\n                              │\n                              ▼\n                        ┌───────────┐\n                        │ cancelled │\n                        └───────────┘\n\n  * done can be issued from any non-terminal state (pending, running, or dispatched)\n  * fail can be issued from any non-terminal state (pending, running, or dispatched)\n  * cancel can be issued from pending, running, dispatched, or failed (terminal: cancelled)\n  * reset returns failed or cancelled actions to pending; running and dispatched\n    must be cancelled or failed first (reset is rejected to avoid spawning a duplicate worker)\n  * cancel/fail/reset only update the DB; tmux panes are not terminated\n  * done, failed, and cancelled are terminal; on_done spawns a new action from done only\n  * `tq action resume \u003cid\u003e` spawns a new action that resumes the claude session of any terminal action whose metadata captured `claude_session_id` (see `docs/cli-reference.md`)\n  * completion dependencies (`--blocked-by-action`/`--blocked-by-task`) hold a\n    pending action until every blocker reaches a successful terminal state\n    (action=done, task=done/archived); a failed/cancelled blocker holds it\n    forever (rescue via `/tq-dep-triage`). `tq action dispatch` is the manual\n    bypass; the queue worker respects the gate (see `docs/cli-reference.md`)\n```\n\n### Worker Types\n\nControlled via `--meta` on `action create` / `schedule create`. Any value outside this set is rejected — pass Claude permission-mode (`auto`, `plan`, `acceptEdits`, …) via `claude_args` instead.\n\n| mode | Description |\n|------|-------------|\n| `interactive` (default) | `claude` in tmux — fire-and-forget, worker reports via `tq action done` / `tq action fail`. |\n| `noninteractive` | `claude -p` — captures stdout, auto-completes. Heartbeat-aware: kept alive past the 600s minimum while the session log mtime stays fresh (≤120s old), up to a 60-minute hard cap |\n| `remote` | Dispatched to remote worker |\n| `experimental_bg` | Research preview: dispatches via `claude --bg` so the action appears in `claude agents`. Lifecycle tracked by polling `~/.claude/jobs/\u003cshort\u003e/state.json`. Shares the `MaxInteractive` slot pool with `interactive`. Requires Claude Code v2.1.139+ with agent view enabled |\n\nAdditional metadata keys:\n- `claude_args` — Additional CLI arguments for claude (JSON array of strings, e.g. `[\"--permission-mode\",\"plan\",\"--worktree\",\"--max-turns\",\"5\"]`)\n\n## Testing\n\nUnit tests live alongside source files (`*_test.go`). End-to-end CLI scenarios are written as [testscript](https://pkg.go.dev/github.com/rogpeppe/go-internal/testscript) files under `e2e/testdata/script/*.txtar`. Each scenario runs against an isolated `TQ_DB_URL`, `HOME`, and `TMUX_TMPDIR`, so they can run in parallel without interference. Run all tests with `go test ./...`, or just the E2E suite with `go test ./e2e`. To add a scenario, drop a new `.txtar` file describing the CLI invocations and expected stdout/stderr; for tmux dispatch scenarios, embed a `claude` stub via `-- file --` sections and synchronize with `tmux wait-for` to keep the test deterministic.\n\nThe same e2e suite can be replayed against a libsql endpoint to verify driver compatibility. With a sqld container (or Turso DB) reachable, set `TQ_DB_URL=libsql://...` and run `go test -tags libsql_e2e ./e2e/ -run TestLibsqlE2E`. The libsql variant resets the schema between scenarios since they share one DB. CI runs this against a sqld service container on every PR.\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmh4gf%2Ftq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmh4gf%2Ftq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmh4gf%2Ftq/lists"}