Console IPC

Fast, stateful rails runner alternative over a Unix socket.

Why use it?

console-ipc gives you a scriptable Rails console that stays warm.

Instead of paying Rails boot cost for every rails runner command, start one background console and send Ruby snippets to it over a Unix socket. Each snippet runs in the same top-level console binding, so local variables, helper methods, loaded records, and exploratory state can survive across commands.

bundle exec console-ipc start > log/console-ipc.log 2>&1
bundle exec console-ipc run 'account = Account.last'
bundle exec console-ipc run 'account.email'
bundle exec console-ipc run --json 'account.attributes.slice("id", "email")'

It is built for tight local feedback loops:

  • Inspect production-shaped Rails data locally without repeating setup code.
  • Keep expensive objects, query results, and helper methods alive between probes.
  • Run quick snippets from shell scripts, editors, terminals, and AI coding agents.
  • Produce fewer output tokens for agent workflows because setup, helper definitions, and repeated context can stay in the warm console instead of being printed again for every command.
  • Ask Ruby and Rails where code lives: source_location, const_source_location, ancestors, methods, and related reflection calls.
  • Edit source, call reload, and keep exploring without restarting the console.
  • Use --json when another tool needs structured stdout, stderr, result, and error data.

The result is faster turnaround, less terminal noise, and smaller agent transcripts. Instead of rerunning a large setup script, you build context once and reuse it.

Install

Add the gem to a Rails app:

gem "console_ipc", group: :development

Then run:

bundle install

Quick start

Start it from the Rails app root. The command daemonizes by default and returns only after Rails is loaded and the socket is listening:

bundle exec console-ipc start > log/console-ipc.log 2>&1

Run snippets against the warm console:

bundle exec console-ipc run 'emails = Account.last(10).map(&:email)'
bundle exec console-ipc run 'puts emails'
bundle exec console-ipc run --json 'Account.count'

State persists:

bundle exec console-ipc run 'def explain(record); record.attributes.slice("id", "created_at"); end'
bundle exec console-ipc run --json 'explain(Account.last)'

Send code through stdin when that is easier than shell quoting:

cat <<'RUBY' | bundle exec console-ipc run --json
account = Account.last
{
  id: account.id,
  email: account.email,
  changes: account.previous_changes
}
RUBY

What it can do

Stateful Rails probing

Every run command evaluates in the same console context:

bundle exec console-ipc run 'scope = Account.where(active: true)'
bundle exec console-ipc run 'scope.count'
bundle exec console-ipc run 'sample = scope.order(:created_at).last'
bundle exec console-ipc run 'sample.class'

That makes repetitive inspection much cheaper than rebuilding the same scope every time.

Reflection and source discovery

Use normal Ruby and Rails reflection from the terminal:

bundle exec console-ipc run 'Account.instance_method(:save).source_location'
bundle exec console-ipc run 'Object.const_source_location("Account")'
bundle exec console-ipc run 'Account.ancestors'
bundle exec console-ipc run 'Account.new.public_methods.grep(/email/)'

Machine-readable output

--json prints the raw response object:

bundle exec console-ipc run --json 'Account.count'

Successful responses include:

  • ok: whether evaluation succeeded.
  • stdout: captured $stdout.
  • stderr: captured $stderr.
  • result: inspect output for the last expression.
  • output: console-style combined output.

Error responses include ok: false, captured output, and the exception message with a short backtrace.

Source reloads

Use reload after source edits. It calls Rails console reload! inside the running process:

bundle exec console-ipc reload

Process lifecycle

Use reset for a clean process and stop when done:

bundle exec console-ipc reset
bundle exec console-ipc stop

Use --foreground when debugging the console process directly or when you want Ctrl-C to stop it:

bundle exec console-ipc start --foreground

Tips

Start the console once and reuse run for later snippets. Do not stop or restart it between runs unless the socket is stale or run reports that no console is listening. If that happens, remove the stale socket and start it again:

rm -f tmp/console_ipc.sock
bundle exec console-ipc start > log/console-ipc.log 2>&1

Use reset when state gets confusing:

bundle exec console-ipc reset

Security model

console-ipc is intended for local development and trusted automation. It evaluates arbitrary Ruby in your Rails app. The socket is created with 0600 permissions, but anyone who can access the socket as your user can run code in that Rails process. Do not expose the socket over the network.