The panels keep their headline under a tall terminal
- Dragging the terminal panel up far enough left the row above it with less height than a side panel needs for its own chrome — and SwiftUI takes that overflow off both edges at once, so the Vault button, the panel switcher and the folder title went off the top of a sidebar that was otherwise still perfectly visible. The empty bottom of the tree hid the other half of the loss, which is why it read as the headline having been dropped rather than as the panel being too tall. The right dock lost its switcher the same way.
- The terminal’s height is now answered against the space the window actually has, and it will not take the row above it below what a panel needs. A height too big for the window now is kept rather than corrected, so the panel goes back to it when the window grows — the same bargain full height already made — and the resize drag clamps by that rule too, so the pointer stops where the panel does instead of travelling on with nothing following it.
Known limits in 1.17.1
- A vault holds up to 5 MiB of encoded documents, and changing its password rewraps the same content key rather than replacing it — rotation answers a credential you no longer trust, not the key itself having escaped.
- Touch ID and Mac-password unlocking need a build signed with a provisioning profile, which the download here is; a vault still opens with its password and recovery key everywhere else.
- There is still no watchdog over a plugin’s own script: one that never returns hangs the app, because the only way to interrupt it is private API that cannot ship on the App Store.
- Code folding and recorded macros remain roadmap items with no promised date.
An encrypted vault
- File ▸ Vault…, or the side panel’s Vault button, opens a window of its own: its own plain-text editor, its own commands, its own
.linelarkvault file. A password unlocks it, a recovery key issued at creation is the way back in without one, and on a Mac that has Touch ID it can be opened with a fingerprint or your login password. - Nothing in it becomes a document, and that is the feature rather than a note about the implementation. Tabs, session snapshots, the unsaved-buffer backups, Recent Files, plugin previews and the agent’s view of your editor are each somewhere plain text would otherwise land — and every one of them is reached by a file being an ordinary document. So this is not an encrypted file type the editor opens; opening the extension routes away from the editor entirely rather than making a tab of it.
- A random 256-bit content key is wrapped by each credential, rather than the documents being encrypted with your password. That is what makes changing the password instant, makes the recovery key an alternative to it rather than a second factor, and makes Touch ID a third door onto one room. The local door is the data-protection Keychain under user presence, so macOS enforces the authentication as the key is retrieved — not this app asking a question in front of a read nothing is stopping. It is device-only and never synchronized, because the password and the recovery key are what carry a vault to another Mac, and a Keychain that syncs is a vault that has left.
- It locks on the window closing or minimizing, on sleep, on screen lock, on switching user, and after 1, 5 or 15 idle minutes, clearing the documents, the key, the text view and its undo stack. Only ciphertext is ever written, atomically and coordinated, debounced while you type and flushed by every way of leaving. A write that fails keeps the encrypted state in memory, says so, and refuses the quit rather than losing what you typed.
- Security ▸ Delete This Vault… retires the enrolled Mac key and its Keychain reference and then moves the file to the Trash, in that order — a failure at the Keychain has to leave the file where it is rather than delete it and strand a key nothing can ever name again. Deleting the file in the Finder is still yours to do, and still leaves that key behind; this is the route that leaves nothing.
Bookmarked files
- The document icon on a tab is now a button — grey when the file is not kept, blue when it is — with ⇧⌘D and File ▸ Bookmark This File saying the same thing from the keyboard. The unsaved dot moved onto the ✕, which is the button that would throw that work away.
- The side panel gained a pane of its own, with folders you make rather than folders on disk: the four files a bug lives in across three projects is exactly the grouping a filesystem cannot express. Rows are dragged into folders or above one another, dropped in from the folder tree or the Finder, and searched by the bookmark’s name or the file’s.
- The library is yours, not a window’s, so it is the same list in every window. It follows a rename made in the folder tree and forgets a file deleted there, while a file that is merely not there — an unmounted volume, a branch switched away — is drawn as missing and kept.
The titlebar says which project
- A window opened on a folder or a
.code-workspace read “Linelark” in the titlebar regardless, exactly as an empty one did, so two windows on two projects were told apart by clicking into them. It now carries the project’s own name — the workspace’s, the folder’s, or “3 Folders” for several with no name between them — and follows a root being added or removed while you watch.
Space previews a row in the folder tree
- The rows this editor cannot open — an image, a PDF, an archive, a
.docx — had exactly one thing they could do when clicked: put up a dialog explaining that the file does not look like text. That warning is about saving, and it is right for every route that ends in a tab, but as the whole of what such a row offers it stood between you and the one useful thing there was to do with it. - Space previews the selected row with Quick Look, exactly as it does in the Finder, and Space or Esc closes it again. Those rows now select on a click rather than opening, which is what makes Space the way in rather than the second thing tried. Only while the folder tree has the keyboard — with an editor focused, Space is a character you are typing.
A split terminal asks what it is about
- Splitting the terminal took the binding of the shell it came from and started in whatever directory that shell had
cd’ed to, which read as the panel guessing rather than answering. The new column now puts up the same chooser a first shell is asked — this file, or which project folder — beside the pane it split from. That pane keeps the keyboard throughout; only the new column asks.
Known limits in 1.17.0
- A vault holds up to 5 MiB of encoded documents in this first version.
- Changing the password or issuing a new recovery key rewraps the same content key rather than replacing it, so rotation is the answer to a credential you no longer trust and is not an answer to the key itself having escaped. Re-keying has to demand the password, issue a new recovery key and ask for Mac unlock to be enrolled again, and it is not in this release.
- Touch ID and Mac-password unlocking need a build signed with a provisioning profile, which the download here is; a vault still opens with its password and recovery key everywhere else, and a build without one now says so in those words rather than reporting a missing entitlement.
- Quick Look is offered for the rows the editor cannot open. A text file opens on the click that selected it and has nothing left for Space to show.
- There is still no watchdog over a plugin’s own script: one that never returns hangs the app, because the only way to interrupt it is private API that cannot ship on the App Store.
- Code folding and recorded macros remain roadmap items with no promised date.
Closing the last tab leaves the window standing
- Safari’s rule was here first, and it threw away the thing you are most likely to want next. The page that replaces the last tab is the list of files and projects to carry on with — and a window that vanishes takes that list with it, along with the folder tree, the shells and the agent it was holding.
- ⌘W again, with nothing left to close but the window, closes it. The gesture still ends in the same place; it is two presses now, and the second is the one that cannot be undone. Close All has always emptied a window and left it standing, and a tab’s own ✕ cannot take a window with it however few tabs are left.
- ⇧⌘N opens on that same page, which is the other half of the thought: a new window is not made with a file already in mind, it is made when there is somewhere else to go, and the page is the list of where. A window opened for something — a project double-clicked in the Finder — shows no page at all, because the question it asks has just been answered.
The welcome page says what makes this a development environment
- Git, a build, something to run, a rendered document and a side-by-side diff are what somebody arriving from VS Code or Xcode expects an editor to already have. In Linelark each of them is a plugin — a deliberate split, since the editor stays small and what a particular kind of work needs is installed — but it only works if the person who needs them is told they exist. On a first launch both recent lists are empty, so what was on screen was four buttons and a link.
- Under the recent files and projects there is now a short, named list: GitHub, Build and Run, Launcher, Document Preview and Compare Files, each with a line about what it adds, and a sentence saying plainly that these are recommendations for that one purpose and that none of them is required. Five rather than the catalog, because a recommendation that lists everything is not one — the rest is a click away in Browse all plugins…
- Clicking a name installs it, through the reviewed catalog and nothing else: same checksum, same permission prompts, same questions Get Plugins… asks. The catalog is fetched at the moment you click rather than when the page is drawn — the list itself is compiled into the app precisely so that opening a window asks the network for nothing.
- Installed ones drop out, and the section goes with the last of them. A page that goes on recommending what is already there is a page you learn to skip.
- The Mac App Store edition offers only the two that work in it. The sandbox has no terminal, no git and no network for plugins, so the other three would install perfectly there and then draw a panel that does nothing — which reads as a broken plugin rather than as an edition that cannot carry it. That edition may not fetch code at all, so a click there opens the plugin page on linelark.com, where the download and Plugins ▸ Install Plugin… are the way in.
A project double-clicked in the Finder gets a window of its own
- Opening a folder or a
.code-workspace over the front window was the one Finder gesture that could take work away without asking. The tabs survived, but the folder tree, the search scope, the shells and the agent all belonged to the project that was there — and the window you double-clicked from is by definition not the one you were looking at. - A window holding nothing — no project, and nothing typed into it — is filled rather than left behind for you to close afterwards. Files are unchanged and still join the window last used, which is what a second
open on VS Code does.
⌘⌫ moves the selected row to the Trash
- The Finder’s gesture on the Finder’s key, through the confirmation the folder tree’s Delete… item already put up.
- The whole difficulty is that ⌘⌫ already means delete to the beginning of the line inside every text view on this platform, and a menu item’s key equivalent beats whatever is typing. So File ▸ Move to Trash is enabled only while the folder tree holds the keyboard — a disabled item does not take the key at all, and the keystroke goes where it always went.
Get Plugins… says when a plugin runs commands
- The one line under each plugin was computed from git and network access alone, so Build and Run — which asks to type
xcodebuild into a shell and to run a command out of sight and read what it printed — was described to the person about to install it as “No network or git write”. Three true words that together said the opposite of the truth, on the one screen where that decision is made. The Launcher had been described the same way since it shipped. - Running commands is named first now, because it is strictly heavier than either of the others: anything git write or a host grants, a command can do anyway. Nothing had to be resubmitted — the capabilities come from the manifest stored with each release, so regenerating the feed describes the old ones correctly and leaves their archives and checksums untouched.
Known limits in 1.16.0
- The recommended list is compiled into the app, which is what keeps the welcome page from asking the network for anything until you click. A plugin published after a release is not named there until the next one — the catalog always has everything.
- Installing from the page is Studio’s. The Mac App Store edition fetches no code at all, so a click there opens the plugin page on the site and the install is the one it has always been: download, then Plugins ▸ Install Plugin…
- ⌘W on the last tab of the only window still quits Linelark, on the second press — there is nothing else for a window to go to.
- There is still no watchdog over a plugin’s own script: one that never returns hangs the app, because the only way to interrupt it is private API that cannot ship on the App Store.
- Code folding and recorded macros remain roadmap items with no promised date.
A new version is offered from the titlebar
- The Studio edition has never had a way to learn that a new version exists. The App Store keeps the sandboxed build current; the direct download has relied on you going to look. A button now appears beside Linelark’s own name when a newer release has been published — Update to Linelark 1.16.0 — counts the download up in its own title, and then offers to open the verified image.
- There is no button the rest of the time, which is almost all of the time. One that sat there saying “up to date” would be a permanent reminder of a question nobody asked.
- It reads the same manifest the download page reads, so the app and the site describe one release rather than two. Taking a download from the network is a larger thing than reading a version number, though: it cannot name a host —
https on downloads.linelark.com, compiled in — and the checksum in the manifest proves only that the bytes arrived intact, since whoever writes the manifest writes its digest too. What proves the image is Linelark is its Developer ID signature, checked against this project’s team before the image is ever offered. - Verifying is not installing. It stops at a checked image in your Downloads folder and opens it, so the drag to Applications stays yours and Gatekeeper still checks notarization at first launch. Replacing a running app needs a helper that outlives it, which is the most security-critical code an app can carry and is not worth adding for the sake of one drag.
Plugins can read what a command printed
- A plugin could already hand command lines to a shell in the terminal panel, where you can watch them, stop them and answer a password prompt — and get nothing back. That is right for a build and useless for
xcodebuild -list -json, so a panel that wanted to offer the schemes in a project, the targets in a Makefile or the scripts in a package.json had to ask you to type what the tool already knows. runQuery is the missing half: one command, no shell, no terminal, resolving with an exit status and the two streams. The host API is at generation 12.- It is its own declaration and its own switch, not a wider reading of the one that already exists. An ordered permission where “may run commands in the terminal” implied “may run hidden commands and read their output” would have widened a yes already on disk without asking anybody — and a plugin genuinely needs both, since a shell you can watch and a query that reports back are not versions of each other.
- There is no list of blessed executables, because that would only put some particular toolchain’s vocabulary in the editor. What is enforced is the part that is not theatre: no shell at all, so quoting is not a category of problem; an argument list refused whole if anything in it is not a string, since a value vanishing out of the middle of an argv yields a different command rather than a failed one; a deadline; a size cap enforced as the bytes arrive; and a command that fails reported as an answer rather than as an error, because tools exit non-zero for ordinary reasons.
The terminal header lost two buttons and gained a useful one
- The pin and Clear are gone from the header. A pin is a statement about a tab closing hours from now, sitting beside buttons that do something the moment they are pressed — and on a project terminal it was not even a control, just a filled pin saying “this one stays”. Clear sat next to the restart arrow looking like a second way to say the same thing. Both keep their place in the Terminal menu, where Clear already had ⌃⌘K.
- In their place is ⇄, the button the Claude Code panes have: it ends the shell and puts the chooser back up, so a terminal that should now be about a different file or project is two clicks rather than a hunt through the picker.
- And the restart arrow now restarts the pane whose header it is. In a split it acted on whichever column had the keyboard, so pressing it in one column could restart the other.
A release can no longer quietly lose the one before it
- Publishing overwrites the single manifest the site reads, so the version being replaced has to be copied into the public archive first — a hand step that had been missed twice, taking 1.6.2 and 1.7.0 off the download and changelog pages while their versioned URLs went on serving them perfectly well.
- The deploy now refuses to publish while the live version is missing from that archive, and asks before the build rather than after five minutes of compiling and a round trip to Apple. It is asked of the published manifest rather than of the checkout, because the version at risk is whichever one is actually live.
Known limits in 1.15.0
- The update button offers a download; it does not install one. There is no background update, no silent replacement, and nothing is ever fetched without the button being pressed.
- The check is Studio-only, as is everything a plugin query touches. The Mac App Store edition updates itself and has no terminal, no network for plugins and no command running at all.
- A plugin’s query has to come from something you clicked, and an
await ends that click — so two queries awaited one after the other lose the second, and a plugin asks for several at once instead. Loosening it would mean a plugin that can start processes with nobody at the machine. - There is still no watchdog over a plugin’s own script: one that never returns hangs the app, because the only way to interrupt it is private API that cannot ship on the App Store.
- Code folding and recorded macros remain roadmap items with no promised date.
The folder tree and the plugin panels follow the filesystem
- The tree has always needed a button pressed, and so has every plugin panel. A file made in the terminal, a branch switched, a
git pull, an agent writing to disk — all of them left both describing a state that was no longer true, and the only way to find out was to ask. - There is now one watch per window over the folders that window has open, and it follows those folders by construction rather than by every command that changes them remembering to say so.
- An event is classified once, into two things. Relisting a directory is what the tree needs and is wasted on a
git status; a panel’s redraw is ten subprocesses in the GitHub panel’s case and is wasted on a file whose bytes changed where it already sat. One rule does the whole of it — a hidden entry is content and never listing, because the tree does not draw hidden entries — which is exactly why a commit made in a terminal reaches the GitHub panel and leaves the tree alone. - A burst is one refresh. Without that, a save is three refreshes and an
npm install freezes the tree for its whole duration, because a debounce that keeps restarting never gets back to rest.
Reveal in Folder Tree
- On a tab’s context menu and on every Find in Files result: the tree opens the folders down to that file, scrolls to it and marks it. Before this the tree could highlight the front tab but never reveal it, so a file reached from a search was drawn as selected only if its folders happened to be open already — a highlight on a row nobody could see.
- What it needed first was for the tree to stop keeping its open folders inside each row. That state could not be reached from a search result or a tab, and it was thrown away whenever the sidebar switched panels — so the tree also forgot its shape every time you glanced at the function list. That is fixed for nothing as a consequence.
- Recent Files does not have one yet.
⌘W closes the window when it closed the last tab
- It closed the tab and stopped there, so closing tabs one by one ended at a window that ⌘W then did nothing to at all. Close Window is on ⌥⇧⌘W, which nobody reaches for by accident, so the honest description of the old behaviour is that the window could not be closed from the keyboard by someone who did not already know that.
- Safari’s rule, which is what ⌘W means on this platform: the tab goes, and if it was the only one the window goes with it. Only from the three gestures that mean “close this one” — ⌘W, the tab’s ✕ and its Close item — and never from Close All, which is a statement about tabs and deliberately leaves the window standing. The app quits after its last window closes, so ⌘W on the last tab of the only window quits Linelark, after the same unsaved-changes question.
The Claude Code panel reaches your tabs on first launch
- The right dock shipped two panels side by side and only one of them could read the tabs above it. The panel running the vendor’s
claude exported the socket and nothing that read it, so it reached the editor only after somebody found Set Up Claude Code Integration… and ran it — which most never will. - The app is the one launching that pane, so it now simply says so on the command line. The installed integration is not made redundant: it stays the route for every shell the app does not launch — the panel below the editor, iTerm, anywhere else — and only a registration can serve those.
- Unlike the headless panel, this one is not narrowed to Linelark’s own tools and nothing is pre-approved. A panel whose whole premise is the vendor’s tool unmodified is the last place to drop the MCP servers you configured, and a prompt in a terminal you are watching is a question you can answer.
The terminal can draw with Metal
- Preferences ▸ Terminal ▸ Draw with Metal, off by default. The path it replaces lays out every visible row through CoreText on each invalidation, and a scroll invalidates the whole view, so scrolling a tall pane costs most of a core for as long as the trackpad is moving.
- Turning it on needs nothing installed and nothing rebuilt — the shader is compiled once at first use, about 150 ms — and a renderer that will not start leaves the view where it was and says why in the same pane rather than failing silently.
Plugins can import a web page
importWebPage() opens a browser the user drives: they type the address, watch the page load, review what was extracted and press Import. Nothing reaches the plugin until then, and what it gets is the text, the title, the URL and the format — never a bridge into the page, shared cookies, or a way to evaluate script in it.- It has to be called straight from something you clicked, so a plugin cannot put a browser on screen from a timer. The host API is at generation 11.
Two things that were in the way
- A backup now costs what you typed, not what you have open. The session snapshot copied every unsaved buffer out whole a couple of seconds after each burst of typing, so a large unsaved file was rewritten in full for one line. Above 64 KB the edits are appended beside the snapshot instead, and the snapshot itself is rewritten only when that record has grown to half its size. Every record carries its own length and checksum and is replayed only as far as it checks out, because the crash a backup exists for can land in the middle of writing one.
- A rebuilt pane no longer takes the keyboard out of a shell. Hosting an editor and focusing a terminal both have to finish on the next turn of the run loop, so which one the app reached second decided who had the keyboard — and that order shifts with how the app was built. A pane rebuilt around the tab already in it now asks for nothing at all: only a tab arriving in a pane takes the keyboard, which is you asking for that document.
Known limits in 1.14.0
- The watch is FSEvents, which reports local volumes. A project on a network share may produce nothing at all, and the panel header’s refresh button and View ▸ Refresh Folder Tree remain the answer there.
- It does not reload your open tabs, and that is deliberate: relisting a directory is not a decision and replacing what is on screen is. A tab with no unsaved edits still reloads itself while a shell or a writing agent is running, and otherwise you are asked the next time the app comes forward.
- The Metal renderer and the Claude Code panels are Studio only — the sandboxed Mac App Store edition has no terminal at all — and so is the web importer, which needs WebKit and the network.
- Backups are journalled only above 64 KB, and the snapshot is still rewritten whole each time the journal reaches half of it, which a long session editing one large file reaches more than once. Nothing is flushed to the disk by force, so what a power cut costs is whatever the filesystem had not yet written — the same bargain the snapshot has always made, and the reason the debounce is seconds rather than minutes.
- The keyboard is settled for a pane being rebuilt, not for the first pane of a window appearing in the same moment a terminal asks for focus: both of those are somebody asking, and the later one still wins. It takes a window opening straight onto a terminal to reach it.
- Code folding and recorded macros remain roadmap items with no promised date.
The agent can be handed your own Claude Code rules
- Until now the panel’s Claude could read your buffers and propose edits, and that was all it could do: the build, the tests and every other command were simply not among its tools. An agent that cannot run the build cannot check what it just wrote, so it could only ever hand you something to try.
- Preferences ▸ Claude now offers a second answer. Claude Code’s Own Rules gives the panel the full tool set and stops pinning a permission mode, so what is approved without asking is decided by your own
settings.json — the same rules, and the same mode, as the claude you run in a terminal. - Linelark adds nothing on top of them. It pre-approves its own editor reads and never a built-in, so nothing here can approve
Bash on your behalf; that decision stays in the one file where you can read it back, scope it to a project, or take it away. Anything your rules still leave to a person is asked in the panel exactly as a buffer edit is, with the command on the card. - Read-Only stays the default, and updating to 1.13.0 changes nothing about what the agent can already do. A window can also disagree with the app: the panel’s ⚡ menu sets the trust for that window alone, which is where the triggers and autostart already live.
The welcome page opens with the app
- It has listed your recent files and recent projects since it was written, and almost nobody has seen them. It was the empty window — and with session restore on by default, a window with nothing in it is a moment that after the first launch nearly never comes.
- It now opens with the app, drawn over the pane with the tab strip left in place above it, so everything the last session restored is visible and one click away. Clicking a tab is what dismisses it, as is opening or creating anything.
- Not when you opened the app at a file, though: double-clicking a document still goes straight to it, because a page in front of it would be answering a question nobody asked. There is a switch on the page itself, another in Preferences ▸ Files, and Help ▸ Welcome to Linelark brings it back after you have turned it off.
Known limits in 1.13.0
- On Claude Code’s own rules the agent has the built-in
Edit and Write, and those write to disk rather than into the buffer. Such an edit is not one ⌘Z and was not shown to you as a diff first. A tab with no unsaved changes reloads itself; a tab with unsaved changes is left alone and asks you the next time the app comes forward. The editor’s own tools still land in the buffer and the agent is told to prefer them, but it is free not to. - What gets approved without asking is whatever your
settings.json already says, an auto-approving mode included. Linelark deliberately offers no second opinion on it — that is the whole of what the setting means, and it is why Read-Only is what you keep until you choose otherwise. - The panel still never sees the MCP servers in your own
~/.claude.json, under either trust: it gets this window’s editor tools and nothing else. That is a question about which servers a panel talks to rather than about who approves what, and it has not changed. - The Claude panel remains Studio only. It spawns a process and opens a socket, so the sandboxed App Store edition has none of it, and the trust setting with it.
- The welcome page opens on every window a launch restores, not only on the one that ends up in front.
- Code folding and recorded macros remain roadmap items with no promised date.
Registre permanent de l’artefact
- Aucune note de version détaillée n’a été publiée pour cette version. Cette page conserve l’identité de l’artefact, son build, sa date de publication, son empreinte et son commit source, plutôt que d’inventer une histoire après coup.
- L’image disque versionnée reste immuable et peut toujours être vérifiée face à l’empreinte SHA-256 indiquée ci-dessous.
A plugin can run commands — in a terminal you can watch
- A plugin that declares
"terminal": "run" and is granted it can hand command lines to a shell in the terminal panel, which is then shown. It does not get a process of its own: the commands are typed at a shell, exactly as you would type them. - Nothing comes back to the plugin — no exit status, no output, no promise — and that is the design rather than a gap in it. Anything given a hidden process would need somewhere to put its output, a way to be stopped, and a way to answer a password prompt. The panel is already all three: the output scrolls where you can read it, ⌃C stops it, and ↑ runs it again long after the plugin’s panel is closed.
- It takes a click. A timer cannot start anything, nor can a panel drawing itself, nor anything after an
await — which ends the gesture the host checks for. A plugin that runs commands while nobody is at the machine is the thing this rule exists to prevent. - Its own switch in Manage Plugins, kept apart from network and git because it contains both: a command can do anything you can do. Granting either of the others never grants this, and revoking it stops the next command rather than the next launch.
Launcher, in the plugin catalog
- The applications a project is made of — a server, a worker, a watcher, a test run — each with its folder and the two or three lines that start it, one click away and each in its own shell. Running the same one twice goes back to the pane it used rather than opening another.
- It is also the worked example for a panel that saves as you type: there is no Save button, because a form that gathers what is typed and commits it on a click loses the last half-second before that click.
A folder picker that asks for nothing
chooseFolder puts an open panel on screen and hands back the one folder somebody picked. It needs no declaration and no switch, for the reason exportFile never needed one: the panel is the permission. A plugin still cannot name a directory and be given it.
One thing that was slow
- The session snapshot rewrote every unsaved buffer whenever any one of them was typed in — each rewrite bridging a whole storage string on the main thread — so a window holding a few large dirty buffers paid for all of them a couple of seconds after every burst of typing. It now writes only the buffers whose text actually moved.
Known limits in 1.11.0
- A plugin is never told what happened to what it ran. There is no exit status and no output, so a panel can say a command was started and nothing more; what happened is in the terminal.
- Running commands is Studio only — the sandboxed Mac App Store edition has no terminal panel at all. A plugin cannot tell that apart from a permission nobody has granted yet, since
canRunInTerminal() is one boolean, so a good one names both. - A second run types into the same shell. If what you started last time is still running — a server, a watcher — the new lines go to that program’s input, exactly as they would if you typed them at it.
- Commands are typed as one line joined with
;, so each runs whether or not the one before it worked. Ask for the other thing by writing && yourself. - Code folding and recorded macros remain roadmap items with no promised date.
Registre permanent de l’artefact
- Aucune note de version détaillée n’a été publiée pour cette version. Cette page conserve l’identité de l’artefact, son build, sa date de publication, son empreinte et son commit source, plutôt que d’inventer une histoire après coup.
- L’image disque versionnée reste immuable et peut toujours être vérifiée face à l’empreinte SHA-256 indiquée ci-dessous.
Two view options that had been waiting since the beginning
- Virtual space (View ▸ Virtual Space) lets the caret stand past the end of a line. The reason it earns its place is vertical: ↓ through a ragged block keeps the column it started in instead of collapsing onto the end of every short line it crosses and arriving somewhere to the left.
- Only the drawing moves. The selection stays a range over characters that exist, so undo, the tools, the find bar and Claude never see a position that does not. Typing is what makes the columns real — padded with spaces and never tabs, whatever your indentation preference says, because a tab is a jump to the next tab stop and lining up is the whole point.
- Wrap indicators (View ▸ Show Wrap Indicators) put a
↵ where the editor broke a line because it ran out of width, so a long line reads as one line rather than as several short ones. Drawn just after the text rather than out at the right margin: this editor’s wrapped width follows the window, and a full-width indicator column sits a long way from the line it belongs to on a wide screen.
A last group in the toolbar, for the app itself
- Behind its own divider: starting and stopping Claude, with the title carrying what the conversation has cost, and a star that opens the App Store listing with the review sheet already up. Neither is about the text in front of you, so nothing you reach for while editing sits after them.
Claude’s model list stops depending on this app’s release cycle
- What goes stale about a command-line agent is not its protocol, which moves about once a year, but the model aliases and effort levels it accepts, which move monthly. Those were compiled in, so a model gaining a name cost a rebuild, a notarization and — for the App Store edition — a review: days of latency on a one-word change.
- They are published beside the plugin catalog now and fetched the same way, cached on disk, falling back to what shipped in the binary when there has never been a fetch. What makes it safe to take instructions about a subprocess from the network is that a profile carries values, never commands: the executable and the flags stay compiled in, and an alias must begin with an alphanumeric, so nothing that looks like an option can become one.
Two things that were wrong
- ⌘F opened the find bar without giving it the keyboard, so it had to be followed by a click.
- A window showing a plugin panel could spin at 100% of a core inside a single layout pass — no drawing, no events answered, nothing in the log. The window’s geometry and the panel’s lazy stack were each invalidating the other; the panel’s nodes are drawn eagerly now, which removes one of the two.
Known limits in 1.9.0
- Virtual space is off under word wrap, where a logical line is several rows and a column is not a place on screen. It is a preference, and it is off until you switch it on.
- A rectangular selection still stops at the end of each line, so virtual space cannot be used to select a column past the ends of short ones. That needs padding inserted per line on edit rather than a caret that is only drawn elsewhere.
- The published model list can only add names the agent already understands. A genuinely new protocol shape — a new message type wanting new UI, a second transport, a different permission flow — still needs a build.
- The Claude panel remains Studio only: it spawns a process and opens a socket, so the sandboxed App Store edition has none of it.
- Code folding and recorded macros remain roadmap items with no promised date.
A headless Claude Code beside the editor
- Studio can run Claude Code in the right dock, one per window, drawn from its structured output rather than from a hidden terminal. Start and stop it from the titlebar; the conversation and the session come back after a relaunch.
- It reads your open tabs as you have typed them, unsaved edits included, through a per-window server the editor exposes over a Unix socket. The same socket is handed to shells in the terminal panel, so a
claude you start yourself can read the editor too.
Nothing changes without you seeing it
- An edit arrives as a card showing the diff the buffer would become, not the name of a tool. It lands in the buffer, so it is one undo and you decide when to save.
- Interrupt stops a turn and keeps the conversation; Stop ends the process. What the conversation has cost is shown in the panel and in the titlebar, so a turn running behind a closed dock is still something the window says out loud.
- Claude can start a turn on its own once you ask it to — after a save, after an open, or on a timer — and each of those is off until you switch it on.
More than one terminal at a time
- New Terminal (⌃⇧N, or the header’s ✚) opens a shell in place of the one on screen. Once two are open, every running shell is listed down the side of the panel.
- Ending the terminal you are looking at now asks what to open next instead of sliding another one into its place.
Known limits in 1.8.0
- The Claude panel is Studio only. It spawns a process and opens a socket, so the sandboxed App Store edition has none of it.
- It needs Claude Code installed and signed in; Linelark finds it through your login shell and says so plainly when it cannot.
- Nothing bounds what a session costs. Everything that can start a turn without you is off by default for that reason, and the running total is on screen.
- A fenced code block in an answer is drawn in a monospaced font and is not syntax-highlighted.
- Code folding and recorded macros remain roadmap items with no promised date.
File ▸ Compare with File on Disk
- Opens the buffer you are editing against what is actually saved, as a two-column diff in its own tab, so you can see what a crash recovery or an outside change did before deciding what to keep.
A plugin can say which project it acts on
- Plugin API generation 8 adds the workspace folder list and a way to bind a plugin’s git actions to one of them. Before this, every git call in a multi-root window acted on whichever repository was last clicked into and said nothing about which.
- That is a poor default for a read and a trap for a write: adding a remote succeeds just as quietly in the wrong repository as in the right one.
Known limits in 1.7.0
- The diff compares the buffer with the file on disk. It is not a git diff and does not know about staged or committed states.
- Only a folder the window already has open can be chosen, and the binding is re-checked on every use, so closing a folder drops the plugin back to the default.
- Code folding and recorded macros remain roadmap items with no promised date.
New files and folders from the sidebar
- A folder’s context menu now opens with New File… and New Folder…, so a new file starts in the project instead of in the Finder and back again.
- Both work in a workspace root as well as in the folders inside it. A new file opens in a tab straight away, and the extension you type is what picks its language.
The terminal exports $LINELARK_FILE
- The variable each shell is given was spelled $Linelark_FILE, which is not the name the documentation gives. Shell variables are case-sensitive, so anything looking for the documented name found nothing at all.
- A Claude Code hook installed by an earlier version reads that old name, so it would quietly stop telling Claude which file is open. Linelark repairs its own hook when it starts, and leaves the rest of your Claude configuration alone.
Known limits
- A hook you have edited yourself is left untouched, since Linelark only repairs the file exactly as it wrote it. Terminal ▸ Set Up Claude Code Integration… rewrites it if you would rather it did.
- Any shell configuration or script of your own that reads $Linelark_FILE needs updating to $LINELARK_FILE.
- Code folding and recorded macros remain roadmap items with no promised date.
Windows return where you left them
- Each editor window now restores its own saved size and position instead of reopening at the default compact size.
- Opening a workspace from Finder or the command line brings its window forward immediately, including on a cold launch.
Workspace files open as projects
- Opening a .code-workspace file now loads its folders into the project sidebar instead of leaving an empty workspace or opening the descriptor as text.
- Existing VS Code workspace aliases, exclusions, settings, tasks, launch configuration, and other unknown fields remain intact when Linelark saves the workspace.
Build a multi-root workspace in Linelark
- File ▸ Add Folder to Workspace… adds another root, and a root’s context menu can remove it without touching the folder on disk.
- File ▸ Save Workspace and Save Workspace As… create a VS Code-compatible .code-workspace file with portable relative folder paths.
Known limits
- Workspace files describe local folders. Missing or inaccessible roots stay unavailable until their paths can be reached again.
- Code folding and recorded macros remain roadmap items with no promised date.
Windows, the way VS Code has them
- File ▸ New Window (⇧⌘N) opens a second editor window with its own tabs, its own panes, its own folder root, and its own find state — not a second view of the same one.
- Every open window is restored on the next launch, in the order they were open, and closing a window forgets that window rather than the app’s session.
- A new window opens looking like the one you opened it from, and the menu bar always acts on the window in front.
Panels belong to the window, preferences belong to the app
- Showing the terminal, the side panel or the right dock in one window no longer shows it in every window — each window keeps its own panel layout and its own panel heights.
- Word wrap, line numbers, the theme, the fonts and the status bar remain settings for the app, because that is what they are.
The terminal panel splits
- Terminal ▸ Split Terminal (⌃⇧5), or the header’s split button, divides the panel into up to three shells side by side, the way the editor divides into panes.
- A split is a second shell on the same terminal — same file, same pin, ended by the same tab — started in the directory the one it came from is currently in, which is usually the folder you just changed to.
- Clicking a pane moves the keyboard to it, Terminal ▸ Focus Next Terminal steps round them, and each pane’s × ends that shell and closes its column. A tab switch only ever changes the pane you are working in.
Known limits
- Editing preferences — word wrap, line numbers, whitespace, the document map, the theme, the status bar — apply to every window at once by design.
- Each window loads its own copy of every plugin, so a plugin enabled in one window needs Plugins ▸ Reload Plugins in the others, and several windows cost several JavaScript heaps.
- Terminals are still not saved with the session: relaunching starts from no shells, and a split shell is not restored.
- Code folding and recorded macros remain roadmap items with no promised date.
The sidebar can manage files, not only open them
- Folder and Open Files context menus can copy an absolute or workspace-relative path, cut or copy an item, paste into a folder, rename it, or move it to the Trash.
- Workspace roots stay protected from rename, cut, and deletion, and a copied item receives an available “copy” name instead of replacing an existing file.
Open work follows a move
- Rename or move a file from the sidebar and its open buffer stays attached to the new path, with its unsaved state and undo history intact.
- Moved folders carry every affected open tab, search result, bookmark, and recent-file path with them rather than leaving stale references behind.
Deletion says exactly what will be lost
- Deleting from the sidebar uses the macOS Trash instead of permanently removing the item.
- The confirmation identifies affected open tabs and warns explicitly when any of them contain unsaved changes before it closes them.
A terminal can belong to a project
- Start a terminal for the active file or for a workspace folder, switch between running shells from the panel, and pin a file terminal so closing its tab does not end the process.
- Project terminals outlive tabs by definition. Hiding the panel no longer closes a shell, and the terminal can temporarily fill the window without rebuilding the editor underneath it.
Known limits
- Sidebar file operations apply to local files and folders. Workspace roots themselves cannot be renamed, moved, or deleted from Linelark.
- A delete closes affected open tabs after confirmation; unsaved text in those tabs is not written to the file being moved to the Trash.
- Code folding and recorded macros remain roadmap items with no promised date.
Open a .code-workspace
- A VS Code workspace file opened from Finder, the Dock or
open -a arrives as the multi-root project it describes rather than as a JSON document to read. - Every local folder it lists becomes a root, in the order the file gives them.
- A directory opened from outside the app is treated the same way: a single-folder project.
Find in Files honours the workspace’s own exclusions
files.exclude and search.exclude from the workspace file are applied to folder search, using the portable subset of VS Code glob syntax — *, ? and recursive ** — so patterns such as **/dist and **/*.generated.swift work as written.- Search in This Folder narrows a search to one subtree without closing or replacing the workspace you have open.
Opening a project does not overwrite your folder
- A project opened from outside the app is a launch context rather than a preference, so closing it leaves the folder you had chosen yourself exactly as it was.
Known limits
- Only local folders in a workspace file are opened; remote and virtual roots are ignored.
- Plugins still see a single root —
folderRoot is unchanged, so generation-7 plugins behave exactly as they did. - Code folding and recorded macros remain roadmap items with no promised date.
Plugins can keep things, and follow you
- A plugin can store its own data between launches — one file per plugin in Application Support, capped at 4 MB and 2,000 keys, with a refused write reported rather than swallowed.
- A panel can opt into following the caret, and ask which line it is on without walking the document on every keystroke.
- Plugins can add their own items to the tab and sidebar contextual menus, one submenu each, called with the exact tab or file that was clicked rather than whatever is in front.
Sign in to a plugin through your browser
- A plugin may now hand a credential it obtained itself to the Keychain slot its manifest declares, which is what makes an OAuth device-flow sign-in possible without the plugin keeping the token in a plain file.
- It is write-only: there is still no call that returns a credential’s value. Storing one needs the manifest declaration and network consent, and signing out needs neither.
- The GitHub plugin uses it. Version 2.3.0 signs in through github.com/login/device instead of asking you to paste a personal access token, and pasting one still works.
Diffs can be merged, not only read
- A plugin that opens a diff can offer arrows down the middle of it, with ⌃ and ⌄ and Take-left and Take-right in a header bar.
- A diff from a plugin that does not offer that is still just a diff.
Remotes, links and settings from a panel
- Plugins can add, retarget and remove git remotes, open an external link from an explicit click, and send you to their own permissions screen.
The catalog stops offering what it cannot run
- A plugin release written for a newer API generation is no longer offered for install. Get Plugins… names the version of Linelark it needs instead, and the install is refused before the download rather than after it.
Known limits
- The App Store edition still has no terminal and no git: the sandbox it ships under does not permit either, and it now says so rather than appearing broken.
- Code folding and recorded macros remain roadmap items with no promised date.
- Plugin scripts run without a watchdog. A plugin that never yields can hang the editor until it is force quit.
The titlebar does the editing
- Undo, redo, cut, copy and paste join the comment and indent buttons already there.
- Each one offers itself only when it would do something: undo reads the document’s own history, cut and copy wait for a selection, and paste watches the clipboard. Cut is refused on a buffer you cannot write to, though copying out of one is fine.
- Column selection becomes a switch rather than a gesture you have to be told about. ⌥-drag still works; the button is the same thing without the modifier, and it turns itself off rather than surviving a relaunch.
Completion can offer itself
- New in Settings, and off until you ask for it: complete words while typing, a third of a second after you stop.
- It waits for two characters before offering anything. ⌃Space still works whether or not this is on.
Diffs are drawn as two files
- A changed file opens as the old and new versions side by side, aligned, with each side numbered in its own file and long lines wrapped rather than pushed off the edge.
- This is what the GitHub plugin now opens when you click a file in it.
Plugin panels grew up
- Generation 2 of the plugin API: foldable sections, rows of icon actions, real labelled buttons, badges coloured by what they mean, side-by-side diffs, and a discard that Linelark confirms with you before anything is thrown away.
- A plugin written for generation 2 is refused by an older Linelark, with a message saying so, rather than loaded with half its panel quietly missing.
Fixed
- Saving a file now redraws the panels that describe the repository. A file you had just saved could sit outside the changes list until something else happened to redraw it.
A new tab is numbered from the tabs you can see
- A restored session took the next untitled number from its saved record rather than from the tabs that came back. A saved file carries an untitled number of its own — unused, never shown — so the first new tab of any restored session was “new 2”.
- A tab the restore could not rebuild counted as well, and left a gap. After 1.1.1 recovered a session whose unsaved tab 1.1 had already discarded, the next new tab was “new 3” with no “new 1” or “new 2” anywhere in the window.
- The number now comes from the untitled tabs actually on screen. Tabs that come back keep the names they had, so nothing is renumbered underneath you.
Upgrading from 1.0 no longer empties the editor
- 1.0 and 1.1 were published under different bundle identifiers, so macOS filed their settings as two unrelated applications and 1.1 could not see anything 1.0 had written.
- An upgrade therefore looked like a factory reset — no open tabs, no folder, default settings — while the previous session sat intact but unreachable on disk.
- 1.1.1 adopts those older settings the first time it starts. Tabs, panes, the open folder, themes, and plugin permissions all come back.
Unsaved tabs survive an upgrade
- Backups of unsaved tabs live in one folder shared by every version, while the record naming them is stored per version. A 1.1 that found no session therefore read every backup as abandoned and deleted it.
- Backups are now retired for fourteen days instead of deleted, and a session that asks for a retired one gets it back.
- A window that has not restored its session yet no longer writes over that session or drops the backups belonging to it.
If 1.1 already emptied your editor
- Install the current release and open it once. The 1.0 session it could not previously see is adopted on that first launch.
- Text from a tab that was never saved to a file, and that 1.1 had already discarded, cannot be brought back by this update.
- Files on disk were never at risk. A backup is not a save, and no version of Linelark wrote to your files here.
Reviewed JavaScript plugins
- Browse versioned releases from Plugins ▸ Manage Plugins… ▸ Get Plugins… and install without leaving Linelark.
- Catalog downloads verify the published archive size and SHA-256 checksum before safe extraction.
- Install local
.linelarkplugin folders or .linelarkplugin.zip archives, manage permissions, reload plugins, and inspect per-plugin logs. - Extend the editor with commands, native panels, document previews, virtual buffers, timers, allowlisted network requests, credentials, and constrained Git operations.
Editing foundation
- Tabbed native editor with per-tab undo, 69 language definitions, auto-indent, bracket matching, comment toggles, and word completion.
- Column selection and Column Editor for text, decimal, hexadecimal, or octal sequences.
- Document map, clickable-gutter bookmarks, line operations, spell checking for prose, and print support.
Files, formats, and search
- Eleven encodings plus BOM handling, reinterpretation, and LF, CRLF, or CR preservation.
- Language detection by extension, whole filename, or shebang.
- Find and replace in one file or an open folder, with filters, regex captures, marked results, and protected writes.
Panes and continuity
- Two, three, or four panes, tabs draggable between them, and multiple shared views of one document.
- ⌘1–⌘9 tab access, session and layout restore, external-change detection, and recovery of unsaved work after a crash.
Studio terminal
- One real login shell per tab, rooted beside the file, with interactive xterm programs, true colour, and mouse reporting.
$LINELARK_FILE, safe reloads after command-line edits, and optional Claude Code session context.
Known limits in 1.1
- Code folding and macro recording remain in the roadmap.
- Plugins use a constrained JavaScript API rather than arbitrary disk, process, browser, or native-code access.
- Find in Files caps at 5,000 hits and skips binary files and files over 4 MB.
- Bookmarks last for the open tab but are not saved with the session.
- Pane layouts use fixed presets rather than an arbitrary split tree.
Registre permanent de l’artefact
- Aucune note de version détaillée n’a été publiée pour cette version. Cette page conserve l’identité de l’artefact, son build, sa date de publication, son empreinte et son commit source, plutôt que d’inventer une histoire après coup.
- L’image disque versionnée reste immuable et peut toujours être vérifiée face à l’empreinte SHA-256 indiquée ci-dessous.