Radish alpha
r
rad:z371PVmDHdjJucejRoRYJcDEvD5pp
Radicle website including documentation and guides
Radicle
Git
radicle.xyz _posts 2026-03-18-radicle-1.7.0.md

[748ddad]: {{ “rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/commits/748ddade2feb6f00245c2ba878bd54842dc57506” | explore }}

Spring has sprung, where we’re writing from, and Daffodils are in season!

The Radicle team are springing into action and announcing the release of Radicle 1.7.0 ([748ddad]), code name Daffodil. The Daffodil is the national flower of Wales and starts to pop up in February/March – guiding us into the spring time.

This release consists of 226 commits from 11 contributors. Thank you to all the amazing contributors who provided valuable work this release:

  • Aaron Würth
  • Defelo
  • justarandomgeek
  • Matthias Beyer
  • Sebastian Martinez
  • srestegosaurio
  • Yorgos Saslis

Installation

curl -sSLf {{ site.url }}/install | sh -s -- --no-modify-path --version=1.7.0

⚠️ Security Fix

This release contains a security fix, and so it is highly recommended that you update all of your nodes. The information on the vulnerability will be disclosed on the 2026-03-30, with a full write-up at <{{ site.url }}{% post_url 2026-03-30-disclosure-of-vulnerability-in-signed-references %}>.

We have taken the time to scan all existing repositories on our public seeds, and have not detected any active exploitation of the vulnerability with malicious intent as of today, 2026-03-18.

New Features

Improved rad/sigrefs

[989edacd564fa658358f5ccfd08c243c5ebd8cda]: {{ “rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/commits/989edacd564fa658358f5ccfd08c243c5ebd8cda” | explore }}

The “Signed References” feature was reimplemented. The commits in refs/rad/sigrefs will now only verify if they carry an appropriate value for refs/rad/root in the associated refs blob. This reference was introduced in commit [989edacd564fa658358f5ccfd08c243c5ebd8cda], which was released via version 1.1.0. A new reference, refs/rad/sigrefs-parent, is now recorded in the refs blob, when writing a new entry. If present, its target must match the parent commit. This is to prevent a replay of a previous refs/rad/sigrefs commit. It is optional to maintain backwards compatibility, and might become mandatory (like refs/rad/root does in this release) in the future. Further, the new implementation detects replay of refs blobs. In order to do so, it walks the history of refs/rad/sigrefs backwards to the root commit, if refs/rad/sigrefs-parent is not set.

Blocking Policies

For those familiar with rad block, you may be aware that you can block a NodeId. Previous to this release, the blocked node’s references would be rejected during a fetch. However, it would not be blocked on the connection management level. With the changes included in this release, blocked nodes are now also blocked at the connection level. Any attempts for inbound or outbound connections will be rejected.

Include a Wider Set of References

The references of a remote were restricted to heads, tags, notes, rad, and cobs. This is too restrictive, and does not allow the extensibility that Git affords us as users. The restriction is now lifted, and the only references that are filtered out are refs/tmp/heads; used by radicle-remote-helper to create temporary patches.

Better Errors for rad id Updates

Using rad id to update the identity document as a non-delegate would result in unclear errors. Now, when a non-delegate user attempts to update the document, they will have a clearer error given to them.

$ rad id update \
    --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji \
    --title "Add myself!" \
    --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk \
    --no-confirm
✗ Error: did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk is not a delegate, and only delegates are allowed to create a revision
✗ Hint: bob (you) is attempting to modify the identity document but is not a delegate!

Improved I/O Usage

Radicle uses sqlite for local state storage, and it was configured to use journal_mode = WAL, and the default value of synchronous = FULL. It was recently found that this combination would result in a high amount of I/O operations for a long running node. The journal_mode and synchronous pragmas are now configurable from rad config edit. The new default values for both are WAL and NORMAL, respectively. This results in less I/O operations. On power loss, transactions might be rolled back, but SQLite still guarantees consistency in this mode.

Fixed Bugs

Windows

Use winsplit on Windows

When preparing commands to execute, the shlex crate was used on all platforms. The semantics on Windows are different (e.g. ‘\’ is a path separator on Windows but marks an escape sequence on Unix-like systems). This lead to issues when attempting to execute child processes, and was fixed by using winsplit on Windows instead.

Prevent git-upload-pack Zombies

One of our Windows users noticed that git-upload-pack processes would never be reaped, resulting in zombie processes. These zombie processes are now prevented by using the “Job” API of the operating system to group child processes and their children.

Signal Handling Support

Signal handling is now supported, and so the radicle-node executable will now respect signals on Windows.

Responsive CLI Commands

Users of the rad CLI would often encounter the following output:

✗ Error: timed out reading from control socket

The reason for this was that the request/response pattern that was implemented never accounted for errors. When the Service would receive a request that resulted in a failure, it would log it, and move on. The Service has now learned to respond with errors. This will improve the above error scenarios by providing more information about the error that occurred.

IPv6 Address Parsing

Parsing addresses involving an IPv6 host failed if they were enclosed in square brackets, e.g. in rad node connect z6Mk...@[::1]:8776. Also, ambiguous addresses would parse, e.g. ::1:8776 would be indistinguishable from [::1]:8776. Since a port number is always required along with a host when providing an address, IPv6 addresses now always require brackets to avoid confusion. Existing IPv6 addresses that are stored in the sqlite database are migrated automatically on node startup.

Deprecations

rad fork

The rad fork command was confusing, and mislead users as to what its purpose was. Many believed it to create a hard-fork of the repository. Instead, it pushed the default branch to the local user’s namespace. The command is now deprecated, and you should use git push instead.

Breaking Changes

Seeds No Longer Contains Fetching Information

If you are using the radicle-node control socket, and request Seeds information, then expect a breaking change to the output. The Connected state of a peer no longer contains fetching information, which was separated out. This has resulted in the entire fetching value being removed.

Changes to rad node debug Information

The rad node debug information for ongoing fetches contained the number of subscribers awaiting for results, this was removed.

COB Type Names are More DNS Compliant

The TypeName strings defined in radicle-cob are restricted to reflect the size limits on domain names as specified in RFC-1035. These restrictions are:

  • A total length of 255 bytes.
  • A max component length of 63 bytes.

Human-readable Timeout Durations

Several rad commands take a --timeout option, and each one would vary in units, e.g. seconds, milliseconds. These options now take human-readable durations as values, e.g. “9s” for 9 seconds, “1min” for 1 minute, etc. This is a breaking change since these options now require the unit to be specified.

Changelog

This release contains 226 commit(s) by 11 contributor(s).

Checksums

e6de41ba2b2efd07b9ab008717d720184f8385c3bb93ad5c4a37f257179ecfed  radicle-1.7.0-x86_64-apple-darwin.tar.xz
0dd4d185bd6a1e5588ec879471678c482b0cc27d92cb2cc3b22982e63e920049  radicle-1.7.0-aarch64-unknown-linux-musl.tar.xz
dd9b734dc7b7b7132e7a27e5a53e268276870bbebd195ff6c0e1273ec2984dea  radicle-1.7.0-aarch64-apple-darwin.tar.xz
e23ad2f616d9730db5ae4eb730baad1373172e2dcaec1fef2c6b199dba514378  radicle-1.7.0-x86_64-unknown-linux-musl.tar.xz
---
title: "Radicle 1.7.0 – Daffodil"
image: radicle-1.png
---

[748ddad]: {{ "rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/commits/748ddade2feb6f00245c2ba878bd54842dc57506" | explore }}

Spring has sprung, where we're writing from, and Daffodils are in season!

The Radicle team are springing into action and announcing the release of Radicle 1.7.0 ([748ddad]), code name *Daffodil*.
The Daffodil is the national flower of Wales and starts to pop up in February/March – guiding us into the spring time.

This release consists of 226 commits from 11 contributors.
Thank you to all the amazing contributors who provided valuable work this release:
- Aaron Würth
- Defelo
- justarandomgeek
- Matthias Beyer
- Sebastian Martinez
- srestegosaurio
- Yorgos Saslis

## Installation

```
curl -sSLf {{ site.url }}/install | sh -s -- --no-modify-path --version=1.7.0
```

## ⚠️ Security Fix

This release contains a security fix, and so it is **highly recommended that you update all of your nodes**.
The information on the vulnerability will be disclosed on the 2026-03-30, with a full write-up at <{{ site.url }}{% post_url 2026-03-30-disclosure-of-vulnerability-in-signed-references %}>.

We have taken the time to scan all existing repositories on our public seeds, and have not detected any active exploitation of the vulnerability with malicious intent as of today, 2026-03-18.

## New Features

### Improved `rad/sigrefs`

[`989edacd564fa658358f5ccfd08c243c5ebd8cda`]: {{ "rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5/commits/989edacd564fa658358f5ccfd08c243c5ebd8cda" | explore }}

The "Signed References" feature was reimplemented.
The commits in `refs/rad/sigrefs` will now only verify if they carry an appropriate value for `refs/rad/root` in the associated `refs` blob.
This reference was introduced in commit [`989edacd564fa658358f5ccfd08c243c5ebd8cda`], which was released via version 1.1.0.
A new reference, `refs/rad/sigrefs-parent`, is now recorded in the `refs` blob, when writing a new entry.
If present, its target must match the parent commit. This is to prevent a replay of a previous `refs/rad/sigrefs` commit.
It is optional to maintain backwards compatibility, and might become mandatory (like `refs/rad/root` does in this release) in the future.
Further, the new implementation detects replay of `refs` blobs.
In order to do so, it walks the history of `refs/rad/sigrefs` backwards to the root commit, if `refs/rad/sigrefs-parent` is not set.

### Blocking Policies

For those familiar with `rad block`, you may be aware that you can block a `NodeId`.
Previous to this release, the blocked node's references would be rejected during a fetch.
However, it would not be blocked on the connection management level.
With the changes included in this release, blocked nodes are now also blocked at the connection level.
Any attempts for inbound or outbound connections will be rejected.

### Include a Wider Set of References

The references of a remote were restricted to `heads`, `tags`, `notes`, `rad`, and `cobs`.
This is too restrictive, and does not allow the extensibility that Git affords us as users.
The restriction is now lifted, and the only references that are filtered out are `refs/tmp/heads`; used by `radicle-remote-helper` to create temporary patches.

### Better Errors for `rad id` Updates

Using `rad id` to update the identity document as a non-delegate would result in unclear errors.
Now, when a non-delegate user attempts to update the document, they will have a clearer error given to them.

```
$ rad id update \
    --repo rad:z42hL2jL4XNk6K8oHQaSWfMgCL7ji \
    --title "Add myself!" \
    --delegate did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk \
    --no-confirm
✗ Error: did:key:z6Mkt67GdsW7715MEfRuP4pSZxJRJh6kj6Y48WRqVv4N1tRk is not a delegate, and only delegates are allowed to create a revision
✗ Hint: bob (you) is attempting to modify the identity document but is not a delegate!
```

### Improved I/O Usage

Radicle uses `sqlite` for local state storage, and it was configured to use `journal_mode = WAL`, and the default value of `synchronous = FULL`.
It was recently found that this combination would result in a high amount of I/O operations for a long running node.
The `journal_mode` and `synchronous` pragmas are now configurable from `rad config edit`.
The new default values for both are `WAL` and `NORMAL`, respectively. This results in less I/O operations.
On power loss, transactions might be rolled back, but SQLite still guarantees consistency in this mode.

## Fixed Bugs

### Windows

#### Use `winsplit` on Windows

When preparing commands to execute, the `shlex` crate was used on all platforms.
The semantics on Windows are different (e.g. '\\' is a path separator on Windows but marks an escape sequence on Unix-like systems).
This lead to issues when attempting to execute child processes, and was fixed by using `winsplit` on Windows instead.

#### Prevent `git-upload-pack` Zombies

[Job]: https://learn.microsoft.com/en-us/windows/win32/procthread/job-objects

One of our Windows users noticed that `git-upload-pack` processes would never be reaped, resulting in zombie processes.
These zombie processes are now prevented by using the "[Job]" API of the operating system to group child processes and their children.

#### Signal Handling Support

Signal handling is now supported, and so the `radicle-node` executable will now respect signals on Windows.

### Responsive CLI Commands

Users of the `rad` CLI would often encounter the following output:

```
✗ Error: timed out reading from control socket
```

The reason for this was that the request/response pattern that was implemented never accounted for errors.
When the `Service` would receive a request that resulted in a failure, it would log it, and move on.
The `Service` has now learned to respond with errors.
This will improve the above error scenarios by providing more information about the error that occurred.

### IPv6 Address Parsing

Parsing addresses involving an IPv6 host failed if they were enclosed in square brackets, e.g. in `rad node connect z6Mk...@[::1]:8776`.
Also, ambiguous addresses would parse, e.g. `::1:8776` would be indistinguishable from `[::1]:8776`.
Since a port number is always required along with a host when providing an address, IPv6 addresses now always require brackets to avoid confusion.
Existing IPv6 addresses that are stored in the `sqlite` database are migrated automatically on node startup.

## Deprecations

### `rad fork`

The `rad fork` command was confusing, and mislead users as to what its purpose was.
Many believed it to create a hard-fork of the repository.
Instead, it pushed the default branch to the local user's namespace.
The command is now deprecated, and you should use `git push` instead.

## Breaking Changes

### `Seeds` No Longer Contains Fetching Information

If you are using the `radicle-node` control socket, and request `Seeds` information, then expect a breaking change to the output.
The `Connected` state of a peer no longer contains fetching information, which was separated out.
This has resulted in the entire `fetching` value being removed.

### Changes to `rad node debug` Information

The `rad node debug` information for ongoing fetches contained the number of subscribers awaiting for results, this was removed.

### COB Type Names are More DNS Compliant

[RFC-1035]: https://www.rfc-editor.org/rfc/rfc1035#section-2.3.4

The `TypeName` strings defined in `radicle-cob` are restricted to reflect the size limits on domain names as specified in [RFC-1035].
These restrictions are:
- A total length of 255 bytes.
- A max component length of 63 bytes.

### Human-readable Timeout Durations

Several `rad` commands take a `--timeout` option, and each one would vary in units, e.g. seconds, milliseconds.
These options now take human-readable durations as values, e.g. "9s" for 9 seconds, "1min" for 1 minute, etc.
This is a breaking change since these options now require the unit to be specified.

## Changelog

This release contains 226 commit(s) by 11 contributor(s).

* `748ddade` **fetch: Make `RemoteRefs` an alias** *<lorenz.leutgeb@radicle.xyz>*
* `35d71f59` **fetch: Remove `DelegateStatus`** *<lorenz.leutgeb@radicle.xyz>*
* `363a7231` **fetch: Remove dead code from `DataRefs`** *<lorenz.leutgeb@radicle.xyz>*
* `725ced09` **fetch: Prune remotes with sigrefs failures** *<fintan.halpenny@gmail.com>*
* `6967bf8f` **radicle: Automatically upgrade sigrefs** *<lorenz.leutgeb@radicle.xyz>*
* `20598d39` **radicle: Remove unused `SyncedAt::load`** *<lorenz.leutgeb@radicle.xyz>*
* `0f9eace8` **crypto: Remove markers `Verified` and `Unverified`** *<lorenz.leutgeb@radicle.xyz>*
* `304a6631` **radicle: Remove generics for verification markers** *<lorenz.leutgeb@radicle.xyz>*
* `393eca39` **node/e2e: `rad/sigrefs-parent` is not fetched** *<fintan.halpenny@gmail.com>*
* `d40fa9a3` **radicle/sigrefs: Switch to new implementation** *<fintan.halpenny@gmail.com>*
* `d3bc868e` **radicle/sigrefs: Rewrite Signed References** *<fintan.halpenny@gmail.com>*
* `52a660fd` **node/test: Set `RAD_RNG_SEED`** *<lorenz.leutgeb@radicle.xyz>*
* `99d92421` **Use humantime to parse timeouts** *<mail@beyermatthias.de>*
* `52e55812` **cli: Don't override existing seeding scope in `rad seed`** *<mail@defelo.de>*
* `281f92e9` **cli/tests: Add test for `rad clone --scope`** *<mail@defelo.de>*
* `eea36177` **use `CONIN$` instead of `/dev/tty` on windows** *<justarandomgeek@gmail.com>*
* `a1fd9e04` **radicle: Update `sqlite` to 0.37** *<fintan.halpenny@gmail.com>*
* `07369771` **node: Migrate IPv6 addresses in database** *<lorenz.leutgeb@radicle.xyz>*
* `9e8f09a1` **Remove stray files** *<fintan.halpenny@gmail.com>*
* `0c47d06f` **radicle/storage/refs: Strengthen Encapsulation** *<fintan.halpenny@gmail.com>*
* `f4495e92` **radicle/device: `impl Keypair for BoxedSigner`** *<lorenz.leutgeb@radicle.xyz>*
* `74fa4425` **crypto: Require `Signer: signature::Signer`** *<lorenz.leutgeb@radicle.xyz>*
* `06fae85e` **crypto: `impl Signer` based on `Keypair`** *<lorenz.leutgeb@radicle.xyz>*
* `f2ad5454` **crypto: `impl signature::KeypairRef` for Signers** *<lorenz.leutgeb@radicle.xyz>*
* `768ecf56` **crypto: Add `impl Verifier for PublicKey`** *<fintan.halpenny@gmail.com>*
* `01c60388` **git-metadata: Add parsing of `CommitData`** *<fintan.halpenny@gmail.com>*
* `58624148` **git-metadata: Add `CommitData::strip_signatures`** *<fintan.halpenny@gmail.com>*
* `60871de8` **git-metadata: Add derivable traits** *<fintan.halpenny@gmail.com>*
* `0e45347b` **radicle/storage: Improve `Validation` error** *<lorenz.leutgeb@radicle.xyz>*
* `ba9c09fa` **radicle/refs: Better `SignedRefs` Encapsulation** *<fintan.halpenny@gmail.com>*
* `39a58ded` **node/test: Use `Arbitrary` for `SignedRefs`** *<fintan.halpenny@gmail.com>*
* `f7ff4d8f` **radicle/arbitrary: Move `impl Arbitrary` of refs** *<fintan.halpenny@gmail.com>*
* `b8502397` **protocol/wire: Remove SignedRefs encoding/decoding** *<fintan.halpenny@gmail.com>*
* `ba8d6b88` **radicle/storage: Remove unused Remote methods** *<fintan.halpenny@gmail.com>*
* `e78d477b` **radicle/git: Remove unused `fn remote_refs`** *<lorenz.leutgeb@radicle.xyz>*
* `759a6fb9` **radicle: Compile `rad::fork_remote` only for tests** *<fintan.halpenny@gmail.com>*
* `7bac1714` **CHANGELOG: fix typo** *<fintan.halpenny@gmail.com>*
* `cb3ca622` **radicle/CHANGELOG: remove variant typo** *<fintan.halpenny@gmail.com>*
* `9dbbb01d` **radicle: remove `TryFrom`** *<fintan.halpenny@gmail.com>*
* `57da7799` **radicle: Add a `load` method to `radicle::profile::Home`** *<me@sebastinez.dev>*
* `ff85c74e` **cli: Add blank line after issue reply header** *<mail@beyermatthias.de>*
* `1b986af0` **cli/tests: Refactor workflow test** *<fintan.halpenny@gmail.com>*
* `fa82bd5f` **cli/tests: Refactor watch command tests** *<adrian.duke@gmail.com>*
* `45e6afd0` **cli/tests: Refactor utility command tests** *<fintan.halpenny@gmail.com>*
* `d282e0d0` **cli/tests: Refactor sync command tests** *<fintan.halpenny@gmail.com>*
* `7d2842a4` **cli/tests: Refactor remote command tests** *<adrian.duke@gmail.com>*
* `c1ab7c38` **cli/tests: Refactor policy command tests** *<adrian.duke@gmail.com>*
* `18d7f99e` **cli/tests: Refactor patch command tests** *<adrian.duke@gmail.com>*
* `4ffabde6` **cli/tests: Refactor node command tests** *<adrian.duke@gmail.com>*
* `b2568f0b` **cli/tests: Refactor jj command tests** *<adrian.duke@gmail.com>*
* `4753b889` **cli/tests: Refactor issue command tests** *<adrian.duke@gmail.com>*
* `8bf655ef` **cli/tests: Refactor init command tests** *<adrian.duke@gmail.com>*
* `a1c1b03b` **cli/tests: Refactor inbox command tests** *<adrian.duke@gmail.com>*
* `cd4532ec` **cli/tests: Refactor id command tests** *<adrian.duke@gmail.com>*
* `dac099e4` **cli/tests: Refactor git command tests** *<adrian.duke@gmail.com>*
* `d39e485c` **cli/tests: Refactor cob command tests** *<adrian.duke@gmail.com>*
* `1f3dc6ae` **cli/tests: Refactor clone command tests** *<adrian.duke@gmail.com>*
* `7a1e6a24` **cli/tests: Refactor checkout command tests** *<fintan.halpenny@gmail.com>*
* `5aaf978f` **radicle: Configure database connections on open** *<lorenz.leutgeb@radicle.xyz>*
* `f3afe7b0` **radicle/config/sqlite: Use `synchronous = NORMAL`** *<lorenz.leutgeb@radicle.xyz>*
* `f4aee203` **radicle: Make SQLite pragmas configurable** *<yorgos.work@proton.me>*
* `6cc3da95` **radicle/node/db: Model SQLite `synchronous` pragma** *<yorgos.work@proton.me>*
* `d36bf41f` **radicle/node/db: Directly represent SQLite pragmas** *<yorgos.work@proton.me>*
* `9ff67562` **cli: Format IPv6 addresses in square brackets** *<mail@defelo.de>*
* `df8e4e6c` **node: Parse IPv6 addresses in square brackets** *<mail@defelo.de>*
* `7c923608` **radicle: fix to schemars of DefaultSeedingPolicy** *<fintan.halpenny@gmail.com>*
* `6291cae5` **cli: add `rad config schema` to the `rad-config` test** *<fintan.halpenny@gmail.com>*
* `f018b434` **node: control debug serialization of FetcherState** *<fintan.halpenny@gmail.com>*
* `9ea1ea24` **Revert "node/debug: Use derived serializers"** *<fintan.halpenny@gmail.com>*
* `e9245b63` **cli: don't override existing seeding scope in `rad clone`** *<mail@defelo.de>*
* `b04f487b` **term: Update to 0.17.0** *<fintan.halpenny@gmail.com>*
* `9a98cf7b` **keccak: Update to 0.1.6** *<fintan.halpenny@gmail.com>*
* `bab3f82a` **fetch: Update to 0.17.0** *<fintan.halpenny@gmail.com>*
* `a0b434c3` **localtime: add description in Cargo.toml** *<fintan.halpenny@gmail.com>*
* `9dba9130` **core: use "data-types" instead of "data types"** *<fintan.halpenny@gmail.com>*
* `f9a36ef7` **systemd: Update to 0.12.0** *<fintan.halpenny@gmail.com>*
* `18d6ce94` **protocol: Update 0.5.0** *<fintan.halpenny@gmail.com>*
* `c0ae5e32` **node: Update to 0.17.0** *<fintan.halpenny@gmail.com>*
* `963b4ded` **crypto: Update to 0.15.0** *<fintan.halpenny@gmail.com>*
* `84e9ffe4` **cob: Update to 0.18.0** *<fintan.halpenny@gmail.com>*
* `186d8d30` **cli: Update to 0.18.0** *<fintan.halpenny@gmail.com>*
* `3a110746` **radicle: Update to 0.21.0** *<fintan.halpenny@gmail.com>*
* `15666467` **radcile/cob/identity: mark ApplyError as non_exhaustive** *<fintan.halpenny@gmail.com>*
* `d596b14e` **build: Pin Zig to 0.13.0** *<fintan.halpenny@gmail.com>*
* `4c759a26` **build: Update macos-sdk to include IOKit, libconv, and libcharset** *<fintan.halpenny@gmail.com>*
* `57a44dae` **build: Update cargo-zigbuild to 0.22.1** *<fintan.halpenny@gmail.com>*
* `89478b16` **cargo/git2: Update to 0.20.4** *<fintan.halpenny@gmail.com>*
* `423cf604` **nix: update to 25.11** *<fintan.halpenny@gmail.com>*
* `30701cc6` **node/runtime: Make `Runtime::run` more readable** *<lorenz.leutgeb@radicle.xyz>*
* `057edf55` **node/reactor: Introduce `LAG_TIMEOUT`** *<lorenz.leutgeb@radicle.xyz>*
* `ae06111e` **node/reactor: Rewrite `Runtime::run`** *<lorenz.leutgeb@radicle.xyz>*
* `4d7b942b` **remote-helper: Rename `to_branch_name`** *<lorenz.leutgeb@radicle.xyz>*
* `6d2a99e1` **remote-helper: Remove Unused Error Variants** *<lorenz.leutgeb@radicle.xyz>*
* `a69420b9` **remote-helper: Rework Visibility Modifiers** *<lorenz.leutgeb@radicle.xyz>*
* `d36ed7c8` **remote-helper/protocol: Introduce Line and Command** *<adrian.duke@gmail.com>*
* `27493c22` **remote-helper/service: Introduce `NodeSession`** *<adrian.duke@gmail.com>*
* `56253b52` **remote-helper/service: Introduce `GitService`** *<adrian.duke@gmail.com>*
* `bd30e80b` **remote-helper/list: Remove printing to stdio** *<adrian.duke@gmail.com>*
* `119445ce` **cli-test: Move `let mut args` closer to its uses** *<lorenz.leutgeb@radicle.xyz>*
* `56ece480` **cli-test: Remove special handling for `rad`** *<lorenz.leutgeb@radicle.xyz>*
* `3cd1af1d` **cli-test: Configure `escargot` properly** *<lorenz.leutgeb@radicle.xyz>*
* `5aca9bf1` **cli-test: Refactor Path Handling** *<lorenz.leutgeb@radicle.xyz>*
* `d88ef3fa` **e2e: Introduce 3 tests for block command** *<adrian.duke@gmail.com>*
* `a4806f27` **node/test: check remote events for `Event::PeerDisconnected`** *<fintan.halpenny@gmail.com>*
* `1fa14ef5` **protocol/service: Use block list for connections** *<adrian.duke@gmail.com>*
* `94e0a512` **node: Add block command to control socket** *<adrian.duke@gmail.com>*
* `4286590f` **fetch: move `Component::from` outside of loop** *<fintan.halpenny@gmail.com>*
* `0e9d7607` **hooks: Enable typos, fix reported errors** *<lorenz.leutgeb@radicle.xyz>*
* `5fa68ed8` **node: Use `gix_packetline`** *<lorenz.leutgeb@radicle.xyz>*
* `c96aea06` **node/e2e: Fix test_non_fastforward_identity_doc** *<adrian.duke@gmail.com>*
* `832598ce` **cli: Warn user about implicit seeding policy** *<adrian.duke@gmail.com>*
* `cee3659e` **radicle: Introduce `radicle::node::config::Scope`** *<adrian.duke@gmail.com>*
* `306d0afb` **protocol: Note on peering and fetches** *<adrian.duke@gmail.com>*
* `0684d1cc` **cli: Changed the default scope from all to followed for clone and seed** *<adrian.duke@gmail.com>*
* `dd13eed1` **cli: Do not print scope in block table** *<adrian.duke@gmail.com>*
* `b5e8776e` **fetch: Improve `refs/rad/id` resolution** *<adrian.duke@gmail.com>*
* `84320919` **node/tests/e2e: use assert_eq! in test** *<fintan.halpenny@gmail.com>*
* `7862e108` **Update gix-* crates** *<fintan.halpenny@gmail.com>*
* `39157117` **fetch: introduce domain type RefPrefix** *<fintan.halpenny@gmail.com>*
* `8070f98a` **fetch/transport/ls_refs: Post-filter of references** *<fintan.halpenny@gmail.com>*
* `980ed561` **protocol/service: rename `Responder::new` to `Responder::oneshot`** *<fintan.halpenny@gmail.com>*
* `0d628a45` **protocol: refactor to use Responder** *<fintan.halpenny@gmail.com>*
* `b1eedd3b` **protocol/service: introduce Responder type** *<fintan.halpenny@gmail.com>*
* `61a9b214` **protocol/service: introduce Result synonym** *<fintan.halpenny@gmail.com>*
* `2c197215` **protocol: opaque command error** *<fintan.halpenny@gmail.com>*
* `38713a8e` **protocol/service: drop `chan` qualifier** *<fintan.halpenny@gmail.com>*
* `912a5ca4` **protocol/service: create command module** *<fintan.halpenny@gmail.com>*
* `fa94638a` **radicle/storage/init: Remove placeholder files** *<lorenz.leutgeb@radicle.xyz>*
* `7425ae4b` **ssh: Treat "connection refused" on Windows** *<lorenz.leutgeb@radicle.xyz>*
* `5099c25d` **node/debug: Use derived serializers** *<lorenz.leutgeb@radicle.xyz>*
* `a1fa3801` **protocol: Depend on `cypheraddr` not `cyphernet`** *<lorenz.leutgeb@radicle.xyz>*
* `d530f126` **node/test: Remove unused file `environment.rs`** *<lorenz.leutgeb@radicle.xyz>*
* `730d696d` **node/test: Bind to loopback interface** *<lorenz.leutgeb@radicle.xyz>*
* `dfe3b501` **radicle/git/raw: `Config` not used on Windows** *<lorenz.leutgeb@radicle.xyz>*
* `ed2b36cf` **cli-test: Log line of assertion being executed** *<lorenz.leutgeb@radicle.xyz>*
* `9055a204` **cli-test: Add placeholder for executable extension** *<lorenz.leutgeb@radicle.xyz>*
* `e831aeb5` **cli-test: Do not store `bins`** *<lorenz.leutgeb@radicle.xyz>*
* `8fbdd46c` **cli-test: Cheat to find coreutils on Windows** *<lorenz.leutgeb@radicle.xyz>*
* `4894657b` **cli-test: Simplify cargo path handling** *<lorenz.leutgeb@radicle.xyz>*
* `25d1974c` **cli-test: Deduplicate populating `bins`** *<lorenz.leutgeb@radicle.xyz>*
* `44f52f4c` **cli-test: Fix uses of `PATH_SEPARATOR`** *<lorenz.leutgeb@radicle.xyz>*
* `dd122f10` **cli/test: Ignore `rad_diff` on Windows** *<lorenz.leutgeb@radicle.xyz>*
* `5974fa32` **windows: Add installer build** *<lorenz@lap-21-0150.mpi-inf.mpg.de>*
* `c06b00e3` **CVE-2026-25727** *<fintan.halpenny@gmail.com>*
* `31607cf7` **CVE-2026-25541** *<fintan.halpenny@gmail.com>*
* `2d0db3c6` **CVE-2025-58160** *<fintan.halpenny@gmail.com>*
* `03bbe524` **signals: Add support for Windows** *<lorenz.leutgeb@radicle.xyz>*
* `865abd35` **protocol/fetcher: Intro `RefsToFetch`** *<lorenz.leutgeb@radicle.xyz>*
* `9081c11b` **protocol/fetcher: Remove `from` from `QueuedFetch`** *<lorenz.leutgeb@radicle.xyz>*
* `53a12869` **protocol/service: Remove unnecessary arg** *<lorenz.leutgeb@radicle.xyz>*
* `94d7799f` **protocol/fetcher/state: Typo** *<lorenz.leutgeb@radicle.xyz>*
* `56ee626a` **protocol/fetcher: Delete unused file** *<lorenz.leutgeb@radicle.xyz>*
* `41f77a49` **RELEASE: start at rc.1** *<fintan.halpenny@gmail.com>*
* `613c4e83` **protocol: separate subscribers by RefsAt** *<fintan.halpenny@gmail.com>*
* `993428df` **node: donwgrade log error to trace for disconnection** *<fintan.halpenny@gmail.com>*
* `aeba81f4` **core: add documentation to `RepoId::from_canonical`** *<fintan.halpenny@gmail.com>*
* `35a01898` **core: guard on expected multibase** *<fintan.halpenny@gmail.com>*
* `8ee32168` **radicle: remove file** *<fintan.halpenny@gmail.com>*
* `ebf7d876` **node: Control via `uds_windows` not `winpipe`** *<lorenz.leutgeb@radicle.xyz>*
* `90cf37c4` **node: On Windows, use job for upload-pack child** *<lorenz.leutgeb@radicle.xyz>*
* `990edbf0` **windows: Introduce new crate** *<lorenz.leutgeb@radicle.xyz>*
* `50fb228a` **term/editor: Implement `exists` for Windows** *<lorenz.leutgeb@radicle.xyz>*
* `450b664a` **term/editor: Use `cfg`-attribute instead of macro** *<lorenz.leutgeb@radicle.xyz>*
* `8fb2d96b` **radicle/profile: No pager from Git on Windows** *<lorenz.leutgeb@radicle.xyz>*
* `930ec175` **term, cli: `winsplit` over `shlex` on Windows** *<lorenz.leutgeb@radicle.xyz>*
* `537eaba8` **Use rust-analyzer from tool chain in devShell** *<aaron.wuerth@posteo.de>*
* `d7a4137e` **systemd: remove redundant lines from system unit** *<lcdt@disroot.org>*
* `27ee6e10` **ci: Enable debugging on Windows** *<lorenz.leutgeb@radicle.xyz>*
* `fefa2837` **cli/init: Canonicalize path before comparison** *<lorenz.leutgeb@radicle.xyz>*
* `ffbbb374` **cli-test: Path separation compatible with Windows** *<lorenz.leutgeb@radicle.xyz>*
* `faeee9f3` **crypto: Optionally provide JSON Schema** *<lorenz.leutgeb@radicle.xyz>*
* `82ad52b1` **cob: further restrict TypeName** *<fintan.halpenny@gmail.com>*
* `fe09cd4a` **cob: split up typename tests** *<fintan.halpenny@gmail.com>*
* `204db22b` **cob: enable sha1 feature** *<fintan.halpenny@gmail.com>*
* `1cab036c` **protocol/service: Wire up `FetcherService`** *<fintan.halpenny@gmail.com>*
* `9e208909` **protocol: Introduce `FetcherService`** *<fintan.halpenny@gmail.com>*
* `f0e3ca34` **protocol: Introduce `FetcherState`** *<fintan.halpenny@gmail.com>*
* `7cf73300` **radicle/storage/refs: Derive `Hash` for `RefsAt`** *<fintan.halpenny@gmail.com>*
* `eccfd6ba` **cli: optional message for issue comments** *<fintan.halpenny@gmail.com>*
* `c33c26fa` **cli: fix casing for warning of preferred_seeds** *<fintan.halpenny@gmail.com>*
* `15adb161` **protocol: missed formatting** *<fintan.halpenny@gmail.com>*
* `91eb6fc0` **protocol: ensure `connect` supports connecting address** *<fintan.halpenny@gmail.com>*
* `36d5a4c8` **protocol: use helper method** *<fintan.halpenny@gmail.com>*
* `73f9a350` **protocol: reuse session address for reconnect** *<fintan.halpenny@gmail.com>*
* `589925e3` **radicle/node: avoid unnecessary allocations in `Emitter::emit_all`** *<mail@defelo.de>*
* `8b1d4751` **protocol: batch inventory removals and events in `sync_routing`** *<mail@defelo.de>*
* `d2ab7b1b` **RELEASE: include patch releases** *<fintan.halpenny@gmail.com>*
* `1c9a1b4f` **RELEASE: Add file documenting the release process** *<fintan.halpenny@gmail.com>*
* `e63c3097` **cli/fork: Deprecate** *<lorenz.leutgeb@radicle.xyz>*
* `b937a938` **radicle-cli: more helpful error for non-delegate updates** *<adrian.duke@gmail.com>*
* `60959f7e` **cli: promote WithHint hint type to String** *<adrian.duke@gmail.com>*
* `67a4a712` **radicle: add new error type for unauthorized non-delegates** *<adrian.duke@gmail.com>*
* `bd5436d7` **core: Fix doctest** *<lorenz.leutgeb@radicle.xyz>*
* `b41ce2e6` **radicle/canonical: provide public Canonical JSON link** *<fintan.halpenny@gmail.com>*
* `f6d3dae4` **CHANGELOG: Release 1.6.1** *<fintan.halpenny@gmail.com>*
* `a4e66d14` **radicle: Allow all references to be included in sigrefs** *<mail@defelo.de>*
* `67dee655` **Release 1.6.0 CHANGELOG** *<fintan.halpenny@gmail.com>*
* `6d1abd28` **node: downgrade `error!` logs** *<fintan.halpenny@gmail.com>*
* `b020543c` **node: downgrade `warn!` logs** *<fintan.halpenny@gmail.com>*
* `ee1f5542` **protocol: downgrade `error!` logs** *<fintan.halpenny@gmail.com>*
* `eeadffa6` **node: update comment** *<fintan.halpenny@gmail.com>*
* `958422a7` **node/routing: remove error scenario from Database::prune** *<fintan.halpenny@gmail.com>*
* `95b3d109` **protocol: downgrade `warn!` logs** *<fintan.halpenny@gmail.com>*
* `9236277a` **fetch: remove `target: "fetch"`** *<fintan.halpenny@gmail.com>*
* `e3cb36d9` **fetch: clean up logging** *<fintan.halpenny@gmail.com>*
* `d860ec15` **cli: Remove dead `fn parse_remote`** *<adrian.duke@gmail.com>*
* `53cb8da8` **clippy: Deny and fix `must_use_candidate`** *<adrian.duke@gmail.com>*
* `2df32c00` **clippy: Deny `fn_params_excessive_bools`** *<adrian.duke@gmail.com>*
* `4c1b7fcd` **clippy: Deny and fix `index_slicing`** *<adrian.duke@gmail.com>*
* `0855af00` **clippy: Deny and fix `unneeded_field_pattern`** *<adrian.duke@gmail.com>*
* `9cc2c869` **clippy: Deny and fix `wildcard_enum_match_arm`** *<adrian.duke@gmail.com>*
* `001aba0d` **clippy: Deny and fix `fallible_impl_from`** *<adrian.duke@gmail.com>*
* `02318f19` **radicle: Re-export `radicle_core::RepoId`** *<fintan.halpenny@gmail.com>*
* `73827f53` **radicle: Re-export `radicle_core::NodeId`** *<fintan.halpenny@gmail.com>*
* `7c016f92` **core: Introduce NodeId** *<fintan.halpenny@gmail.com>*
* `d5fea632` **core: Introduce RepoId** *<fintan.halpenny@gmail.com>*
* `af3f0762` **chore: Update thiserror from 1 to 2** *<lorenz.leutgeb@radicle.xyz>*
* `d98033a1` **localtime: localise the localtime dependency** *<fintan.halpenny@gmail.com>*
* `3168107d` **fetch: surface underlying I/O error** *<fintan.halpenny@gmail.com>*
* `75b665ff` **node/wire: manage logs for error establishing connection** *<fintan.halpenny@gmail.com>*
* `47dc2c56` **protocol/service: defensive storage.contains check** *<fintan.halpenny@gmail.com>*
* `a46f8eb1` **node: use `outbound.get` over `outbound.get_mut`** *<fintan.halpenny@gmail.com>*
* `b8a6e1a5` **radicle/cob/stream: skip commits that do not have a manifest** *<fintan.halpenny@gmail.com>*
* `cf023f75` **cob: allow hyphens in `TypeName`** *<mail@defelo.de>*
* `352c29c2` **cargo(deny): allow Zlib** *<fintan.halpenny@gmail.com>*
* `a66d44eb` **workspace: update git-ref-format-core and radicle-surf** *<fintan.halpenny@gmail.com>*

## Checksums

```
e6de41ba2b2efd07b9ab008717d720184f8385c3bb93ad5c4a37f257179ecfed  radicle-1.7.0-x86_64-apple-darwin.tar.xz
0dd4d185bd6a1e5588ec879471678c482b0cc27d92cb2cc3b22982e63e920049  radicle-1.7.0-aarch64-unknown-linux-musl.tar.xz
dd9b734dc7b7b7132e7a27e5a53e268276870bbebd195ff6c0e1273ec2984dea  radicle-1.7.0-aarch64-apple-darwin.tar.xz
e23ad2f616d9730db5ae4eb730baad1373172e2dcaec1fef2c6b199dba514378  radicle-1.7.0-x86_64-unknown-linux-musl.tar.xz
```