Open-source project
x-motemen/gore avatar
x-motemen/gore

x-motemen/gore: a Go REPL that recompiles on every line

Yet another Go REPL that works nicely. Featured with line editing, code completion, and more.

5,519 stars152 forksGoMIT

At a glance

What is it?
gore gives Go an interactive prompt with line editing, completion through gopls and module-aware imports, but it evaluates each input with go run, so timing and speed are not what you get from a compiled program. Here is who it fits and who should look elsewhere.
Who is it for?
Adopt gore when you want a scratchpad for expressions, imports and function declarations without writing a main.go, and you accept that each line is re-executed through go run. Skip it if you need stable wall-clock measurements, tight loop latency, or a project whose own README recommends other REPLs.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 63 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What gore is for, and who keeps it installed

Go has no REPL in the standard toolchain. The usual workaround is a throwaway main.go, a print statement and a go run, repeated until the answer appears. gore replaces that loop with a prompt: you type expressions, statements and function declarations, and it keeps them as one growing source file that it compiles and executes. The README describes the target plainly, "Yet another Go REPL that works nicely," and lists line editing with history, multi-line input, package importing with completion, and evaluation of expressions, statements and function declarations. It also claims no "evaluated but not used" errors, which is the compiler complaint that makes the throwaway-main.go approach annoying when you only want a value printed.

The audience is narrow but real. Someone exploring an unfamiliar package wants to call one function and see the shape of the result. Someone checking a regular expression, a date parse or an encoding round trip does not want a file on disk. gore is for that person, at a terminal, in a directory that is already a Go module. It is not a runtime for embedding, not a notebook, and not a way to ship anything. The README's own caveats section is unusually candid about this: it says the project started from a simple idea to use go run for all REPL input and that other implementations are more actively maintained and faster.

How gore runs your input: go run on every line

The mechanism is the source of both the convenience and the cost. According to the README, gore runs code using go run for each input, and every line entered is evaluated repeatedly. There is no incremental compiler and no interpreter in the middle. Each submission is folded into the session's accumulated source, written out, compiled and executed, and the output is shown back to you. That is why a function declaration you typed ten lines ago is still callable, and why the type of an expression can be inspected with :type. It is also why the README states you cannot bind the evaluated time with time.Now(), because the timestamp you capture belongs to that particular re-execution, not to a session that started when you opened the prompt.

The repository layout matches that model. The top level holds session.go, node.go, errfilter.go, quickfix.go and gomod.go alongside the command implementations in commands.go and the completion plumbing in complete.go and gopls.go. The dependencies in go.mod tell the same story: peterh/liner for the prompt, motemen/go-quickfix for fixing up the generated source, and the go.lsp.dev packages for talking to gopls over JSON-RPC. Module handling is delegated to the Go toolchain rather than reimplemented; the README says gore supports Go modules, that starting it in a project directory loads local modules, and that :import github.com/... downloads the module without a separate go get.

Installing gore and running a first session

The README is explicit that no standalone binary is distributed, because the gore command needs Go toolchains at runtime. Installation is a go install against the cmd/gore package. The second command is optional but is what makes completion work, since the README ties code completion to gopls.

bash
go install github.com/x-motemen/gore/cmd/gore@latest
go install golang.org/x/tools/gopls@latest

If you would rather not install anything, the README also gives a Docker invocation that pulls an image with gore and gopls already inside. The repository's Dockerfile builds gore with make install, installs gopls, and sets the entrypoint to gore.

bash
docker run -it --rm ghcr.io/x-motemen/gore

Once the prompt appears, the README documents a set of REPL commands for importing, inspecting types and printing the accumulated source. After that, the source can be inspected or saved.

text
:import strings
:type strings.ToUpper
:print
:write
:quit

What you should see is the function's signature from :type, then the full source gore has assembled so far. :write with no filename writes that source out, and :clear empties it. To leave, use Ctrl-D or :q. Two environment variables are worth knowing before you start: GORE_HOME decides where the history file lives (it defaults to $XDG_DATA_HOME/gore, or ~/.gore when XDG_DATA_HOME is unset), and GORE_PAGER sets the pager used for :doc output, for example less. GORE_VERBOSE controls whether assigned or declared values are printed automatically at startup; set it to 0 or false to turn that off, or toggle it mid-session with :verbose.

The re-execution model is the limitation, not a footnote

Every input re-runs the whole accumulated program through go run. The README links this to issue #67 for the repeated-evaluation behaviour and issue #182 for the resulting slowness, and states directly that the execution is fairly slow. This is not a tuning problem you can fix with a flag. It is the design.

Two consequences matter in practice. First, anything with a side effect happens again on the next input: a file written, a counter incremented, a network call made. The README's time.Now() example is the clearest case, but the same logic applies to anything non-deterministic. Second, wall-clock measurements are meaningless, so gore is the wrong tool for benchmarking a function or comparing two implementations by timing them. Use a compiled test with the standard testing package for that. The README also points readers elsewhere on maintenance grounds, recommending gomacro or yaegi and saying those implementations are more actively maintained and run faster. When a project's own README says that, take it at face value. The last push to this repository was on 2026-07-30, and v0.7.0 was released the same day.

gomacro and yaegi: interpreters instead of go run

The README names two alternatives, and the difference is architectural rather than cosmetic. gomacro and yaegi are interpreters. They parse and evaluate Go source inside the running process, which is why they can start faster and why repeated input does not pay a compile cost each time. gore sits on top of the real toolchain, so what it executes is what the compiler would build, including the parts of Go that interpreters tend to approximate.

That trade cuts both ways. If you care about the exact behaviour of generics, cgo, or a build-tag-dependent file, an interpreter may not match the compiler, while gore's go run path does by construction. If you care about latency between keystrokes and output, or about evaluating the same expression a hundred times in a loop, the interpreters win and gore's README says so. There is also a practical difference in what you need installed: gore requires a Go toolchain at runtime and gopls for completion, while an interpreter is a single binary. The Docker image in this repository bundles gore and gopls together, which is the closest gore gets to that single-binary experience.

Session state, files on disk and upgrade cost

gore keeps state in two places. The growing source lives in memory and is visible through :print and extractable through :write. The command history lives in a file under GORE_HOME. That split matters when you are deciding whether a session is reproducible: the source can be saved and read, but the history is a convenience, not a record of what ran. If you want to keep a result, run :write before you quit rather than relying on scrollback.

On upgrades, the project tracks the Go toolchain closely. go.mod declares go 1.26, and the Dockerfile builds from a golang:1.26.4-alpine3.24 image before copying gore and gopls into the final stage. Because gore shells out to the toolchain, a Go upgrade on your machine can change gore's behaviour without gore itself changing, and the Docker image pins a specific toolchain version for that reason. Completion depends on gopls being on PATH and on the version of gopls you installed, since the README's install line uses @latest. If completion stops working after an upgrade, that pairing is the first thing to check.

The licence is MIT, stated in the README badge and in the LICENSE file at the repository root. MIT is permissive: it allows use, modification and redistribution with the copyright notice and permission notice retained, and it comes with no warranty. That is a description of the terms, not legal advice; read the LICENSE file if the distinction matters to your organisation. The repository also carries a CREDITS target in its Makefile that generates a credits file with gocredits, which is the project's own way of tracking the dependency licences it ships against.

Editorial conclusion

Adopt gore when you want a scratchpad for expressions, imports and function declarations without writing a main.go, and you accept that each line is re-executed through go run. Skip it if you need stable wall-clock measurements, tight loop latency, or a project whose own README recommends other REPLs. Before committing, install it with go install github.com/x-motemen/gore/cmd/gore@latest, check that gopls is on PATH if you want completion, and run :print after a few inputs to confirm the accumulated source is what you expect.

Frequently asked questions

Does gore need Go installed to run?

Yes. The README says the gore command requires Go toolchains at runtime, which is why no standalone binary is distributed. The Docker image exists for people who do not want to install the toolchain themselves.

Why does gore re-execute my code on every line?

gore runs code using go run for each input, and the README states that every line entered is evaluated repeatedly, referencing issue #67. That is why a time.Now() value cannot be bound to the moment you started the session.

How do I get code completion in gore?

The README lists code completion as requiring gopls, installed with go install golang.org/x/tools/gopls@latest. The repository's Dockerfile installs gopls alongside gore so the image has it by default.

Can gore import packages from a remote repository?

Yes. The README says you do not need to go get to check the usage of a remote repository, because :import github.com/... automatically downloads that module. Local modules load when you start gore in the project directory.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. x-motemen/gore on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/x-motemen-gore.svg)](https://hysenlabs.com/projects/x-motemen-gore)