Comparison

Bivvy vs Setup Scripts

Your bin/setup got you this far. Bivvy takes it the rest of the way — with idempotency, change detection, shared configs, and CI parity baked in.

🔄

Run it again without fear

Setup scripts blindly re-run everything. Bivvy's completed_check detects what's already done and skips it. Safe to run a hundred times.

👀

Knows when things changed

watches tracks your lockfiles. When Gemfile.lock changes, the Ruby step re-runs. When it hasn't, skip. No wasted time.

🏢

Share across every repo

extends: lets your infra team publish a base config. Every repo inherits it. When the base updates, every project picks it up.

Side by side

Capability Bivvy bin/setup
Idempotent Yes — completed_check skips satisfied steps Rarely — most scripts re-run everything
Change detection watches detects changed lockfiles None — runs the same regardless
Shared across repos extends: inherits from shared configs Each repo has its own script
CI support Same config, --non-interactive flag Separate workflow file maintained in parallel
Error handling depends_on lets independent steps continue Stops on first failure
Discoverability bivvy status and bivvy list Read the script source
Template reuse Built-in and remote template libraries Copy-paste between repos
Interactive recovery Retry, fix, skip, or debug on failure Script exits, figure it out

Setup scripts rot silently

Every project starts with a fresh bin/setup. Six months later, someone adds a new dependency and forgets to update the script. The README says one thing, the script does another, and CI has its own version of reality.

Bivvy's declarative config is the single source of truth. bivvy status shows what's satisfied and what's not — on any machine, at any time.

bivvy status
 bivvy status

  [✓] brew         2 hours ago
  [!] ruby         stale (Gemfile.lock changed)
  [✓] node         2 hours ago
  [✓] docker       running
  [pending] db  not yet run

Declarative, not imperative

A setup script says "run these commands in order." Bivvy says "ensure this state exists." The difference matters when you run it the second time, the tenth time, or after pulling new changes.

completed_check means bivvy knows whether a step's already done. watches means it knows when something changed. The result: fast, correct re-runs instead of "just run the whole thing again."

.bivvy/config.yml
steps:
  ruby:
    template: bundler
    watches: [Gemfile.lock]
    completed_check:
      command: "bundle check"

  node:
    template: yarn
    watches: [yarn.lock]

  db:
    command: "rails db:prepare"
    depends_on: [ruby, docker]

From script to config in minutes

You don't have to rewrite anything. Run bivvy init in your project and bivvy detects your stack, generates a config from built-in templates, and works immediately.

Your existing setup logic becomes declarative steps with completion checks. Same outcome, better ergonomics. And once it works for one repo, extends: lets you share the pattern across your entire org.

bivvy init
 bivvy initbivvy init

  # Detecting project...
   Ruby 3.2.2 (bundler)
   Node 20.11.0 (yarn)
   PostgreSQL (docker-compose)

   Created .bivvy/config.yml
    3 steps configured from templates

  Run bivvy run to set up.

Ready to retire bin/setup?

Bivvy is what your setup script would be if someone designed it as a product instead of a one-off script.

Also compare

ESC
Type to search documentation...