- commit
- b5b525c
- parent
- b5e97df
- author
- Eric Bower
- date
- 2025-12-05 16:09:02 -0500 EST
refactor!: postfix uid for socket dir
- first we look for TMPDIR env var or else we default to `/tmp`
- then we look for ZMX_DIR env var or else we create a `/tmp/zmx-{uid}` folder
Since this is a breaking change, you can kill all of your previous
sessions by using `ZMX_DIR=/tmp/zmx zmx kill {sesh}`
Closes: https://github.com/neurosnap/zmx/issues/15
BREAKING CHANGE: this moves sockets to a new location which means none
of your previous sessions will be available
3 files changed,
+45,
-12
+7,
-4
1@@ -146,15 +146,18 @@ Wow! Now you can setup all your os tiling windows how you like them for your pro
2
3 ## socket file location
4
5-Each session gets its own unix socket file. Right now, the default location is `/tmp/zmx`. At the moment this is not configurable.
6+Each session gets its own unix socket file. Right now, the default location is `/tmp/zmx-{uid}`. You can configure this using environment variables:
7+
8+- `TMPDIR` => overrides `/tmp`
9+- `ZMX_DIR` => overrides `/tmp/zmx-{uid}`
10
11 ## debugging
12
13-We store global logs for cli commands in `/tmp/zmx/logs/zmx.log`. We store session-specific logs in `/tmp/zmx/logs/{session_name}.log`. These logs rotate to `.old` after 5MB. At the moment this is not configurable.
14+We store global logs for cli commands in `/tmp/zmx-{uid}/logs/zmx.log`. We store session-specific logs in `/tmp/zmx-{uid}/logs/{session_name}.log`. These logs rotate to `.old` after 5MB.
15
16 ## a note on configuration
17
18-At this point, nothing is configurable. We are evaluating what should be configurable and what should not. Every configuration option is a burden for us maintainers. For example, being able to change the default detach shortcut is difficult in a terminal environment.
19+We are evaluating what should be configurable and what should not. Every configuration option is a burden for us maintainers. For example, being able to change the default detach shortcut is difficult in a terminal environment.
20
21 ## a smol contract
22
23@@ -175,7 +178,7 @@ At this point, nothing is configurable. We are evaluating what should be configu
24
25 - The `daemon` and client processes communicate via a unix socket
26 - Both `daemon` and `client` loops leverage `poll()`
27-- Each session creates its own unix socket file `/tmp/zmx/*`
28+- Each session creates its own unix socket file
29 - We restore terminal state and output using `libghostty-vt`
30
31 ### libghostty-vt
+2,
-2
1@@ -13,7 +13,7 @@ pub const LogSystem = struct {
2 self.path = try alloc.dupe(u8, path);
3
4 const file = std.fs.openFileAbsolute(path, .{ .mode = .read_write }) catch |err| switch (err) {
5- error.FileNotFound => try std.fs.createFileAbsolute(path, .{ .read = true }),
6+ error.FileNotFound => try std.fs.createFileAbsolute(path, .{ .read = true, .mode = 0o640 }),
7 else => return err,
8 };
9
10@@ -82,7 +82,7 @@ pub const LogSystem = struct {
11 else => return err,
12 };
13
14- self.file = try std.fs.createFileAbsolute(self.path, .{ .truncate = true, .read = true });
15+ self.file = try std.fs.createFileAbsolute(self.path, .{ .truncate = true, .read = true, .mode = 0o640 });
16 self.current_size = 0;
17 }
18 };
+36,
-6
1@@ -67,17 +67,47 @@ const Client = struct {
2 };
3
4 const Cfg = struct {
5- socket_dir: []const u8 = "/tmp/zmx",
6- log_dir: []const u8 = "/tmp/zmx/logs",
7+ socket_dir: []const u8,
8+ log_dir: []const u8,
9 max_scrollback: usize = 10_000_000,
10
11+ pub fn init(alloc: std.mem.Allocator) !Cfg {
12+ const tmpdir = posix.getenv("TMPDIR") orelse "/tmp";
13+ const uid = posix.getuid();
14+
15+ var socket_dir: []const u8 = "";
16+ if (posix.getenv("ZMX_DIR")) |zmxdir| {
17+ socket_dir = try alloc.dupe(u8, zmxdir);
18+ } else {
19+ socket_dir = try std.fmt.allocPrint(alloc, "{s}/zmx-{d}", .{ tmpdir, uid });
20+ }
21+ errdefer alloc.free(socket_dir);
22+
23+ const log_dir = try std.fmt.allocPrint(alloc, "{s}/logs", .{socket_dir});
24+ errdefer alloc.free(log_dir);
25+
26+ var cfg = Cfg{
27+ .socket_dir = socket_dir,
28+ .log_dir = log_dir,
29+ };
30+
31+ try cfg.mkdir();
32+
33+ return cfg;
34+ }
35+
36+ pub fn deinit(self: *Cfg, alloc: std.mem.Allocator) void {
37+ if (self.socket_dir.len > 0) alloc.free(self.socket_dir);
38+ if (self.log_dir.len > 0) alloc.free(self.log_dir);
39+ }
40+
41 pub fn mkdir(self: *Cfg) !void {
42- std.fs.makeDirAbsolute(self.socket_dir) catch |err| switch (err) {
43+ posix.mkdirat(posix.AT.FDCWD, self.socket_dir, 0o750) catch |err| switch (err) {
44 error.PathAlreadyExists => {},
45 else => return err,
46 };
47
48- std.fs.makeDirAbsolute(self.log_dir) catch |err| switch (err) {
49+ posix.mkdirat(posix.AT.FDCWD, self.log_dir, 0o750) catch |err| switch (err) {
50 error.PathAlreadyExists => {},
51 else => return err,
52 };
53@@ -133,8 +163,8 @@ pub fn main() !void {
54 defer args.deinit();
55 _ = args.skip(); // skip program name
56
57- var cfg = Cfg{};
58- try cfg.mkdir();
59+ var cfg = try Cfg.init(alloc);
60+ defer cfg.deinit(alloc);
61
62 const log_path = try std.fs.path.join(alloc, &.{ cfg.log_dir, "zmx.log" });
63 defer alloc.free(log_path);