<feed xmlns='http://www.w3.org/2005/Atom'>
<title>slosh.git/Makefile, branch v0.1.7</title>
<subtitle>an opinionated terminal multiplexer in C with programmable pane chrome</subtitle>
<id>https://git.sl0p.foo/slosh.git/atom/Makefile?h=v0.1.7</id>
<link rel='self' href='https://git.sl0p.foo/slosh.git/atom/Makefile?h=v0.1.7'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/'/>
<updated>2026-09-02T14:22:03Z</updated>
<entry>
<title>slosh --install-terminfo: the binary carries its own terminfo entry</title>
<updated>2026-09-02T14:22:03Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-09-02T14:22:03Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=f9986df0da09cc692e168e33ef9ccfab5b9d2faf'/>
<id>urn:sha1:f9986df0da09cc692e168e33ef9ccfab5b9d2faf</id>
<content type='text'>
The xterm-256color fallback works everywhere; the real entry is
better, and a tarball user on a bare box had no easy way to get it.
The entry is generated from the vendored tree (contrib/terminfo, so
it describes the terminal core we actually ship), compiled with tic,
embedded as bytes, and written to ~/.terminfo under every name it
answers to, letter and Darwin-hashed layouts both. No root, no
package, no conflict with a ghostty installed later. Proven end to
end in a mount namespace: bare box falls back, installs, and the
next pane says xterm-ghostty.
</content>
</entry>
<entry>
<title>Add competitive multiplayer support.</title>
<updated>2026-09-02T12:51:02Z</updated>
<author>
<name>Ingmar Steen</name>
<email>iksteen@gmail.com</email>
</author>
<published>2026-08-31T12:43:32Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=29061a4aca5e3d645c0e23b885342036ac48f97b'/>
<id>urn:sha1:29061a4aca5e3d645c0e23b885342036ac48f97b</id>
<content type='text'>
Last input wins, canvas size is adjusted to active connection.
</content>
</entry>
<entry>
<title>shaders: remove the .so plugin loader</title>
<updated>2026-09-02T12:43:09Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-09-02T12:43:09Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=18d1aef0f9bf4620135fd9f77f26683e6f2f8c00'/>
<id>urn:sha1:18d1aef0f9bf4620135fd9f77f26683e6f2f8c00</id>
<content type='text'>
The static musl release builds cannot dlopen -- musl compiles it out
-- so loadable shader plugins were a feature most shipped binaries
could not use. Nothing we ship used it either: every shader in
contrib/shaders is an expression. Gone: the dlopen/glob loader in
shader.c, shader_dir in the config, the plugin ABI table and entry
macro, the Windows dl*/glob shims that existed only for it, the
contrib/shader-plugin skeleton, its tests, and every doc mention.
shader_abi.h stays as the shader model (cell_t, shade_ctx_t,
shader_t) with a note about what it used to be.
</content>
</entry>
<entry>
<title>web: the real site is the only site, and web/publish ships it</title>
<updated>2026-09-02T12:22:37Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-09-02T12:22:37Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=c36d7d07060f5d49a068724bc889a14460f16853'/>
<id>urn:sha1:c36d7d07060f5d49a068724bc889a14460f16853</id>
<content type='text'>
The coming-soon gate (FULL=1) and its page go: the site is finished
enough to be the default. web/publish (make www-publish) builds,
refuses to sync a tree that does not look like the site, and rsyncs
to /opt/slosh -- around /arch, which contrib/ship owns, and around
the served demo when a NO_DEMO build has none to offer.
</content>
</entry>
<entry>
<title>find zig on PATH instead of hardcoding ~/zig-0.16.0/zig</title>
<updated>2026-09-02T10:55:24Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-09-02T10:55:24Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=89dc98578d32cd9784869cd499ae7b9ea51da272'/>
<id>urn:sha1:89dc98578d32cd9784869cd499ae7b9ea51da272</id>
<content type='text'>
</content>
</entry>
<entry>
<title>docs: deprecate boring design narrative, more trimming and culling</title>
<updated>2026-09-02T10:32:45Z</updated>
<author>
<name>Peter Geissler</name>
<email>peter@haxx.in</email>
</author>
<published>2026-09-02T10:32:45Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=794e22914666775cab0b1b730a000b2529cec6b5'/>
<id>urn:sha1:794e22914666775cab0b1b730a000b2529cec6b5</id>
<content type='text'>
</content>
</entry>
<entry>
<title>graphics: a frame the client never got must be said again</title>
<updated>2026-08-29T19:31:41Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-29T19:31:41Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=8a8b5e1c7acd269d4a639a40712412a84480ad18'/>
<id>urn:sha1:8a8b5e1c7acd269d4a639a40712412a84480ad18</id>
<content type='text'>
A pane image is re-emitted to the client as decoded RGBA, which for one
screenshot is ~4MB of base64 in a single indivisible message -- and
conn_send silently dropped anything that would overflow the 4MB outbox,
while push_graphics ignored the refusal and the model advanced anyway.
Everything stateful in that dropped frame was lost for good: the image
was marked sent (so its placements drew nothing, forever), and the
deletions rode out with it (so a placement the client had was never
revoked). Reported as screenshots in a recovered pi transcript parked
at a fixed spot on the screen, immune to scrolling and pane swaps --
those were placements whose deletion left with a dropped frame. The
1000x800 one could never be delivered at all: its transmission alone
was bigger than the cap.

So the frame is now transactional. Deletions queue and are repeated
every flush until gfx_commit() confirms the client heard them;
transmissions recorded in a frame are unwound by an undelivered commit
so they are sent again. A flush nobody commits counts as undelivered at
the next gfx_begin(), which is what the `graphics` control command is:
bytes rendered for a CLI, not the client. The server reports the
verdict and keeps the paint pending until it lands.

The outbox cap now bounds the backlog rather than backlog-plus-message,
so one big transmission on a drained queue always fits -- and that
surfaced a second way to lose: a queued image legitimately holds the
backlog over the cap until the client swallows it, and push_frame read
that as a dead client and closed the connection. The session
auto-detached every time a screenshot crossed the wire. A full outbox
is a client that is *behind*, not gone: push_frame now marks the screen
for a full repaint (the dropped diff means the client's cells are
unknown) and retries as POLLOUT drains the queue; a client that truly
left still shows up as a write error there.

The headless suite pins the owed-until-committed contract; the new
tests/live_graphics.py drives the real socket with a
bigger-than-the-cap image and a reader that stalls, and would have
caught both bugs: the flood must not detach, the transmission must
arrive whole, and a placement scrolled away must be deleted -- then
come back on scroll without a second copy of the pixels.
</content>
</entry>
<entry>
<title>release: one command to bump, commit and tag</title>
<updated>2026-08-28T13:44:01Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-28T13:44:01Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=79df05ec1a3c38751956e8f6b122333ed3737efc'/>
<id>urn:sha1:79df05ec1a3c38751956e8f6b122333ed3737efc</id>
<content type='text'>
contrib/release X.Y.Z moves ./VERSION, commits and cuts the annotated tag
together, so the floor and the tag cannot disagree by construction. It
refuses a dirty tree, a detached HEAD, a malformed or non-increasing
version, and an existing tag; notes passed as the second argument land in
the tag message. It prints the push and `make release` commands instead of
running them, because publishing should be deliberate.

contrib/release --check verifies the invariant (VERSION equals the newest
tag) on its own: `make release` runs it before building anything, and the
new pre-push hook runs the same comparison against the commit a v* tag
points at, so a tag made by hand is caught before it escapes the machine.
</content>
</entry>
<entry>
<title>gitignore: DESIGN.md and .fastfeedback are local, not the project</title>
<updated>2026-08-28T13:38:41Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-28T13:38:41Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=a7a20bc026488928b6b65f44924b31615b898263'/>
<id>urn:sha1:a7a20bc026488928b6b65f44924b31615b898263</id>
<content type='text'>
DESIGN.md was a scratch design doc and .fastfeedback a per-repo tool cache;
neither belongs in the tree. Both stay on disk, ignored. Everything that
pointed at DESIGN.md now points at docs/design.md, and the decision counts
quoted from it (which had already drifted: the README said twenty-one, the
docs said twenty-two) are gone with it.
</content>
</entry>
<entry>
<title>windows release: a zip in dist/, built beside the linux tarballs</title>
<updated>2026-08-28T13:38:27Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-08-28T13:38:27Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/slosh.git/commit/?id=67e0330e5f18e4fe7f87db978071c6afa77ee91b'/>
<id>urn:sha1:67e0330e5f18e4fe7f87db978071c6afa77ee91b</id>
<content type='text'>
make -f Makefile.windows dist stages slosh.exe as
slosh-&lt;version&gt;-windows-&lt;arch&gt;.zip -- a zip, not a tarball, because Windows
is the machine that will open it -- carrying the same licensing paperwork as
the linux tarballs, with docs/windows.md riding along instead of the
manpages. `make release` now builds both architectures via release-windows,
so the windows zips land under the same SHA256SUMS as everything else.
</content>
</entry>
</feed>
