Skip to content

Releases: exviolet/sendoff

Sendoff v0.3.0 — Doctor, images by path, hardened preview

Choose a tag to compare

@exviolet exviolet released this 04 Sep 14:06

Three weeks of work: a first run that explains itself, images that reach the agent as
paths, workspace editing where you switch workspaces, and a markdown preview that is no
longer a route from a file you opened to your shell.

Upgrading from v0.2.0 is a drop-in replacement. Same app identifier, same data
directory, same database version — download the new AppImage and run it. Nothing moves,
nothing migrates, and rolling back to v0.2.0 works.

The first run now shows what Sendoff sees

Downloading Sendoff used to open an empty editor with "Untitled" and a placeholder — no
hint of what the thing is for. First launch now walks exactly one chain: see a target,
bind it, write, Ctrl+Enter, see the confirmation. No theme picker, no font picker, no
tour. Continue without a target and Escape are available at every step, because
without a target Sendoff is still a working editor and a mandatory wizard would be lying
about that.

It also stops at the honest boundary: Sendoff confirms that its send path ran, never
that the agent read anything. It cannot know the second one.

Sendoff Doctor

The empty picker was previously a dead end — no targets, no reason given. Two real
incidents were impossible to investigate after the fact: a send-path validator rejecting
a live handle, and IndexedDB becoming unreadable after a WebKit version change.

Doctor reports, per target, whether the executable is visible in Sendoff's own PATH
(a GUI launch does not inherit your shell's), whether discovery actually ran, and the live
handle the target hands back — the exact shape a send is validated against. Plus the
versions that decide whether your data is readable at all: Sendoff, Tauri, WebKitGTK, and
the data directory.

It only reports. It fixes nothing, configures nothing, and sends nothing to a live agent.
Ctrl+Shift+PSendoff Doctor, or from the first-run screen.

Images reach the agent as paths

Paste a screenshot with Ctrl+V, drop an image file into the editor, or pick one from the
palette — Sendoff inserts its absolute path into the prompt. Coding agents read images from
a path, so this is what actually arrives: the terminal carries text, not pixels.

Verified on both Codex and Claude Code with an image containing a random six-digit number
that does not appear in the filename. Both read it back correctly, so the channel works and
does not depend on which agent the tab is bound to.

A pasted image is written into Sendoff's own data directory; a file you dropped or picked is
referenced where it already lies and never copied.

Workspaces are editable where you switch them

F2 in the workspace switcher (Ctrl+Shift+W) opens rename and delete in place. Deleting a
workspace moves its tabs to the next one instead of discarding them, and says so before you
commit.

Security: the markdown preview is no longer a route to your shell

An internal review found a chain in v0.1.x and v0.2.0: a markdown file you did not write —
opened and previewed — could run JavaScript in the webview, and from there reach the shell
plugin. It required opening an untrusted .md and turning preview on; it was found in
review, not reported in the wild.

Three independent layers now close it:

  • Rendered markdown is sanitised before it reaches the DOM.
  • A strict Content-Security-Policy: scripts load from the app only, with no inline
    execution.
  • The tmux permission is scoped to four named subcommands with argument validators,
    instead of allowing arbitrary arguments. send-keys accepts the literal Enter and
    nothing else, so it submits and cannot type.

The last one is the layer that mattered: with arbitrary arguments allowed, injected
JavaScript could run commands in any pane. The security boundary in the README describes
the new model.

Also in this release

  • Global shortcuts no longer leak through open dialogs. Ctrl+W used to close the tab
    underneath a picker; a second picker could be stacked on the first.
  • When a session write fails, the reason is shown instead of being swallowed silently.
  • Cleaning up empty tabs no longer leaves an empty group chip behind, or a selection
    pointing at tabs that are gone.
  • The frontend, which lived in a separate sendoff-web repository behind a submodule, is
    now part of this repository with its full history. Source builds and ./update.sh no
    longer touch submodules.

Download

Sendoff_0.3.0_amd64.AppImage — x86_64 Linux.

sha256  6f8db75ff1bb9ca9306b2340f38457a6d3101f5807990fc2c08fe22877332a6b

Needs glibc ≥ 2.35 — Ubuntu 22.04+, Debian 12+, Fedora 36+, Arch. Built in an Ubuntu
22.04 container for that reason: an AppImage bundles its libraries but not glibc, so
building on a rolling distro would produce a file that only runs on rolling distros.

⚠️ Don't mix the AppImage and a source build on the same machine. The AppImage bundles
WebKitGTK 2.50, while current distributions ship 2.52+, which writes IndexedDB in a newer
metadata format and silently upgrades the database the first time it opens it. After that
the AppImage can no longer read it and shows an empty editor plus a storage error. Your
data is intact and is never overwritten — when Sendoff cannot read, it stops writing
altogether. Go back to the build you were using and your tabs are there.

Sendoff v0.2.0 — renamed from Rewrite

Choose a tag to compare

@exviolet exviolet released this 12 Aug 23:01

The project was renamed: Rewrite → Sendoff. Same editor, same database, new name.

The old name read as "AI paraphraser" — the one thing this editor deliberately is
not: it makes no network calls and has no API keys. It also collided with
OpenRewrite and with Microsoft 365's
"Rewrite" feature. Renaming before the project gets posted anywhere was the last
cheap moment to do it.

Upgrading from v0.1.x — your tabs move with you

The app identifier changed (com.rewrite.appdev.sendoff.app), which means the
data directory changed too. You do not need to do anything: on first launch
Sendoff moves ~/.local/share/com.rewrite.app to ~/.local/share/dev.sendoff.app
before it opens anything. It only moves when the old directory exists and the new
one does not, so it can never overwrite newer data, and it is safe to run twice.

Same for source builds — ./install.sh does the move as well, and refuses to run
while the app is open.

The database itself is untouched: same schema, same version, and it is still named
rewrite-db internally on purpose — that string is a path to your data, not a label.
Rolling back to a v0.1.x build works, as long as you move the directory back.

Download

Sendoff_0.2.0_amd64.AppImage — x86_64 Linux.

sha256  bcaff222dab8a2ea8870043da4efb47d7d1c436f5edb7282cc9a3e52a8a52b77

Needs glibc ≥ 2.35 — Ubuntu 22.04+, Debian 12+, Fedora 36+, Arch. Built in an
Ubuntu 22.04 container for that reason: an AppImage bundles its libraries but not
glibc, so building on a rolling distro would produce a file that only runs on
rolling distros.

Verified before publishing: the maximum GLIBC_* required across all 167 bundled
libraries is 2.35, and on a container with zero WebKit and zero GTK packages
installed it gets all the way to "Failed to initialize GTK" — it stops at the
missing display, not at a missing symbol.

It expects a normal desktop system for the libraries AppImage deliberately does not
bundle (graphics and text shaping: libGL, libEGL, libgbm, libdrm, libX11,
libX11-xcb, libxcb, libfontconfig, libfreetype, libharfbuzz, libfribidi,
libexpat). Any Linux desktop has them; a bare container does not.

⚠️ Don't mix the AppImage and a source build on the same machine. The AppImage
bundles WebKitGTK 2.50, while current distributions ship 2.52+, which writes
IndexedDB in a newer metadata format and silently upgrades the database the first
time it opens it. After that the AppImage can no longer read it and shows an empty
editor plus a storage error. Your data is intact and is never overwritten — when
Sendoff cannot read, it stops writing altogether. Go back to the build you were
using and your tabs are there.

Also in this release

  • Ctrl+Shift+, / Ctrl+Shift+. move the current tab along the bar, so reordering
    no longer needs PgUp/PgDn — those live on a function layer on 60% keyboards.
  • Dragging a tab one position to the right now actually moves it. It had been a
    mathematical no-op since the beginning: the tab was removed, the target slid into
    the freed slot, and inserting "before the target" put it back where it started.
  • Typing / at the start of a line or after a space opens an inline menu — your
    trigger phrases first, then markdown scaffolding. A slash inside a word (src/lib,
    12/08) stays plain text.
  • The window's app_id is now sendoff-desktop and the desktop entry's
    StartupWMClass finally matches it — they never did before, so window rules and
    launcher icon association can now be written against it.

Only the AppImage is published. The .deb and .rpm come out of the same build but
have never been installed on a Debian or Fedora system, and shipping untested
packages is a promise this project cannot back.

Previous releases (v0.1.0, v0.1.1) are left exactly as they are — the sha256
recorded in their notes stays true. They are named Rewrite_* because that is what
the project was called then.

Rewrite Desktop v0.1.1

Choose a tag to compare

@exviolet exviolet released this 11 Aug 08:19

A bugfix release. If you downloaded v0.1.0, replace it — that build can lose
your tabs, and the failure is silent.

Why this exists

Opening Rewrite twice could wipe your data. Saving is not incremental: each
save clears the stores and rewrites them from the snapshot in that instance's
memory. So a second window did not even have to be used — closing it flushed its
own, older snapshot over everything the first window had written since. There was
no warning, and nothing in the UI hinted at it.

v0.1.1 refuses to start a second instance: the second launch exits immediately
and no second window opens. The guard has to be native — the browser mechanisms
for this (BroadcastChannel, Web Locks) do not reach outside a single webview
process.

It also asks the existing window to come forward, and that part does not work
on Wayland: compositors ignore an activation request from a process you did not
just interact with. Measured on niri, identically from this AppImage and from a
source build. So on Wayland a second launch looks like nothing happened — which is
correct behaviour, just not obvious. The README says so too.

A failure to read the database now says so. Previously the cause was swallowed
and you got an empty editor with a vague toast — indistinguishable from having no
data. There is now a banner that states three things: what you type right now will
not be saved, existing data has not been touched, and what usually causes this.
The underlying error goes to the console instead of being discarded.

That failure has one known cause worth naming: WebKit changed its IndexedDB
metadata format between 2.50 and 2.52.
This AppImage ships 2.50 (Ubuntu 22.04,
for glibc compatibility). If you have already run Rewrite built from source on a
current rolling distro, that build silently upgraded your database to the new
format and this AppImage can no longer open it — the direction is one-way and no
code change fixes it. Pick one: the AppImage, or a source build. Do not alternate
between them on the same machine.

Your data survives either way: the app refuses to write when it could not read.

Download

Rewrite_0.1.1_amd64.AppImage — x86_64 Linux.

chmod +x Rewrite_0.1.1_amd64.AppImage
./Rewrite_0.1.1_amd64.AppImage

Requires glibc ≥ 2.35 — Ubuntu 22.04+, Debian 12+, Fedora 36+, Arch.

Built the same way as v0.1.0: in a container on Ubuntu 22.04, because an
AppImage bundles its libraries but not glibc. It still expects the libraries
AppImage deliberately never bundles — X11/Wayland, OpenGL, fontconfig, freetype.
Every Linux desktop has them; a bare container does not.

.deb and .rpm come out of the same build but are not published: nobody has
installed them on Debian or Fedora, and an untested package looks like a support
promise this project cannot back.

What Rewrite is

A prompt-first editor: write the prompt in a real editor instead of a cramped
terminal input, then send it straight into your agent's terminal with Ctrl+Enter
— tmux, Herdr, or
Orca. See the
web README for what it does.

Everything else in this release is documentation

No features were added. The README now warns against mixing the AppImage with a
source build on one machine, and the demo recording was replaced — the old one was
from June and showed an indicator that no longer exists.

Honest scope

Unchanged from v0.1.0: Linux-only, x86_64 only, no auto-update, no
Windows/macOS builds. Tests cover pure logic and the IndexedDB layer; components
and hooks are not covered. This is a personal tool made public as a portfolio
piece — it works for its author, but no support or stability is guaranteed, and
issues may sit.

Contributions aren't being solicited — fork freely instead.

Rewrite Desktop v0.1.0

Choose a tag to compare

@exviolet exviolet released this 09 Aug 14:17

Warning

Superseded by v0.1.1 — please replace this build.
This one has no single-instance guard, so opening Rewrite a second time can
silently destroy your tabs: a save rewrites the whole snapshot, and the second
window flushes its older view over everything the first one wrote. Nothing warns
you.

The file below is untouched and its sha256 still matches what this page has
always claimed — nothing here was swapped.

First prebuilt artifact. Not the first version of the app — Rewrite has been in
daily use for months and built from source until now. This release just means
you no longer have to.

Download

Rewrite_0.1.0_amd64.AppImage — x86_64 Linux.

chmod +x Rewrite_0.1.0_amd64.AppImage
./Rewrite_0.1.0_amd64.AppImage

Requires glibc ≥ 2.35 — Ubuntu 22.04+, Debian 12+, Fedora 36+, Arch.

Built in a container on Ubuntu 22.04 on purpose: an AppImage bundles its
libraries but not glibc, so an artifact built on a rolling distro only runs on
rolling distros.

It also expects the libraries AppImage deliberately never bundles — X11/Wayland,
OpenGL, fontconfig, freetype. Every Linux desktop has them; a bare container
does not.

Verified before publishing: launched in a clean ubuntu:22.04 with no dev
packages and no system WebKitGTK (it reached GTK init and stopped only for the
missing display — so all 167 bundled libraries loaded and WebKit came from the
AppImage), and launched again on Arch against a real display.

.deb and .rpm come out of the same build but are not published: nobody
has installed them on Debian or Fedora, and an untested package looks like a
support promise this project cannot back.

What Rewrite is

A prompt-first editor: write the prompt in a real editor instead of a cramped
terminal input, then send it straight into your agent's terminal with
Ctrl+Enter — tmux, Herdr, or
Orca. See the
web README for what it does.

Notable in this build

  • UI is English throughout. It used to mix English and Russian — sometimes in
    adjacent buttons of the same panel.
  • Customisable keyboard shortcuts (Ctrl+/, click a chord to rebind).
  • Closed tabs survive a restart — archived and restored with Ctrl+Shift+T.
  • Live agent status in the status bar: a quiet dot while the agent works, a
    visible label only when it is blocked waiting for you.
  • One target picker for tmux / Herdr / Orca (Ctrl+Shift+Enter).

Honest scope

Linux-only, x86_64 only, no auto-update, no Windows/macOS builds. Tests cover
pure logic and the IndexedDB layer; components and hooks are not covered. This
is a personal tool made public as a portfolio piece — it works for its author,
but no support or stability is guaranteed, and issues may sit.

Contributions aren't being solicited — fork freely instead.