icr
Version, currently 1.1.04 versions
- 1.3.0latestOct 2, 2026
- 1.2.0not indexedOct 2, 2026
- 1.1.0not indexedOct 2, 2026
- 1.0.0not indexedOct 2, 2026
github.com/OrelSokolov/icr.cr
Interactive Crystal Shell — an irb-style console for Crystal. Live `crystal i` backend over a PTY (instant, stateful) with an automatic whole-session-recompile fallback for stock compilers.
Nothing has been indexed for 1.1.0 yet. The tag is recorded, its shard.yml has not been read, so the manifest and dependency list below are empty because they are unknown rather than because they are absent.
Installation
# Add this to your shard.yml
dependencies:
icr:
github: OrelSokolov/icr.cr
version: ~> 1.1.0Then run:
shards installshard.yml
No shard.yml has been indexed for 1.1.0. You can read it on the repository.
Dependencies
Unknown: the shard.yml for this version has not been read yet.
README
This README is the one indexed from the repository at its latest ref, not from the tag for this version.
icr — Interactive Crystal Shell
An irb-style console for Crystal:
⢀⡴⠊⢉⡟⢿ icr v1.1.0 - Crystal 1.21.0 - live interpreter
⣎⣀⣴⡋⡟⣻ "exit" to quit · ".program" session source · ".reset" clear
⣟⣼⣱⣽⣟⣾ ~/your/project
icr> 2 + 2
=> 4
# 0.2s
Two backends
- live — a persistent
crystal iinterpreter process driven over a PTY: real in-process state, ~0.1–0.5s per line. Official Linux Crystal builds ship without interpreter support, so runscripts/build-interpreter.shonce to build a local compiler withinterpreter=1into~/.local/share/icr/(nothing system-wide). - replay — automatic fallback for stock compilers: every line
recompiles and re-runs the whole session via
crystal run(~1.5–3s per line). State "persists" because all previous lines are replayed; side effects (DB writes etc.) re-run on every submission.
The backend is picked automatically: ICR_CRYSTAL env var →
CRYSTAL_INTERPRETER_PATH env var →
~/.local/share/icr/crystal/bin/crystal → crystal from PATH
(usually falls through to replay). Both env vars are read directly
from Crystal code (ENV[...]? in Icr.interpreter_bin) at startup.
Usage
bin/icr # or: crystal run src/cli.cr
ICR_CRYSTAL=/path/to/crystal bin/icr
CRYSTAL_INTERPRETER_PATH=/path/to/crystal bin/icr
Commands inside the console:
| command | action |
|---|---|
.program | print the session source so far |
.reset | drop state (live: restart the process) |
.exit / exit / Ctrl+D | quit |
Tab | autocomplete from the baked table |
Ctrl-T | fuzzy search over the baked table |
An incomplete line (def f, open blocks…) continues with ... >
prompts until the expression is complete. In replay mode, end a line
with \ to continue on the next one.
Autocomplete (baked at compile time)
When the whole program (icr included) is compiled, a macro harvest
(src/icr/completion.cr) walks the type graph and "bakes" a TSV table
of types, methods and constants into the binary — Icr::Completion::TABLE.
The standalone bin/icr opts in itself (stdlib + icr), so Tab completes
Str → String, String.bu → String.build…, and Ctrl-T opens a
fuzzy-search overlay over every method.
Host apps that use icr as a library opt in with require_with_autocomplete,
which is a plain require plus namespace roots:
require "icr"
require_with_autocomplete "./my_math", MyMath
Classes and structs anywhere in the program are harvested automatically;
modules and enums are invisible to Object.all_subclasses, so list them
explicitly as roots. Programs that never opt in get an empty table —
zero cost.
Known limits (see plans/autocomplete.md for the full analysis):
- The table is a build-time snapshot: types defined later inside the session are not completed.
- Only literal type names are completed after
.(MyMath.sq<Tab>), not variables — the host process can't know a variable's runtime type.
As a library
Both sessions share one interface, and Icr.open_session picks the
best backend automatically — a live interpreter whenever one is
available (same chain as the CLI: ICR_CRYSTAL →
CRYSTAL_INTERPRETER_PATH → ~/.local/share/icr/… → crystal on
PATH), replay otherwise. Works identically when icr is installed as
a shard into another app; the env vars are read from Crystal code at
call time, so the host app can set them before opening a session.
require "icr"
require_with_autocomplete "./my_math", MyMath
session = Icr.open_session # live if available, replay otherwise
puts session.submit("2 + 2") # => "=> 4"
session.close
To control the backend explicitly:
session = Icr::LiveSession.new(Icr.interpreter_bin.not_nil!)
Notes
- Live backend: Linux and macOS (openpty via libutil; the interpreter
builds from Crystal sources on both — see
scripts/build-interpreter.sh). macOS is untested in this repo; on Windows there is no openpty, so icr runs in replay mode only (crystal runworks everywhere Crystal does). - The interpreter installs to
~/.local/share/icr/crystalon every OS (the same path icr's loader checks). - The PTY protocol quirks (paste threshold, window size, continuation
prompts) are documented in
src/icr/live.cr. - Crystal >= 1.21.
License
MIT
Documentation
Built from the current release. The first visit to a release nobody has asked for starts its build.
Links
This release
- Version
1.1.0- Tagged
- Oct 2, 2026
- Commit
40db8edc88c8- Indexed
- not yet
Dependents
Repository
github.com/OrelSokolov/icr.cr
Metadata
- Created
- Oct 4, 2026
- Updated
- Oct 24, 2026
- Synced
- Oct 24, 2026
- Versions
- 4