Repository navigation
Conversation
The whole tree as of the move to a public repo. Everything since 0.12.0 ships in 0.13.0; CHANGELOG.md and docs/adr record the history before this commit.
* ci: keep minor Tauri bumps out of Dependabot's weekly groups tauri build refuses an npm Tauri package and its Rust crate on different minor versions. Dependabot bumps npm and Cargo in separate pull requests, so each one failed the macOS build (#2, #4). Dependabot now proposes only patch updates for @tauri-apps/* and tauri*; a minor or major Tauri bump is done by hand, both sides together. Security updates are not affected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: hold back minor bumps only for Tauri packages with a twin The tauri* pattern also matched tauri-build, tauri-plugin-positioner and tauri-plugin-updater, which have no npm side, so their minor updates would have stopped with nothing to remind anyone. The rule now names the seven npm/Rust pairs on each side. The comment also says a security update can still bring one side's minor alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(adr): name the Tauri pairs and the security-update exception ADR 0043 said Tauri packages get only patch updates from Dependabot. Security updates ignore update-types, so it now says which packages pair up and that a security update can bring one side's minor alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ary (#8) * fix(structured): keep the turns before a compaction and hide its summary After Claude Code compacts a session, the Structured view lost every turn from before the compaction and showed Claude Code's summary as the newest prompt, so the view no longer matched the terminal. Two things caused it. The compact_boundary row has no parentUuid; it links to the row before it through logicalParentUuid, so the parent chain stopped there. And the summary is a user row (isCompactSummary) that opened a turn of its own. The chain now follows logicalParentUuid when parentUuid is missing, the summary is treated like a meta row, and a compaction that lands after a turn's reply no longer keeps that text from being read as the reply. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(structured): skip a compaction's summary instead of treating it as meta The summary row counted as meta, so it joined the turn before the compaction and moved that turn's end time to when the compaction ran. A turn that took seconds could then read as taking hours. The summary now carries the chain and is otherwise left out of the view, like an attachment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(structured): say the main chain crosses compactions Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(ptyd): remove only the bridge socket this daemon bound A daemon removed whatever path KRIYON_BRIDGE_SOCKET named when it ended, whether or not it had bound that socket. A daemon started from inside a Kriyon session, such as one from the kriyon-ptyd tests during `pnpm check`, inherits that session's bridge path. It can't bind it while the session's own daemon serves it, but on exit it still deleted the file. The session's daemon kept listening on a socket nobody could reach, so its companion stopped reaching Kriyon and the Structured view stopped updating. The daemon now records the device and inode of the socket it binds, and removes the path only when it still points at that file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(ptyd): never pass a Kriyon session's bridge socket to a test daemon Most kriyon-ptyd tests spawned the daemon with the environment they ran in. Run from inside a Kriyon session, each test daemon was handed that session's KRIYON_BRIDGE_SOCKET. Each spawn now removes it, as stop_ends_the_whole_tree already did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(ptyd): leave a bridge socket someone else bound over the daemon's Nothing tested the device and inode check: removing whatever the daemon had once bound passed every test. The new test unlinks the daemon's socket, binds another at the same path, and checks it survives the daemon's stop. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ptyd): record bridge ownership in the same step as the bind The bridge thread created the socket file a moment before recording it as its own, and the daemon's way out didn't wait for it. A daemon that stopped in that gap left its own socket file behind. A stop before the thread had bound at all let it bind afterwards, with the same result. Binding and recording now happen under one lock, which the way out takes too, and once the daemon is stopping a bind that hasn't happened yet is refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ut of the newest turns (#10) * fix(structured): keep live rows cut off with the transcript's start out of the newest turns The Structured view reads only the newest 12 MiB of a transcript. Once a session's transcript grew past that, the companion's live rows from its start were no longer in what was read, so they counted as rows the transcript had not written yet and were shown after the newest turn. The view then ended on the session's first turns instead of its latest one. The transcript only lags at its end, so a live row is now still to be written only when it comes after the last live row the transcript holds, and when it isn't older than the oldest row read. The second rule covers live rows from an earlier companion run that share nothing with what was read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(structured): pin that a row cut off just before the transcript read stays out Removing the "after the last live row the transcript holds" rule passed every test, because the cut-off rows in the fixtures were also older than the oldest row read. The new test has a cut-off row received a moment after that row was written, so only its place in the live rows keeps it out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The release check ran `stapler validate` with its output thrown away, so when the 0.13.0-beta.3 build failed it the log said only that the DMG had no stapled ticket, seconds after stapling had succeeded. The failure now includes stapler's own output. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
#12) * refactor(ui): move the reply Markdown renderer into a shared component The Structured view drew Claude's replies with its own Markdown renderer. It moves, unchanged, to src/ui/Markdown.tsx as `Markdown`, with the inline text, links and copy button it uses, so the update dialog can draw release notes the same way. `Markdown` takes a `size`: body for replies, small for a dialog. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(update): draw the release notes as Markdown The update dialog showed the release notes as raw Markdown, with the `###` and `-` marks in view. It now draws them with the shared Markdown component: headings, lists, bold and code as they read on GitHub. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(update): give the update pill an icon and the accent The "Update available" pill now has a sparkle icon with a slow glow, an accent tint and border, and a tooltip naming the version on offer. It pops in when an update arrives; reduced motion stills both animations. Its tint goes in through --kr-fill, as `fillVars` (now exported) does for the other hover-classed controls. The old pill took chip()'s inline background, which outranked the hover fill, so it never lit up on hover. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(ui): leave file paths as text where there is no folder to open them in The update dialog draws release notes with the shared Markdown component but has no session folder, so a path in the notes (`src/ui/Markdown.tsx`, `~/.claude/settings.json`) became a link whose click always failed with "cwd is not a directory". Without a LinkCwd folder, file paths now stay text and only URLs are links. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(theme): give chip() a pressable variant that keeps its hover chip() painted its background inline, which outranks .kr-hover-surface's hover fill, so the update pill had to spread fillVars and then unset background by hand. chip({ fill, hover }) now publishes both through --kr-fill for a chip that is a button, and the hover-seam test covers it. fillVars is private again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(layout): let the companion chip light up on hover The session header's companion chip spread chip()'s inline background onto a button with .kr-hover-surface, so the hover fill never showed. It now uses the pressable chip, which leaves the fill to the hover class. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(theme): make the hover-seam scan see the pressable chips The scan that checks every host of a --kr-fill recipe also carries a hover class didn't know chip({ … }), so a pressable chip that lost .kr-hover-surface would show no fill at rest and every test would pass. chip({ is now one of its recipes. The scan reads a style only when it is declared at a file's top level and ends within its window, so the two pressable chips are shaped to be read: the companion chip's base style moves to the top of its file, and the update pill's icon comment becomes a doc comment. Taking either chip's hover class away now fails the scan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…width (#13) * fix(composer): keep the footer in one row and Send in the box at any width In a narrow window the composer's footer broke: the usage readout was the only part allowed to shrink, so "330k · 33% ctx" wrapped onto four lines, and the buttons, which can't shrink, pushed Send out past the box's edge. Nothing in the footer wraps now, and the right group (hide, Stop, Send) never shrinks. As the footer narrows, the rest steps down in a fixed order, least useful first: the ⌘⇧P hint, the Session chip, "Save prompt" to its ✦, the usage readout, and "Prompts" to its icon. `footerFit` in composerFooterFit.ts decides the steps from the footer's measured width; as a last resort past them, the left group clips instead of pushing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(composer): fit the footer by measuring it, not by estimating widths footerFit decided what fits from pixel widths copied by hand from the button, chip and keycap styles, and the copies already disagreed with them (an icon button is 27px, not 26). The next change to any of those styles would have brought the clipped footer back with the tests still green. The footer now measures itself: after each layout, while the tools' content is wider than their box, it gives up one more step (fitAfter holds the order). The steps run in layout effects, so only the settled footer is painted, and they start again from everything when the footer's width, the usage readout or Stop changes. The fitting lives in FooterTools, so a step re-renders the tools and not the whole composer. No width is estimated anywhere. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(composer): re-fit the footer when it widens, from one fitting module The footer's width was read from the footer's own ref, inside the tools component it contains. React runs a child's layout effects before it attaches the parent element's ref, so the width observer was never created: once the footer had given parts up, widening the window never brought them back. The width now comes from the box the tools sit in (their own ref's parent), which is attached in time, and a test widens a composer after it mounts. The fit also started again only when a hand-built key changed, so any new input left out of it would have left the footer stuck stripped. It now starts again whenever the tools get new props or their box changes width, and the measuring hook lives beside the order it steps through, in composerFooterFit.ts, with nothing for the caller to list. A 1px allowance keeps a rounding difference between scrollWidth and clientWidth from counting as overflow. The layOutTools test helper now removes its prototype override when done: jsdom keeps scrollWidth and clientWidth on Element.prototype, so the old restore left the override in place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(structured): open a turn when a subagent hands back its report
When a background subagent finishes, Claude Code wakes the main agent
with a meta user row stamped origin.kind "peer". The Structured view
did not open a turn for it, so the work that followed joined the
previous turn, which had already recorded its end. The view then told
the backend the turn was over, and the session read Done in the
sidebar while Claude was still running a tool.
A hand-back now opens its own turn as a Work report ("Agent "…"
reported back"), named by the Agent step that launched it. A hand-back
that only echoes Claude Code's own report for that agent is dropped.
Claude writing after a turn's recorded end also reopens that turn, so
any other unrecognised wake-up cannot settle the status to Done.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* fix(structured): match an echoed hand-back by its agent id
A hand-back was told apart from Claude Code's own report by the end of
its summary, and matched to it by the text between quotes. A hand-back
was then dropped beside any other work of the same name, such as a
background command called "Build", or kept twice when its launch was
not in view and it had no name.
Each Work report now keeps the id of the work it is about (a report's
task-id, or the agent a hand-back came from) and whether it is a
hand-back. Neither is sent to the frontend. A hand-back is dropped only
when Claude Code's own report for the same id is in the turn.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
#15) While Claude works, Claude Code posts its own copy of each message it queues for the model, such as a subagent's hand-back or a background task's report, through the companion's "queue" door. The transcript never writes these copies. Until the transcript caught up, the Structured view read each one as a typed prompt and opened a turn showing its raw <agent-message> or <task-notification> text. Live rows from the queue door are now left out, as the transcript leaves them out. A hand-back still opens its turn from its peer row, and a report that wakes Claude from its own prompt row. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(companion): say hello again after a resume or /clear After /resume or /clear, Claude Code ends the old conversation and goes on under a new one without firing session.start, so the companion posted nothing until the first prompt there. Kriyon had already moved the session to the new conversation, found no companion posts for it while hooks kept firing, and showed "Companion off". The companion now listens on the classic SessionStart hook and, for a resume or clear, posts a hello under the new conversation's id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(companion): say hello again after a /branch too A /branch or --fork-session moves the running process to a new session id the same way a resume or /clear does, and Claude Code reports it as a classic SessionStart with source fork. Leaving fork out kept the same quiet window open for branched conversations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(structured): draw Markdown tables and rules in replies The Structured view's Markdown reader knew fenced code, headings, lists and paragraphs only, so a pipe table in Claude's reply showed as raw lines of pipes and dashes, and a `---` separator as literal text. The reader now turns a header row followed by a delimiter row into a table block, with each column's alignment from the delimiter, every row padded or cut to the header's width, and a pipe inside a code span or escaped as `\|` kept as text. A line of three or more dashes, stars or underscores is a rule. Both are drawn as elements with theme tokens; a wide table scrolls sideways inside the reply. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(structured): keep table edges from eating cells and nearby blocks Review found four ways the new table reader went wrong on ordinary replies: - A lone backtick in a cell opened a code span to the end of the row, so later pipes became text and the last cell was dropped. A backtick with no partner later in the row is now just a character. - A prose line with a pipe in code, over a bare ---, became a one-column table. A delimiter row now needs a pipe; a bare --- is a rule. - A list item, heading or fence right after a table, with no blank line, was read as one more row. Table rows now end where another block starts, and a heading is never a table header. - The spaced rule (- - -, * * *) and escaped pipes had no tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(structured): show the companion starting instead of missing While a session's companion was still starting, the Structured view said it needs Kriyon Companion, as if it were off. It now shows the wait itself: Claude Code's mark sends light across a link to the mascot, which ripples as each one lands, under a shimmering "Starting Kriyon Companion…". A line explains the one thing that can hold it up, a folder Claude Code wants trusted, with a button to open the terminal to answer it. The screen fades in after a short delay, so a companion that answers at once never flashes it. Colours come from the tokens, so it follows the theme and the mascot hue, and reduced motion stills it through the global rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(structured): share the loading shimmer with the session overlay The companion's starting title wrote out its own copy of the shimmer the session loading overlay already had, and the two had drifted apart in colour and speed, so a new session showed two different shimmers back to back. The shimmer is now one `shimmerText()` recipe both use. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(structured): take the packet glow from the tokens The light dots on the starting screen set their glow as a literal shadow. It is now `tokens.shadow.glow`, lit with the accent, so a token change reaches it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(structured): share the mascot tile and its size The starting screen copied the banner's mascot tile, and both typed the mascot's size by hand beside it. The tile and the size it is drawn for now come from `Mascot.tsx`, so resizing one can't leave a mascot clipped or spilling over its tile on one screen only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…18) * feat(structured): set the user's prompts apart from Claude's replies In the Structured view a prompt was only bold text in the same column as the reply, so a long turn was hard to scan for who said what. A prompt now sits on the right as a speech card in a wash of the accent, with any images under it, and Claude's steps and reply sit under a "✻ Claude" label across the full column. The sent stand-in, the streaming reply and the /usage card follow the same split; work reports stay unmarked so they never read as typed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(structured): keep the prompt card's tucked corner The prompt card set its tucked bottom-right corner and then the all-corners radius after it, so the shorthand put that corner back to 12px and the bubble's tail never showed. One shorthand with all four corners leaves nothing to override it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(structured): take the prompt card's spacing from the tokens The prompt card's padding and the speaker label's gap were pixel literals off the spacing scale; src/AGENTS.md has spacing come from theme/tokens.ts so a change to the scale reaches them too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…otes (#20) * fix(release): list only what is new since the previous beta in beta notes A beta's notes came from git-cliff's unreleased draft, and git-cliff counts only from release tags (cliff.toml's tag_pattern). So every beta listed everything since the last stable release, not what changed since the beta a tester already runs. A beta's notes now count from the newest release or beta before it, and a nightly's from the newest release or nightly, through a git range. git-cliff drops the range under --unreleased, so the range replaces that flag; no release tag can fall inside it, since it starts from the newest one. A stable release's notes are still its CHANGELOG.md entry, which lists everything since the last stable release. ADR 0046 says so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(release): keep a release tagged between two betas in one section A pre-release's notes come from git-cliff over the range from the last tag on its channel. A release can still be tagged inside that range, such as a patch shipped between two betas, and git-cliff then split the range into two sections. draftNotes strips only the first heading, so the beta's notes showed a stray "## 0.12.1" section. Ignoring every tag inside the range keeps it in one section, under the pre-release's own tag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(release): count release tags through cliff.toml's tag_pattern notesSince decided what a release tag is with its own pattern, while cliff.toml's tag_pattern is the one definition that latestRelease, nextRelease and preReleaseBase read. It now takes that pattern too, so a change to tag_pattern moves git-cliff and the notes range together. A tag the pattern does not match, such as a bare 0.12.5, no longer counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(adr): say what a tester who skips a beta sees in its notes ADR 0046 said a beta's notes show what changed since the build a tester runs. They count from the previous beta, so that holds only for a tester who takes every beta. The ADR now says what one who skipped a beta sees, and where the skipped beta's notes are. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* fix(structured): show pasted text without Claude Code's paste markers Claude Code records a paste inside the prompt as `<pasted_content id="x">…</pasted_content id="x">` so the model knows which part the user pasted. Kriyon showed those markers as part of the prompt in the Structured view, and a prompt that was only a paste got the opening marker as its session title and past-session preview. The markers are now taken out and the pasted text kept as plain text; an opening marker without its matching close is left as written. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(composer): type long messages in pieces so none of it is lost Claude Code reads an input chunk over 800 characters as a paste. The composer wrote a message to the terminal in one write, so a message of 800 to about 1000 characters was recorded as one pasted block, and a longer one, which the terminal splits into ~1 KB reads, lost everything but its last chunk. The text is now written in 256-byte pieces, 20 ms apart and never split inside a character, which Claude Code reads as typing. Checked against Claude Code 2.1.303: a 3000-character message arrives whole and untagged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(structured): read pastes the way Claude Code shows them, wherever a prompt is read Paste markers were taken out by two readers (the turn builder and prompt_label), while the Prompt event kept them, so "Save last prompt…" still saved the raw tags, and an all-paste prompt got an empty title. The markers are now removed where each parser reads a user row: the Structured view's row builder, the Prompt event, and the prompt text that session titles and past-session previews use. The matching now follows Claude Code's own rules: a four-hex-digit id followed by a newline, with up to two newlines dropped on each side of a paste. Before, any id matched, so a typed prompt quoting the tags lost them, and an all-paste prompt showed two blank lines above its text. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(composer): send a long message as one paste so it always arrives whole Typing a long message in 256-byte pieces relied on a 20 ms gap: if Claude Code was busy for longer than about 60 ms, the pieces arrived as one read over its 800-character paste limit, and the text could be lost again. A message of up to 800 bytes is typed in one write, as before this pull request; whatever way the terminal splits or joins it, Claude Code reads it as typing. A longer message, with its @ mentions, goes as one bracketed paste, which Claude Code collects whole however it is read. Text that contains the paste-end sequence cannot close the paste early. Checked against Claude Code 2.1.303 with Kriyon's own timing: a 3160-character message with an @ mention arrived whole and the file was attached. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(composer): remove every escape from a pasted message so it cannot end early Only the paste-end sequence itself was defused, so text holding two escapes before it (pasted terminal output, say) became a working end sequence again: the paste ended inside the message and the rest was read as typed keys, where a newline could send part of it early. The paste body now carries no escape character at all, which no text a person means to send needs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ws it (#22) * fix(activity): show steps and turns in plain words The Activity tab showed what Claude Code sends the model, not what a person can read: a subagent's hand-back headed its turn as raw `<agent-message>` tags, a heredoc split into one "command" per script line, searches said only "Searched the code", and tools like ScheduleWakeup read as "Used ScheduleWakeup". Each step now keeps a one-line summary: the description Claude already writes for a command or subagent, or the pattern, query or page a search or fetch was about. It costs no tokens, since Claude sends it anyway. Steps already in the log get theirs from the input they recorded. - A command row is titled by its description, with its commands under it. Heredoc bodies stay part of their command, each command shows its first line, long chains show the first three and how many more, and home folders read as `~`. - Searches, web calls, subagents and skills say what they were about, and Claude Code's other tools get plain titles. - A turn started by a subagent's hand-back or a work report is headed by its summary ("Agent "pr-scorer" reported back"). Paste markers are taken out of prompts. - A main-agent step whose end was never recorded no longer reads "running…" once its turn has ended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(activity): show what Claude did to the machine, as the design draws it The Activity tab exists so a person can see what Claude did: files it made or changed, what it deleted, where it went online, what it installed. It now follows design A (side panel timeline): - What a step did to the machine leads its title: "Installed a package", "Deleted files", "Touched a secret file", "Read a file outside the project". Otherwise a command reads as Claude's own description in the past tense ("Ran the tests"). - A file change shows the lines it added and removed, from Claude Code's own patch, and a new file reads as "Added". A command that edited files shows its lines too and counts under the Changes filter. - A test run shows its result at the row's end ("43 passed", "2 failed"), read from the whole output by the hook, so a long run can't lose it. - A step the user approved in a permission dialog says "you approved". - Web steps say where they went ("Used the internet" over the address, "Searched the web" over the query), and a search shows what it looked for and how many files it found. Flag chips read "web" and "outside". - Reads in a row fold into "Read 9 files" and file changes into "Changed 3 files" with their lines added up. A folded row opens to show each step. Flagged or failed steps never fold, so they stay in sight. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(activity): use Claude Code's real paste markers in the store test dev now takes only Claude Code's real paste format (a four-hex-digit id), so the test's made-up id was read as prose. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(activity): show subagents' work, command output and files outside Testing on a real session showed what the timeline still hid: - A subagent's steps were mixed in with the main agent's. They now sit under the step that started the subagent, with their lines added up. A subagent whose start isn't in view gets a block of its own. - Claude often reads and writes through Bash. A command that names a file in the home folder or the system's own (`cat ~/.claude/settings.json`, `/etc/hosts`) outside the project is now flagged "outside". A command that changed files names them ("Changed format.js, format.test.js") and is flagged like a file tool would be. - The step detail showed a command's result as raw JSON. The hook now records the output itself, a change's patch or a page's text, keeping the start and end of a long one. Older JSON results and command inputs are shown as text too. - Node's built-in test runner results ("ℹ pass 3") now show as "3 passed". - A shell loop or `if` reads as one command, not one per piece. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(activity): add the changed-files column in its own migration A store already at v6 (from an earlier build of this branch) skipped the column, so the timeline failed to load. It now has a v7 step of its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(activity): drop install noise and name subagents by their task From the second smoke run: - An install's node_modules and git's own files no longer count as files a command changed, so `npm install` doesn't list a package's LICENSE or add its lines to the project's. - A subagent's hand-back heads its turn by the task Claude gave it ("Agent "Review format.js and add test" reported back"), not its type. - A subagent handing back reads "Reported back", not "Used SubagentHandback". - Claude loading its own tools does nothing on the machine, so it is left out of the timeline and its counts. - More of Claude's verbs read in the past tense ("Appended", "Reviewed"). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(activity): flag package removals and keep descriptions in one tense From the third smoke run: - Removing a package (`npm uninstall`, `pnpm remove`, `pip uninstall`, `brew uninstall`, `cargo remove`, …) takes something off the machine, so it is flagged like a delete and titled "Removed a package". - Every verb Claude chains in a description now reads in the past tense ("Installed dayjs and checked its output"), not just the first. Words that read as nouns after "and" ("…and test files") stay as written. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(activity): hide a background helper's check-ins Claude Code forks helpers of its own: they carry an agent id but no subagent type, since nobody launched them. One stopping a check-in loop showed up as "Subagent · unknown" with a step that never finished, though it did nothing on the machine. A helper's check-in is now left out like other housekeeping, and anything else a helper does shows under "Claude Code in the background". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(activity): show every flag a step earned A command that removed one package and installed another showed only its most serious flag. Each flag now gets its own chip, most serious first, and "reinstall" and "retry" read in the past tense. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(activity): read test results from runner summaries, and a subagent's launch The hook took any line with "N passed" as a test result, so a run where every test failed showed nothing and `grep passed` output got a green badge. It now reads only the summary lines vitest, jest, pytest, cargo and Node's runner print, and adds up every runner in one command (`pnpm check` counts vitest, node and cargo together). On a subagent's own event, the hook now reads the sidecar Claude Code writes beside its transcript (`subagents/agent-<id>.meta.json`) and records which launch started it, so a subagent can be tied to its launch exactly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(activity): link subagents by one rule in core, and flag package removals Matching a subagent to the call that launched it was written three times (the store's SQL, the timeline and the live Agents panel), and the copies already disagreed. kriyon-core now owns it: `exact_launch` (the launch the sidecar names, or a background launch's agent id) before `guessed_launch` (the earliest free launch of its type). The Activity log and the live panel both use it, an exact link never takes a launch from another subagent, and a launch that names no type runs as `DEFAULT_SUBAGENT`. Removing a package is now its own step flag in core, so the frontend no longer keeps a second, already different copy of the rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(activity): keep a subagent's launch type and link from the store The store read a launch's subagent type from the kept input, which the hook cuts at 2000 characters, so a subagent with a long brief lost its type. It now keeps the type the hook sends on its own (migration v8, filled in from the kept input for older launches), with the launch facts core links by. Each read of a session's turns links its subagents once through core and sends every subagent step its launch and its name; hand-back headings use the same name. The step detail no longer sends `agentId` twice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(activity): show commands as written, and name agents one way - A shell loop or `if` stays one command even when nested, keeping its real separators, and a here-string or `$(( … ))` is no longer read as a heredoc. - Subagent steps nest under the step the store says launched them, and a subagent block, its launch row, its hand-back heading and the step detail all name it the same way. - ", then commit" reads in the past tense; after "then" a word is always a verb. - A background helper's unfinished step keeps "running…" after the turn. - Only the real home folder is shortened to `~`, through one helper the Details rail shares. - The step detail shows only a command step's command; other tools keep all of their input. - Spacing comes from the theme tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* chore(release): 0.13.0 * docs(readme): list Homebrew as a way to install, not coming soon The 0.13.0 entry lists `brew install leafycode/tap/kriyon`, and publishing 0.13.0 writes the tap's first cask, so the README no longer says the tap is coming soon. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
4 tasks done
cleanEntry and draftNotes removed guidance comments in one pass, so a comment split around another (`<!<!-- x -->-- y -->`) left a whole `<!-- y -->` behind in the release notes. They now repeat until no comment is left. CodeQL flagged both as incomplete multi-character sanitization on the release pull request. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
0.13.0 — 2026-10-20
Kriyon is now open source, and it can update itself.
Added
installs it when you say so. Your sessions keep running.
brew install leafycode/tap/kriyon.look different, so you can tell them apart at a glance.
Changed
computer, such as installed or deleted files.
Fixed
Security
🤖 Generated with Claude Code