From karellen-rr-mcp
Debug a data race or concurrency bug using rr. Records the program, then uses deterministic replay with thread inspection and watchpoints to find the exact interleaving that caused the race.
npx claudepluginhub karellen/claude-plugins --plugin karellen-rr-mcpThis skill uses the workspace's default tool permissions.
Use this skill when you suspect a data race, deadlock, or concurrency bug. rr records
Guides Payload CMS config (payload.config.ts), collections, fields, hooks, access control, APIs. Debugs validation errors, security, relationships, queries, transactions, hook behavior.
Builds scalable data pipelines, modern data warehouses, and real-time streaming architectures using Spark, dbt, Airflow, Kafka, and cloud platforms like Snowflake, BigQuery.
Builds production Apache Airflow DAGs with best practices for operators, sensors, testing, and deployment. For data pipelines, workflow orchestration, and batch job scheduling.
Use this skill when you suspect a data race, deadlock, or concurrency bug. rr records the exact thread interleaving that occurred, then replays it deterministically so you can inspect every thread's state at every point.
Run the program under rr. If the race is intermittent, you may need multiple attempts:
rr_record(command=$ARGUMENTS, trace_dir="<project>/rr-trace-<random>")
For sanitizer-detected races, enable ThreadSanitizer to make the race more visible:
rr_record(command=["./program"], env={"TSAN_OPTIONS": "halt_on_error=1"}, trace_dir=...)
rr_ps(trace_dir="<trace>")
rr_replay_start(trace_dir="<trace>", pid=<pid>)
Before diving in, understand the thread landscape:
rr_continue()
At the crash or end point:
rr_thread_list()
Note which threads exist and their states. Switch between threads to see what each was doing:
rr_thread_select(<tid>)
rr_backtrace()
rr_locals()
Identify the shared variable or memory that is being raced on. This might be obvious from the crash (e.g., corrupted pointer) or from sanitizer output.
Set a watchpoint on the contested data:
rr_watchpoint_set("shared_variable")
Or on a memory address:
rr_watchpoint_set("*(int*)0x7fff5678")
Use continue (forward and reverse) to find every access to the contested data:
rr_continue() # Find the next write
rr_backtrace() # Who wrote it?
rr_thread_list() # Which thread?
Save checkpoints at each access point:
rr_checkpoint_save() # Save before moving on
rr_continue() # Next access
Once you have the sequence of accesses across threads, identify where synchronization is missing:
Use rr_continue(reverse=True) with the watchpoint to walk backwards through all
writes and find the first unsynchronized access.
Use rr_when() to note event numbers at key points:
rr_when() # Note event number
rr_run_to_event(N) # Jump to a specific point
rr_replay_stop()
rr_rm(trace_dir="<trace>")
rr_evaluate("pthread_mutex_trylock(&mutex)") to check lock states at any point.