README.md

# Reach

Program dependence graph and release-safety toolkit for Elixir, Erlang, Gleam, JavaScript, and TypeScript.

Reach builds a graph of **what depends on what** in your code: control flow, call graph, data flow, effects, and OTP/process relationships. Use it to inspect risky functions, trace values, validate architecture policy, and generate interactive HTML reports.

Elixir 1.18+ / OTP 27+.

## Installation

```elixir
def deps do
  [
    {:reach, "~> 2.0", only: [:dev, :test], runtime: false}
  ]
end
```

Optional dependencies enable richer output:

```elixir
{:jason, "~> 1.0"},       # JSON output
{:boxart, "~> 0.3.3"},    # terminal graphs
{:makeup, "~> 1.0"},
{:makeup_elixir, "~> 1.0"},
{:makeup_js, "~> 0.1"}
```

## Quickstart

Generate an interactive report:

```bash
mix reach
```

Map the project:

```bash
mix reach.map
mix reach.map --modules
mix reach.map --coupling
mix reach.map --hotspots
```

Inspect a target:

```bash
mix reach.inspect MyApp.Accounts.create_user/1 --context
mix reach.inspect lib/my_app/accounts.ex:42 --impact
mix reach.inspect MyApp.Accounts.create_user/1 --why MyApp.Repo
```

Trace data:

```bash
mix reach.trace --from conn.params --to Repo
mix reach.trace --variable changeset --in MyApp.Accounts.create_user/1
```

Run release checks:

```bash
mix reach.check --arch
mix reach.check --changed --base main
mix reach.check --candidates
```

Inspect OTP/process risks:

```bash
mix reach.otp
mix reach.otp --concurrency
```

## Canonical CLI

Reach 2.x uses five canonical analysis tasks plus the HTML report task.

| Command | Purpose |
|---|---|
| `mix reach` | Interactive HTML report |
| `mix reach.map` | Project map: modules, coupling, hotspots, effects, depth, data flow |
| `mix reach.inspect TARGET` | Target-local deps, impact, graph, context, data, candidates, why paths |
| `mix reach.trace` | Data-flow, taint, and slicing workflows |
| `mix reach.check` | CI/release checks: architecture, changed code, dead code, smells, candidates |
| `mix reach.otp` | OTP/process analysis: behaviours, state machines, supervision, concurrency, coupling |

Use `--format json` for automation. Canonical commands emit pure JSON envelopes with stable command names.

Older task names were removed in Reach 2.0 and fail fast with migration guidance. See the [Canonical CLI guide](guides/cli.md).

## Configuration

Reach reads `.reach.exs` for architecture and change-safety policy:

```elixir
[
  layers: [
    web: "MyAppWeb.*",
    domain: "MyApp.*",
    data: ["MyApp.Repo", "MyApp.Schemas.*"]
  ],
  deps: [
    forbidden: [
      {:domain, :web},
      {:data, :web}
    ]
  ],
  source: [
    forbidden_modules: ["MyApp.Legacy.*"],
    forbidden_files: ["lib/my_app/legacy/**"]
  ],
  calls: [
    forbidden: [
      {"MyApp.Domain.*", ["IO.puts", "Jason.encode!"]}
    ]
  ],
  tests: [
    hints: [
      {"lib/my_app/accounts/**", ["test/my_app/accounts_test.exs"]}
    ]
  ]
]
```

Start from [`examples/reach.exs`](examples/reach.exs). See the [configuration guide](guides/configuration.md) for the full reference and narrative examples.

## Library API

Reach can also analyze snippets, files, and source directories directly:

```elixir
graph = Reach.string_to_graph!("""
def run(input) do
  command = String.trim(input)
  System.cmd("sh", ["-c", command])
end
""")

[cmd_call] = Reach.nodes(graph, type: :call, module: System, function: :cmd)
Reach.backward_slice(graph, cmd_call.id)
```

Common queries:

```elixir
Reach.backward_slice(graph, node_id)
Reach.forward_slice(graph, node_id)
Reach.taint_analysis(graph, sources: [function: :params], sinks: [module: System, function: :cmd])
Reach.independent?(graph, node_a.id, node_b.id)
Reach.data_flows?(graph, source_id, sink_id)
```

## Documentation

HexDocs guides are organized by workflow:

- Overview, installation, and quickstart
- Canonical CLI and JSON output
- Configuration and `.reach.exs` policy
- Concepts: dependence graph, control flow, call graph, data flow, effects, OTP
- Validation and ProgramFacts oracle checks
- Recipes and contributing notes

## Validation

Reach itself is validated with:

```bash
mix compile --force --warnings-as-errors
mix ci
/tmp/reach_validate_canonical_full.sh
mix docs
mix hex.build
```

`mix ci` includes formatting, JS checks, Credo/ExSlop, ExDNA duplication checks, architecture policy, Dialyzer, and tests.

## Acknowledgements

Some structural smell patterns were informed by public [Credence](https://github.com/Cinderella-Man/credence) rules. Reach implements them over its own IR/project model and keeps them advisory.

## License

MIT. See [`LICENSE`](LICENSE).