Skip to content

cfal/rcq

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rcq

rcq is a transparent local resource queue for commands launched by coding agents. It keeps expensive tests, builds, and compilers from stampeding a workstation while leaving stdout, stderr, stdin, exit status, signals, argv, environment, and the working directory attached to the invoking agent.

Linux and macOS are supported.

Quick Start

Build and place rcq on PATH:

cargo install --path .
rcq cargo test --workspace

A missing or empty ~/.rcq.conf is useful immediately. Common compilers, builds, test runners, and package installs enter a default queue with four slots. Everything else, including ls, rg, and Git commands, runs directly. The daemon starts automatically on the first queued command and remains nearly idle between requests.

RCQ accepts argv rather than a shell string. Use an explicit shell when shell syntax is needed:

rcq bash -c 'producer | consumer >result.txt'

Configuration

Configuration is one TOML file at ~/.rcq.conf. All settings are optional. See examples/rcq.conf for a valid, fully annotated configuration covering every option, and examples/default.conf for the explicit equivalent of an empty configuration.

This routes tests separately and limits all builds together through an ancestor queue:

notify_queued = true

[queue.build]
capacity = 3

[queue."build/test"]
capacity = 2

[queue."build/compile"]
capacity = 3

[[rule]]
glob = ["cargo test*", "pytest*"]
queue = "build/test"

[[rule]]
program = ["gcc", "clang", "cc"]
queue = "build/compile"

A command in build/test consumes one build/test slot and one build slot. Only explicitly declared ancestors impose a shared cap. A queue selected by a rule but not declared gets one slot; an undeclared fallback queue gets four.

Weighted pools model resources shared across otherwise unrelated queues:

[pool.cpu]
capacity = 8

[pool.memory_gib]
capacity = 32

[[rule]]
regex = '^(?:make|ninja) -j(?:8|16)(?: |$)'
queue = "build/compile"
resources = { cpu = 6, memory_gib = 8 }

[fallback]
direct = true

Claims are admission units, not runtime enforcement. Queue slots, declared ancestor slots, and pool units are reserved atomically. After 30 seconds, the oldest blocked queue head reserves its conflicting resources as running work drains, preventing large claims from starving. Set starvation_after_seconds = 0 to disable that reservation.

Every queued command claims one slot from its queue and each declared ancestor. The resources table adds weighted pool claims; omit it when none are needed. Claims must be positive, so direct execution is an action rather than a zero-claim queue entry.

Rules are checked in file order before the built-in expensive-command policy and fallback. Each rule has one of program, glob, or regex, and one of direct = true or queue = "name". Use rcq explain -- <command> to inspect a decision and rcq config check to validate the complete effective configuration.

Command Prefixes

RCQ can apply a wrapper after classification. This lets agents use RCQ as their only hook while still receiving RTK output reduction:

command_prefix = ["rtk"]

rcq cargo test then classifies cargo test and executes rtk cargo test. An exact prefix already present is not added again, so rcq rtk cargo test also contains one RTK layer. --no-prefix disables insertion for one command.

Operations

rcq status [--json]
rcq daemon start
rcq daemon stop
rcq daemon restart
rcq --direct -- <command...>

Queued execution fails closed if the daemon or configuration is unavailable. --direct and RCQ_BYPASS=1 are explicit operator escape hatches. Status does not start a stopped daemon.

A nested rcq using the same configuration runs directly inside its live outer allocation instead of consuming another slot. The inherited marker is tied to the outer ticket lease, so stale descendants queue normally; a different configuration source remains an independent queue namespace.

The daemon owns scheduling state, while a private foreground runner owns each started command. Kernel file leases preserve capacity safety if the daemon or public client is killed. A replacement daemon accepts waiting clients but does not grant new work until every command from the previous generation has finished. Normal client loss retains only that command's exact queue and pool claims.

Agent Integration

Install the included Codex instructions in a workspace or globally:

rcq init --codex
rcq init --codex --global

The managed AGENTS.md import is idempotent and preserves unrelated content. Agent command timeouts must include both queue wait and execution time.

Development

cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-features -- --test-threads=1

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages