AI refac
Development

بِسْمِ ٱللَّهِ ٱلرَّحْمَـٰنِ ٱلرَّحِيمِ

Build Guide

How to build refac from source, keep the installed binary current, and set up a local development loop.

This page will inshallah take you from a checkout to a development loop that stays current.

Build

The crate requires Rust 1.99 or newer. rust-toolchain.toml pins development to Rust 1.99.0 with rustfmt and rust-analyzer. Use Cargo in the normal way:

cargo build            # debug build
cargo build --release  # release build

Outputs:

  • target/debug/refac
  • target/release/refac
  • target/debug/create_testbed, the generator for sample projects

Install and keep it current

The expected setup is that refac is reachable as ~/.local/bin/refac. The preferred way is the script, which builds, links, and verifies:

scripts/install.sh

Run it after every pull, checkout, or source change. It is idempotent and takes seconds when nothing changed. It runs cargo build --release, points ~/.local/bin/refac at target/release/refac, and then checks three things. It stops with exit code 1 and the reason when one of them fails:

  1. A refac is found on the PATH. If not, ~/.local/bin is missing from it.
  2. That refac is this checkout's target/release/refac and not another copy that shadows it.
  3. refac --version names the commit that is checked out.
installed and current: refac 0.1.4 (55b157a, built 2026-10-09 20:09 UTC)

The stamp comes from build.rs and exists in the release profile only, so debug and test builds do not recompile after every commit. They print dev build. +dirty after the commit means a file under src/, Cargo.toml, Cargo.lock, or build.rs differs from that commit. The helper scripts in scripts/ are read from the checkout at run time and are not compiled in. To check without building, compare refac --version with git rev-parse --short HEAD.

By hand, the same is a symlink, which follows every rebuild, or a copy, which is a fixed snapshot:

mkdir -p ~/.local/bin
ln -sf "$(pwd)/target/release/refac" ~/.local/bin/refac
cp target/release/refac ~/.local/bin/refac

Disk

The installed binary is one file of about 36 MB. The 1.5 GB around it in target/release is build cache, mostly the embedded rust-analyzer, and it is what makes a repeat build take a fraction of a second, so keep it. Deleting target/release also deletes the binary that the link points to, and scripts/install.sh brings it back in about 4 minutes. The much larger debug and test programs are a by-product of cargo test and collect stale copies after toolchain or dependency changes.

CLI during development

Show help without installing:

cargo run -- --help
cargo run -- move --help

Run a move directly:

cargo run -- move \
  --project-path /absolute/path/to/project \
  --source-path src/old_file.ts \
  --target-path src/new_file.ts

Run a semantic Rust module move:

cargo run -- move-module \
  --project-path /absolute/path/to/cargo-workspace \
  crate::engine::matching \
  crate::domain::matching

Set REFAC_PROJECT_PATH to avoid repeating --project-path. For move, point it at the concrete package root. Repeat --source-path and --target-path to run several moves in one call, and add --json for machine-readable output.

Testbed generator

create_testbed generates sample projects for manual verification:

cargo run --bin create_testbed

It recreates Trials/0_Refac_Tree/ with sample projects for TypeScript, Python, Rust, Go, and Dart. Each project has internal references, so a move can be checked against real imports and module declarations.

Basic development workflow

  1. scripts/install.sh builds, links, and verifies the release binary.
  2. Run cargo test after a behavior change.
  3. cargo run --bin create_testbed regenerates the samples when you need them.
  4. Run refac move ... against a concrete project.
  5. Verify the project still builds with its native toolchain (cargo check, go build ./..., and so on). It should inshallah build without an edit by hand.

On this page