Library / SDK
sparrowwallet/sparrow avatar
sparrowwallet/sparrow

Sparrow: what its Java build, network flags and directory rules actually do

Desktop Bitcoin Wallet focused on security and privacy. Free and open source.

2,167 stars344 forksJavaApache-2.0

At a glance

What is it?
Sparrow is a desktop Bitcoin wallet written in Java, built around PSBT and most hardware signers. Its Gradle build, network precedence and per-category XDG rules are tight enough to audit line by line.
Who is it for?
Sparrow suits people who sign with hardware devices and want a Java codebase they can read and rebuild, not people who want a finished installer with no build step. Its network precedence, per-category XDG move and reproducible build are documented tightly enough to check before trusting either.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

PSBT and hardware signers shape a Java desktop wallet

Sparrow is a desktop Bitcoin wallet whose repository is written in Java and organised as a Gradle project: the root carries build.gradle, settings.gradle, gradlew, gradlew.bat and a .sdkmanrc file, with application sources under src/. The wallet sits on standards such as PSBT and supports most hardware wallets, which moves signing off the desktop and onto the device itself. For anyone holding coins on a signer and wanting to assemble, inspect and sign transactions on a laptop, that arrangement is the reason to pick this project.

The emphasis on transparency runs through the build as well. Source, build scripts and a SECURITY.md file at the root are readable, and the application can be rebuilt locally instead of taken on trust. For a tool that grants spend permissions, being able to repeat the build is a practical property rather than a marketing line.

Cloning recursively and installing Java 25 first

Building starts before any code is compiled. Sparrow requires Java 25 or higher, and the published binaries are produced with Eclipse Temurin 25.0.2+10, so matching that version removes one source of difference between your machine and the one that built them. If you use SDKMAN, a single command picks up the version pinned in the repository:

bash
sdk env install

Two clone commands are documented, one over SSH and one over HTTPS, and both are recursive:

bash
git clone --recursive [email protected]:sparrowwallet/sparrow.git
git clone --recursive https://github.com/sparrowwallet/sparrow.git

The recursive part is not decoration, because the root carries a .gitmodules file. On Debian and Ubuntu three packages are named before you build, and the list is worth reading closely because it installs rpm on a distribution that packages with deb:

bash
sudo apt install -y rpm fakeroot binutils

Those three packages appear immediately before the packaging step rather than the run step, and no reason is given for the split.

Three gradle paths for installers and one missing piece

The application is packaged with one Gradle task:

bash
./gradlew jpackage

That path builds installers through jpackage, and the notes beside it explain how to skip them on distributions that have neither deb nor rpm packaging tools, naming Arch as the case:

bash
./gradlew jpackage -PskipInstallers=true

Skipping the installers gives you the application and no packaging. The Windows installer is a separate problem: it needs WiX installed, and the project links the wixtoolset page instead of pinning a version of it. Keeping an existing tree current takes one more command, again recursive:

bash
git pull --recurse-submodules

The root also holds repackage.sh next to sparrow and sparrow.bat, so the project ships its own run scripts rather than handing every task to Gradle. What none of these instructions offers is a way back: no rollback command is given, and no commit or tag is named as a known-good state to return to.

Four option groups decide log level and network

Once built, the launcher runs from inside the project directory, and Java 25 or higher must be installed for that run exactly as for the build:

bash
./sparrow

The help output is the only place where the accepted network names are enumerated, in four option groups:

bash
./sparrow -h

Usage: sparrow [options]
  Options:
    --dir, -d
      Path to Sparrow home folder
    --help, -h
      Show usage
    --level, -l
      Set log level
      Possible Values: [ERROR, WARN, INFO, DEBUG, TRACE]
    --network, -n
      Network to use
      Possible Values: [mainnet, testnet, regtest, signet, testnet4]

Five log levels, five network values, nothing else in the list. Two options carry single letter short forms, and the one that changes where your data lives is the home folder option rather than the network one.

Testnet means testnet3 until testnet4 is named

Network selection has a documented order: the command line first, then an environment variable, then a file. The variable form is short:

bash
export SPARROW_NETWORK=testnet

The last fallback is a file called network-testnet dropped into the Sparrow home folder. Here is what a quick reading misses. The help output offers five network values, and one of them is testnet3 carried under the older name testnet, while testnet4 sits beside it as a value of its own. The marker file is documented only for testnet, so the file name a reader would infer for the other four networks appears nowhere. Each network then keeps its config, its wallets and its log in subfolders of the home folder, which makes switching between mainnet and a test chain a matter of which folder is in use.

A second constraint arrives with Electrum. When Sparrow is pointed at an Electrum server while on testnet, that server has to run on testnet configuration as well. Only that requirement is written down, and what happens when the two ends disagree is not documented.

XDG directories move one category at a time

Past the network question, the home folder itself has rules. The default location is ~/.sparrow on macOS and Linux and %APPDATA%/Sparrow on Windows, holding the config file, the log and the wallets.

On macOS and Linux an XDG Base Directory layout is available and described as opt in, which is the part worth pausing on. Each of the 4 categories resolves independently: if the directory for that category already exists, Sparrow uses it, otherwise it carries on with the home folder above. Config points at $XDG_CONFIG_HOME/sparrow, defaulting to ~/.config/sparrow, and holds the config file plus the network-* markers. Data points at $XDG_DATA_HOME/sparrow, defaulting to ~/.local/share/sparrow, and holds wallets, certs and lark. State points at $XDG_STATE_HOME/sparrow, defaulting to ~/.local/state/sparrow, and holds sparrow.log, tor/work and lock files. Cache points at $XDG_CACHE_HOME/sparrow, defaulting to ~/.cache/sparrow, and holds tor/cache.

So adopting the layout is a manual act repeated once per category: create the directory you want to move and that single category moves. Naming --dir instead disables XDG resolution altogether and puts every file in the folder you give it, which is the cleaner choice for a test run or a wallet you intend to discard.

Reproducible builds stop before the installer

The build can be audited in a way most desktop wallets are not. Sparrow states that the release binaries are reproducible from v1.5.0 onwards, with codesigning and installer packaging deliberately outside that promise, and the method is written up in docs/reproducible.md.

The published packages carry a signature, and the key is named in full so the comparison does not depend on a short id:

Fingerprint: D4D0D3202FC06849A257B38DE94618334C674B40, with the 64-bit half written as E946 1833 4C67 4B40 under craigraw's key on keybase.io.

Where the guarantee stops matters as much as where it begins. Codesigning and installer packaging sit outside the reproducible range, so a byte comparison covers the application and not the signed package a user downloads, and the instructions for checking the signature step by step are not given. Builders are asked to upload build videos to bitcoinbinary.org and told to check that site for someone who has already verified a given binary, which makes third-party verification a community activity rather than a documented procedure.

Signed binaries against a source run and the gaps left

There are two ways to get Sparrow and they trade off differently. A source user runs ./sparrow from the project directory with Java 25 installed, skips installers and codesigning entirely, and keeps the tree current with a recursive pull. A binary user takes a signed package, builds nothing, gives up the ability to read what is running, and gains the signature plus a reproducibility claim that holds only up to packaging.

This is not an abandoned project: the repository is not marked as archived and the last push was on 2026-09-28. The upgrade cost for a source user is therefore a pull and a rebuild, and no rollback command is given for a tree that stops working. The recursive flags point at content the tree does not itself carry: .gitmodules sits at the root beside directories named drongo and lark, and nothing in the documentation says which submodules the clone fetches or what they hold. Anyone running real funds through this wallet should check the key fingerprint against the key page first, then decide whether the source tree is needed at all.

Editorial conclusion

Sparrow suits people who sign with hardware devices and want a Java codebase they can read and rebuild, not people who want a finished installer with no build step. Its network precedence, per-category XDG move and reproducible build are documented tightly enough to check before trusting either. Before adopting, compare the GPG fingerprint D4D0D3202FC06849A257B38DE94618334C674B40 against the key page, build with Temurin 25.0.2+10, and confirm that your recursive clone pulled the submodules the Gradle build expects.

Frequently asked questions

How do I run Sparrow on testnet instead of mainnet?

Pass --network testnet, set SPARROW_NETWORK=testnet in the environment, or create a file named network-testnet in the Sparrow home folder. The testnet value currently points at testnet3, and testnet4 is a separate value of its own.

What do I need before I can build Sparrow from source?

Java 25 or higher, a recursive clone of the repository, and on Debian or Ubuntu the packages rpm, fakeroot and binutils. The application is produced by ./gradlew jpackage, and the Windows installer also needs WiX installed.

Where does Sparrow keep my wallets, config and log files?

In ~/.sparrow on macOS and Linux and %APPDATA%/Sparrow on Windows, unless you point it somewhere else with --dir. Each network keeps its own subfolders, and the log file is sparrow.log inside the configuration directory.

Can I check that a Sparrow binary matches the source code?

Sparrow states that binaries are reproducible from v1.5.0 onwards, before codesigning and installer packaging, with the method in docs/reproducible.md. Published binaries are signed with craigraw's GPG key, fingerprint D4D0D3202FC06849A257B38DE94618334C674B40.

What does the --dir option do to the XDG directories?

It disables XDG resolution entirely and stores every file in the folder you name. Without it, each XDG category is used only when that directory already exists, so categories move one at a time.

Official sources

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. sparrowwallet/sparrow on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/sparrowwallet-sparrow.svg)](https://hysenlabs.com/projects/sparrowwallet-sparrow)

Was this useful?