Changelog
Qué ha ido pasando
El registro de commits del CLI, del más reciente al más antiguo, directo de GitLab. Cada versión queda marcada donde apunta su etiqueta, con sus notas de CHANGELOG.md debajo.
actual: 0.16.1 · 100 commits · la historia completa en GitLab
0.16.1
Added
- Diff a snapshot against now. In the snapshot view,
d(or ops → diff) opens a tree of the folders and files that changed versus the current worktree. Enter a file to see its patch; Esc returns to the tree. Folders start folded.torii snapshot diff <id>lists the files first, then the patches. - Custom auto-snapshot intervals in the TUI. The snapshot view's picker still has off / 5 / 15 / 30 min / 1 hour, plus a
custom…row. Type30m,2h,45, the same durationstorii snapshot config --intervalalready takes. The value is stored as minutes in.torii/config.toml, so a CLI2hno longer snaps to 1 hour when the TUI loads it. - The issues view names the forge. Heading, each row and the detail pane show
gitlab/github/ … and theowner/repothe list came from.pswitches between remotes, the way the PR view already does.torii issue listprints the same host line. - Built-in keys are claimed per view. A letter may live in many views; it may not live twice in one, or collide with a global (
e, Tab,W). The files tree is dispatched from that table, so adding the event-log key there fails before the handler can hide it. tin the files view shows the tree of HEAD. Status columns hide for a nested tree of folders and files in the current commit, with icons and the usual connectors. Folders lead, then files.torEscbrings the status layout back. Folders start folded. Enter, space,h/l, arrows or-/+open and fold; a click selects a row, a second click opens or folds it. An unborn HEAD is an empty tree, not an error. (estays the event log, which is global.)
Fixed
torii sync <branch> --mergeno longer destroys uncommitted work on a fast-forward. The checkout is safe: a dirty file the incoming tree does not touch stays, and a dirty file it would overwrite refuses the merge instead of being clobbered.torii sync --pulluses the same path. (#1)torii snapshot configwrites the same storetorii configreads. It used to dump a per-repo JSON with different key names that nothing else looked at, sotorii config get snapshot.auto_enabledstayedfalseafter a successful--enable.--intervalnow parses the documented30m/1hforms (and bare minutes) and errors on garbage instead of silently becoming 30. (#3)- Auto-snapshot actually fires. With
snapshot.auto_enabled, a dirty fast-forward takes a snapshot first. The TUI interval picker reads and writes the same toml. (#2) torii snapshot restoreno longer deletes the repository. Snapshots live under.git/torii/snapshots/, and restore used toremove_dir_all(.git)— which erased the snapshot it was reading and left an empty.git. It now rewrites.gitwhile keepingtorii/, and a snapshot also stores dirty / untracked files so uncommitted work comes back. The TUI snapshot view talks to the same store instead of writing empty.metafiles.
- Diff a snapshot against now. In the snapshot view,
- 28247910 chore 0.16.1
0.16.0
Added
- A clone view in the TUI. The sidebar's new
cloneentry leads the list: getting a repository is how you start, not a property of the one already open. Opening the TUI still lands onfiles, because you launch it inside a repository. It lists the repositories of whichever account you have a token for, filters them as you type, and clones the one you pick — with a progress bar, because a clone is the one operation in torii that can take a minute and say nothing. - The destination is on screen before the clone starts, and is editable. It is
<clone.base_dir>/<repo>, re-derived every time the caret moves or the URL box changes, and left alone the moment you edit it: a field that overwrites what you typed is not an editable field. An existing path is refused up front rather than by libgit2 halfway in. [u]takes a URL or a local path, for everything a listing cannot name — someone else's repository, a host torii has no listing for, a bare repo on this disk. It wins over the selection when it has anything in it, and the destination follows it, so the path shown is always the path used.[p]switches host and says which ones have a token here. A host is still selectable without one; the error it gives names the command that sets it, which is more use than a row that cannot be clicked.[t]picks ssh or https, seeded the waytorii cloneseeds it —mirror.default_protocol, or the presence of an SSH key.- When it finishes, the repository is open. It is also registered in the active workspace, if there is one, so the repo switcher and the multi-repo commands see it without being told twice. Cloning a repository in order to then go and find it is two steps too many.
- The listing is a background worker, like every other network call in the TUI; the view stays usable while it runs, and a host with no token is never asked, because the answer is already known.
Escover a running clone stops it. The progress sink returns false, which is what libgit2 already asked for, and libgit2 removes the half-fetched tree. A Radicle clone kills theradprocess instead; seed state in~/.radiclemay remain.clone.base_dir— where a clone lands when no destination is given. Default is., which is whatgit clonedoes, so nothing moves for anyone who does not set it.~is expanded.torii config set clone.base_dir ~/repos.list_reposfor Gitea, Forgejo and Codeberg. All three answer the same API and all three returned "not yet wired", which left the new view with three empty hosts. One paged implementation now serves them, stopping on the first short page and at a ceiling, so a host that ignoreslimitcannot spin.list_reposfor Bitbucket, sourcehut and Azure. The clone view can now browse those three the way it already browses GitHub / GitLab / Gitea. Bitbucket followsnextwith the same 20-page ceiling; sourcehut pagesgit.sr.ht/api/reposand names the owner from meta.sr.ht when a row does not carry one; Azure lists every git repo in the organisations the PAT can see (AZURE_DEVOPS_ORG/AZDO_ORGpin it to one).- Gitea / Forgejo / Codeberg
PlatformClient.create/delete/get/update/configure_featuresshare one helper, the waylist_reposandset_visibilityalready did.torii remote create codeberg …no longer sends you to the web UI. torii clone <plat> user/repocovers sourcehut and Azure. Sourcehut is~user/repo(the tilde is added if you omit it). Azure isorg/project/repo, because that is how the URLs are shaped (git@ssh.dev.azure.com:v3/…/https://dev.azure.com/…/_git/…). Forgejo and Gitea shorthand now readFORGEJO_URL/GITEA_URLthe same way the API client does, instead of always pointing Forgejo atcodeberg.org.- Radicle clone via
rad, not libgit2.list_reposisrad ls --all(falls back torad ls);get_repoisrad inspect --payload.torii clone radicle rad:z…and arad:/rad://URL both runrad clone. The TUI lists Radicle without a token — the local node is the auth — and Esc kills theradprocess. A stop during fetch can leave seed state in~/.radicle; the working copy is not promised.radstill has to be on PATH. - OAuth for self-hosted Forgejo and Gitea. They share an API, not an OAuth grant. Forgejo has RFC 8628 (Codeberg already did):
torii auth oauth forgejotalks toFORGEJO_URL(default codeberg.org, and then the bundled Codeberg client_id is reused). Any other host needs a public OAuth app andTORII_FORGEJO_APP_ID. Gitea still only speaks authorization-code:torii auth oauth giteaopens a PKCE loopback on127.0.0.1:8888/callback, host fromGITEA_URL, client_id fromTORII_GITEA_APP_ID. The TUI runs Forgejo's device flow in-place; Gitea (and Bitbucket) name the CLI command instead of pretending device flow works. GitRepo::clone_repo_with_progress— the clone, with libgit2's progress handed to a caller-supplied sink instead of tostdout.clone_repois now that function plus the printing sink the CLI wants, so credentials,TORII_CLONE_DEPTHand the empty-remote HEAD fixup have one implementation rather than two that drift.- Filter the log by author.
Aopens a dropdown of the identities in the loaded log — most commits first, with a count each — over an "all authors" row that lifts the filter. The cursor starts on whoever is filtered in already, or failing that on the author of the commit under the caret, so the usual ask isAthen Enter. The search box (/) reaches the same filter as anauthor:<who>qualifier, which narrows to one identity instead of matching the message as well. - The term is matched against the whole
Name <email>, so a bare name, a bare address and a pasted identity all reach the same commits; the menu writes the identity in full, because a name alone folds together two people who share one, and one person's two addresses. - "all authors" is a row rather than a second keybind: with the filter on there is no commit of anyone else's left in the list, so the menu has to carry its own undo.
- It pairs with the picking that landed alongside it: filter to the identity you mean to replace, then
spacedown the list, and every commit the pick lock would have refused is already gone from the view. - The heading says
of those loaded — ↓ for morewhile the log is still paginated. The filter only ever sees the commits already fetched, and a count that looks like the whole answer has to admit it is not one. - A filtered list pages like an unfiltered one.
jpast the last match pulls the next slice of history and re-runs the filter over it; it used to stop dead at the bottom of the loaded page, which made an author whose commits were further back look like an author with none. - The plain log search reaches the author's email. It matched the message, the name and the hash — never the address — so searching for the identity you were trying to get rid of came back empty.
- Pick commits in the log, then act on the picks.
spacemarks the commit under the caret and the ops dropdown becomes a short menu that takes the marked set as its subject —reauthor pickedandclear picks.Escdrops the selection. - The first pick locks the set to that author identity, and commits by anyone else are greyed and refused, with the reason in the event log. That is not a UI nicety:
reauthorreplaces *one*--old, so a set spanning two identities has nothing coherent to run with. - Because the set already agrees on an identity,
reauthor pickednever asks for the old one — it is the half that has to match exactly, and the selection already has it right. Only the replacement is typed. torii history reauthor --only <rev>...— restrict the identity change to named commits (repeatable or comma-separated), which is what the picked menu runs. Note what it does *not* promise: commits after a rewritten one are recreated regardless, because their parent moved, so their hashes change either way. A rev the walk never reaches is an error rather than a silent no-op.reauthorin the log's ops menu. Replacing an author identity across history was CLI-only — the menu went straight from "rewrite dates" to "scan history". It now prompts for the old identity and then the new one, and rewrites the committer alongside the author: a menu has no room for the CLI's--committerflag, and an identity fixed on one field and left stale on the other is the half-rewrite that sends people back to the terminal.- Both prompts want
Name <email>in full, including the old one — the CLI's looser--old(a bare name or a bare email) is bounded by--sinceand--dry-run, and the menu has neither. A long history keeps the same person under several identities, and half a pair matches all of them. - A malformed identity is refused on the prompt line, with the parser's own reason next to the cursor, instead of Enter doing nothing.
- The two prompts accept shifted characters. Every older prompt matches
KeyModifiers::NONEalone, which is harmless for a path or a ref and quietly eats the capitals and<>an identity is made of. - Refusals arrive verbatim, so the dirty-tree guard now reads as "working tree has uncommitted changes" instead of "reauthor failed".
Changed
statssits with the admin views. It is a look at the repo from a distance, not a daily action, and it was occupying the row underfiles. It drops to just abovebisect, sosaveandsyncsit next to the entry views.
Fixed
torii cloneends its progress line. The last📥 …was written with a carriage return and no newline, so✅ Cloned repository to: …landed on top of its tail.- Event-log messages wrap instead of being cut off. Each entry was one ratatui
Line, and aLinein aListis clipped, not wrapped — in a panel 55 columns wide at most, that left the timestamp and the first few words of every message. Entries now flow over as many lines as they need, with a hanging indent under the status symbol, and a word too wide for the panel (a hash, a path, an identity) is broken rather than lost.
- A clone view in the TUI. The sidebar's new
- 7513d5e3 feat clone from every git forge, and stop one that is running
- 677b1eba chore 0.16.0
- 9aacd90e feat clone a repository without leaving the TUI
- 601920ca feat a clone that reports progress instead of printing it
- 99f0c34f feat a dropdown of authors in the log
- d63e1cad feat filter the log by author
- 16ec889b feat pick commits in the log and reauthor just those
- 19565933 feat torii variable — CI variables and secrets
- 40c36884 style rustfmt the tiny-window test's panic closure
- 153d5232 docs pin the GitLab runner protocol and commit to an agent
- f7fe2c2e feat publish both AUR packages from the repository
- dd617f58 fix a window too small for a modal no longer kills the TUI
- 3c2b2709 chore 0.15.0
- efe1b7c0 style take the redundant borrows out of format! and rewrap submodule
- afa10e46 fix stop the config view from forking the test binary
- 7c9ad869 chore record the llm-qa baseline for this repo
- 85105574 feat register list rows for the mouse across the remaining views
- db10dcfc style cargo fmt over core vcs and platform contents
- a23cd4f2 feat mouse support, with a hit map and a switch to turn it off
- 7b7a7049 feat configure the scanner from the safety view
- 915252f0 fix apply the user's own secret rules everywhere, not only on save
- a7f45b50 chore lockfile follows the 0.14.0 bump
- 367069ff feat fold the ignore rules and the scanner into one safety view
- b389cabe feat stats sits second in the sidebar, where an overview belongs
- 1879b561 feat a people section in stats — addresses, aliases and signing
- 16fc5f93 feat a stats view for the repo and the workspace
- 536b192a feat the selected row is the accent, washed down
- c219450c fix drop the ellipsis from action labels
- d80daac1 fix wrap the keys rows instead of cutting the action id
- 32937c38 feat switch branch or workspace repo from any screen
- bde88d50 feat user-defined keys, with a config section and an action palette
- 44612f0f feat move ignore up the sidebar, next to snapshot
- dc745dac feat an ignore view for the .toriignore pair
- e7e4aad7 feat the secret scanner reports its findings into the event log
- 3cfd5757 feat put the events popup in the window chrome
- 93691834 fix tell behind, ahead and diverged apart in --verify
- 92583d53 chore 0.14.0
- 21e9dbc5 style cargo fmt over the restyled views
- 41873adf feat torii restore — put a tracked file back the way it was
- e565a692 fix keep core's CLI output off the alternate screen
- f7e13b57 fix re-derive the log view's state when the commit list is reloaded
- aa9df06e feat square nodes, and lanes in the rule's grey
- 7a4dc473 refactor move the hint strip and overlays onto the theme palette
- 5632b13c refactor move the log view's last colours onto the theme
- 5ed9bbee feat convert the platform view to the window chrome
- 94cfdec7 feat convert the pull request view to the window chrome
- 48bb45b4 feat convert the config and issue views to the window chrome
- 4c9ea75a fix let the bisect detail pane wrap its own paragraph
- 906e31e0 feat convert the auth and bisect views to the window chrome
- 35076328 feat convert the worktree and submodule views to the window chrome
- 88ac21c9 feat convert the remote and workspace views to the window chrome
- 309a1495 feat convert the snapshot and tag views to the window chrome
- 42438af7 feat convert the sync view to the window chrome
- b6bb8186 feat convert the commit view to the window chrome
- 08da391f feat convert the branch view, and let columns meet the rule below
- 78d78854 feat convert the log view to the window chrome
- bc25d21a fix tie a view's column rules into the rule above them
- 69b09a7a feat give the chrome the shape drawn on gitorii.com
- 48922f82 docs release artifacts stopped at v0.7.15, and the AUR plan behind it
- e3a44390 fix close missing DB-scheme aliases, stop excluding guessable passwords
- 01fd4420 chore bump version to 0.13.0
- d769da62 feat add --stage to prepare files without committing
- 836398a8 fix status and diff --staged no longer crash on unborn HEAD
- dfa77deb fix close secret-scanner detection gaps and false positives
- 8174a368 build vendor libgit2 (git2 vendored-libgit2 feature)
- 81629c16 feat GitLab support for remote contents
- 08885794 feat remote repo contents (tree + file) without cloning
- 2252a07b fix record MERGE_HEAD parents when committing a merge resolution
- 4b8a9a84 fix resolve remote-tracking branches when integrating
- f011daf1 fix use the GitHub REST API instead of gh for repo settings
- b8e50103 feat filter-branch/filter-repo suite; bump 0.12.0
- 9b9aae27 feat history reword + date-preserving save/amend; bump 0.11.0
- c584a9c7 style clear all 325 clippy warnings across the workspace
- 58b9c889 chore regenerate Cargo.lock for 0.10.0
- dcb53048 chore bump to 0.10.0 — torii-lib split, precise errors, fixes
- cd1aba4f refactor package torii-lib (import torii_lib) — nombre registrable
- 9149d88c style cargo fmt over the workspace
- 37f75dfb fix fail fast on findings without a TTY; add --yes
- 236888da fix reindex tracked entries when renaming a directory
- c0546586 chore drop stale TSAL header — relicensed MIT/Apache in 0.9.0
- f703c939 refactor workspace lib+bin — crates/torii-core + crates/torii
- 78e0e28c refactor WorkspaceManager devuelve datos, el CLI imprime
- 301e713b refactor sellar fugas git2 de la API pública + vcs/sign.rs
- 0e1e827f refactor status() devuelve RepoStatus en vez de imprimir
- 422a4529 chore regenerate Cargo.lock for 0.9.2
- 764e62b8 chore bump to 0.9.2 — refresh README badges (license, rust)
- b1c335d3 chore bump MSRV to rustc 1.95 (Cargo.toml + README badge)
- c83d6f56 chore regenerate Cargo.lock for 0.9.1
- bf56dac9 chore unpin russh, drop rust-toolchain.toml
- db4693b9 chore regenerate Cargo.lock for 0.9.0
- 5058b53d chore relicense to MIT OR Apache-2.0
- 712e61b8 feat Log ops dropdown gains history ops
- d7463efe docs refresh crates.io / README presence
- c6bec5c0 chore bump Cargo.lock for 0.8.1
- 78b23b73 feat split online/local runners in Platform Runners sub-tab
- 53af6e76 feat platforms.toml registry + GitLab self-hosted
- 122acbd0 feat submodule ops dropdown
- ed6a7c31 fix+feat workspace path bug + OAuth auto-refresh + worktree TUI ops
- 1ed0aad4 feat exec local job — gitlab-runner exec / gitlab-ci-local / act