See here for an SVG screencast: https://raw.githubusercontent.com/aleloi/zepl/refs/heads/main/examples/zepl_cast.svg
It tries to compile each user input separately and then dynamically load it into the repl process. Tested on mac and linux on Zig 0.11-0.13. Doesn’t build on master. Very proof-of-concept: leaks memory and probably crashes on some input.
$ git clone https://github.com/aleloi/zepl.git && cd zepl
$ zig build
$ ./zig-out/bin/zepl
zepl> var x: i32 = 123;
zepl> @import("std").debug.print("interactive zig!\n", .{});
interactive zig!
zepl> const alloc = @import("std").heap.page_allocator;
mem.Allocator{ .ptr = anyopaque@0, .vtable = mem.Allocator.VTable{ ... } }
zepl> x
123
zepl> @import("builtin").zig_version
0.13.0
zepl> const std = @import("std");
zepl> std.SemanticVersion.parse
fn ([]const u8) @typeInfo(@typeInfo(@TypeOf(SemanticVersion.parse)).Fn.return_type.?).ErrorUnion.error_set!SemanticVersion@1032c0930
zepl> std.json.parseFromSlice(struct {x: i32, y:i32}, alloc.*, "{\"x\": 10, \"y\": 0}", .{}) catch |err| err
json.static.Parsed(snippet_4.__snippet_4__struct_1667){ .arena = {...} , .state = {...}, .end_index = 0, .value = snippet_4.__snippet_4__struct_1667{ .x = 10, .y = 0 } }
// suppose testfile.zig has `pub fn sqr(i32) i32` and `pub var string_constant = "abc"`
zepl> const tst = @import("testfile.zig");
zepl> tst.string_constant
{ 97, 98, 99 }
// After changing the constant in the file "123" (by editing the file)
zepl> tst.string_constant
{ 49, 50, 51 }