Sprout · version control and hostingIn developmentOpen source

Undo Anything.
Lose Nothing.

Sprout is version control and hosting for everyone who makes things: developers first, and writers, designers, musicians and researchers too. It reads and writes Git, so GitHub, your editor and your scripts keep working, and adds plain words, undo for anything, big files that just work and a phone app for reviews. Every demo below runs in your browser; the screens are from Sprout itself, and every number says how it was measured.

  • Windows
  • Linux
  • macOS
  • iOS
  • Android
  • Web
All planned. Downloads open through the waitlist.
01 · Undo anything

Every action on a timeline. Every one undoable.

Your work is always saved: the working copy is itself a save, so there's no staging area and no stash. Every action, a save, a bring-in, even a share, goes in an operation log, and undo takes back the last one, on Sprout hosting too. Plain words by default; a switch shows Git's. Drag along the timeline, then undo.

src/rank.rs
    Timeline

      7 mssp status with nothing changed, the watcher on
      13–31 mssp status right after an edit, the watcher on
      54 mssp save, the watcher on (85–93 ms without it)
      77–79 mssp undo of a save

      Measured 26 October 2026 on one machine (Linux, 4 cores, release build of sp) on a copy of Avlory's own repository, 11,672 files. The watcher is Sprout's own file watcher, which the app keeps on for each open project. For scale, git status took 0.09 s on the same copy.

      Sprout hosting in the browser, the History of Ines / fernwood-app: the main line with two shared saves, Add the picker and Start Fernwood, and the selected save's change to src/picker.rs, one function changed, beside the project's tabs for files, reviews, issues, checks, deploys, releases, packages, big files, lines of work and everything done.
      History on Sprout hosting, in the browser, from Sprout's screen tests (an example project).
      02 · Save part of your work

      Save just the lines you meant to.

      Pick whole files, single changes or single lines, and save only those; everything else stays as unsaved work, still kept. As in the app: Space picks the line you're on, A picks the whole file, S saves what's picked. Git's own hooks see exactly the picked changes.

      src/search.rs

        Arrow keys move, Space picks, A picks the whole file, S saves. Or click a line.

        History

          Split a save

          First build

          A save that isn't shared yet splits in two, the files you name first. Undoable, like everything.

          Absorb fixes

          First build

          Each unsaved change moves into the save, not shared yet, that last changed those lines.

          Move a save

          First build

          Put a save elsewhere in its stack, or drag it in the app; the saves on top follow.

          Signed like Git

          First build

          Saves are signed with Git's own signing settings, SSH, GPG or X.509. If signing fails, nothing is saved unsigned.

          Sprout's desktop app in Loam: Changes with src/lib.rs partly picked and src/paths/recent.rs picked, and the diff reader beside it with 1 of 4 changed lines picked, Pick the whole file, Pick this change and Save picked, above a message box and Save picked: 2 files.
          Saving part of your work, from Sprout's screen tests (an example project).
          03 · Try an idea

          Try an idea. Conflicts never stop you.

          Conflicts in history are builtCombining by structure is decided, not built

          Try an idea apart from the main line, then bring it in. Two changes to different functions in one file will be combined by the code's structure and marked “please check” once each language passes its own test suite; until then Sprout combines them line by line, as Git does. Two changes to the same code make a conflict that's saved in history: nobody's work is lost, you keep working, and it can't be shared until a person settles it. Sprout never keeps two versions of code side by side.

          The main line and an idea, drawn as growth.
          The two changes

          95 mssp save of 1 file in a 10,016-file project
          1.02 ssp switch to a line of work about 1,100 files apart (382 ms back)
          36 mssp history
          391 mssp blame of an 8,000-line file changed in 100 saves

          Measured 28 October 2026 on the 4-core Linux build machine with another build running, release sp, one process per command, on a generated repository of 10,016 files with 301 saves and a second branch; one run, so a figure can be off by a third. cargo test --release -p sprout-cli --test scale -- --ignored --nocapture sweep_10k

          Sprout's desktop app showing review number 1, Faster search: Kofi wants to bring faster-search into the main line, 2 saves. Ines's comment on an outdated line, Dana's comment that followed the code from src/picker.rs to src/search.rs with Kofi's reply, and a side panel saying Not ready yet with Approve, Ask for changes and Bring it in.
          Bringing an idea in through a review, from Sprout's screen tests (an example project).
          04 · GitHub in tandem

          GitHub keeps working. Both ways.

          A project on Sprout hosting stays in step with a GitHub repository both ways, through webhooks, with polling when they stop. A line changed on both sides is held as a conflict, never kept twice, with GitHub's version beside it. Force-pushes and deleted branches wait for a person. Everything that comes in can be undone, and the whole GitHub module can be switched off.

          ines/fernwood-app · mainIn step

          Sprout hosting

            GitHub

                Make something happen

                A simulation of the sync's rules, not a connection to GitHub.

                Sign in with a code

                First build

                Sprout shows a short code, you type it on github.com, and the key stays in the system keychain. No token pasting.

                Bring issues and pull requests

                First build

                GitHub's issues and pull requests can be imported once, and pull requests can be read, approved and merged from Sprout.

                GitHub Actions, if you want

                First build

                A project can also run its checks through GitHub Actions; their results show beside Sprout's, marked as from GitHub.

                Plain Git underneath

                First build

                Every save is an ordinary Git commit beside a normal .git, so other tools and plain git keep working.

                Not tried against the real GitHub yet

                • Every test of the GitHub module runs against a stand-in GitHub on the same machine, which speaks its REST calls, device sign-in, Git over HTTP and signed webhooks. No test reaches github.com.
                • Signing in to GitHub needs Sprout's OAuth app, which the owner registers once from the steps in the code.
                Sprout hosting in the browser, the files of Ines / fernwood-app, with badges for Public, Main line protected, Contributions by invitation and GitHub: waiting for its limit until 14:20, the README, a review called Faster search, the faster-search line of work 2 ahead and 0 behind, and Sprout hosting as home.
                A project on Sprout hosting waiting out GitHub's rate limit, from Sprout's screen tests (an example project).
                05 · Big files

                Big files for every kind of work.

                Songs, photos, footage, 3D and game assets go in Sprout's big-file store, cut into 1 MB chunks that versions share, fetched only when you need them, and resumed where a transfer stopped. GitHub and plain Git still see ordinary Git LFS files. Files that can't be merged can be locked. Changes show in each file's own way: pictures side by side, overlaid or swiped, recordings as waveforms with the changed stretches marked. Change part of a 500 MB recording, then share it.

                audio/final_mix.wav · 500 MBNot locked
                Try

                An illustration: each square is one 1 MB chunk.

                4.5 ssharing a 500 MB file, about 110 MB a second
                3.5 sfetching it again, about 140 MB a second
                5 MBsent for a second version with five changed megabytes
                505 MBheld on the server for both 500 MB versions

                Measured 23 October 2026 on one machine, release build, with the Sprout server on the same machine (127.0.0.1), so these are Sprout's own costs with no real network in between.

                Sprout's Get a copy dialog for fernwood/app with three choices for big projects, all ticked: Recent history only (the last 200 saves), Leave big files on the server (old versions of files over 1 MB), and Only the folders you work in, with a box for the folders to have on disk.
                Getting a copy of a big project, from Sprout's screen tests.
                06 · Checks and reviews

                Checks run first on your machine.

                sp share runs the project's checks on your computer first and always scans for secrets, then writes the result into what it shares as signed Sprout-Check lines, so the server reruns only what it must. Reviews, issues and one inbox are built in, on the desktop, in the browser and in the phone app. Share once with the tests passing, then make one fail.

                .sprout/checks.toml · sp share
                  This share

                  Runners you own

                  First build

                  A runner on your own machine runs each job in a container or a Linux sandbox, and signs every result with its own key.

                  Reviews that follow the code

                  First build

                  Comments on lines follow their code as new saves land; outdated ones are marked and kept. Bringing a review in can be undone.

                  One inbox

                  First build

                  Review requests, mentions and assignments in one place, with email through Avlory's own mail and no tracking.

                  The phone app

                  Not on a phone yet

                  Inbox, Reviews, Issues, Projects and You, with reviews opening conversation first. Built and tested at phone size; not yet run on an Android or iOS device.

                  Sprout's Checks page in the desktop app: run history with a failed share of faster-search (unit tests passed, lints failed, docs skipped because none of its paths changed), a passed bring-in on main and a cancelled run replaced by a newer push, beside the runners, settings for GitHub Actions and Avlory-hosted runners, and secrets.
                  The project's checks, from Sprout's screen tests (an example project).
                  Sprout's phone layout showing review 1, Faster search: Not ready yet with checks not run and not approved, the conversation tab first with Kofi's opening note, Ines's comment on an outdated line and Dana's comment that followed the code, and the bottom tabs Inbox, Reviews, Issues, Projects and You.
                  A review at phone size, from Sprout's screen tests.
                  07 · Commands

                  Plain words in the terminal. Git's beside them.

                  The command line is one program with two names: sprout, and sp for short. It has 53 commands, every error ends with what to do next, and --git-words (or a setting) says commit, branch and push instead of save, line of work and share. Below, real sessions recorded from sp play back in a terminal.

                  ines@laptop: ~/fernwoodRecorded

                    Recorded from a real sp build on 4 November 2026. Played back, not live.

                    Recording

                    Each recording ran in a fresh practice project whose shared copy is a Git repository on the same machine, so no network. Commands type out at a steady pace, because typing isn't recorded. Each line of output appears when sp printed it, at real speed, on the 4-core Linux build machine. Lines starting with # say what happened between commands.

                    Cheat sheet

                    • sp get owner/repoGet a copy (owner/repo means GitHub)
                    • sp statusWhat's changed, and what to do next
                    • sp save "what you did"Name this point. Your work is kept anyway
                    • sp undoUndo the last thing you did, whatever it was
                    • sp try idea-nameTry an idea apart from the main line
                    • sp switch mainBack to the main line, no stashing
                    • sp bring-inBring in others' changes, yours on top
                    • sp shareChecks, a secret scan, then share
                    • sp conflictsWho changed what, then sp settle <file>
                    • sp helpEvery command; --git-words for Git's words

                    The commands, grouped

                    CommandWhat it does, in sp help's wordsIn Git
                    Start
                    sp get <owner/repo | url | path> [folder]get a copy of a projectgit clone
                    sp get --recent[=N] --without-big-files[=SIZE] --only=a,bfor big projects: only the newest N saves (50), old versions of files over SIZE (1m) left out until needed, only these folders on diskgit clone --depth, --filter=blob:limit
                    sp init [folder]start Sprout here (an existing Git repository stays as it is)git init
                    sp statuswhat's changed since your last save, and what to do nextgit status
                    spon its own opens the Sprout app on this project (sp --terminal shows the status instead)None
                    Save and undo
                    sp save "what you did"name this point (your work is always kept anyway)git commit, with no staging step
                    sp undoundo the last thing you did, whatever it was (a share too, on the shared copy, if nobody has built on it yet)No one command (Jujutsu's jj undo)
                    sp undo --as-new-savetake your last share back with a new save on Sprout hosting (when someone has built on it), then bring it ingit revert, then git pull
                    sp revert <save>a new save that takes back what an earlier one changedgit revert
                    sp history [--actions]your saves, or every action you tookgit log
                    sp history <file|folder>the saves that changed it (a file followed through renames)git log --follow -- <path>
                    sp blame <file>who changed each line, in which save, and the save's messagegit blame
                    sp split <save> <file>... [-m "..."]split a save in two: these files first, the rest afterNone (Jujutsu's jj split)
                    sp absorb [save]move each change into the unshared save that last touched those lines (your unsaved work by default)None (Jujutsu's jj absorb)
                    sp move <save> --after|--before <save>put a save somewhere else in its stack (undoable)git rebase -i
                    sp bisect start [bad] [good]find the save that broke something by halving the historygit bisect
                    Share
                    sp sharechecks, a secret scan, then share (to Sprout hosting or GitHub)git push
                    sp share --skip-checks "why"emergencies only: no checks (the secret scan still runs); every save shared is marked for reviewersgit push
                    sp save|share --skip-hooks "why"emergencies only: don't run the project's Git hooks (pre-commit, commit-msg, pre-push); the saves say so--no-verify
                    sp bring-inbring in others' changes; conflicts are saved, never blockinggit pull --rebase
                    sp tag new <name> [save] -m "..."an annotated tag on a save (signed when Git signs tags)git tag -a
                    sp tag push [name]send tags to the shared copygit push origin <tag>
                    Lines of work and ideas
                    sp try <name>start trying an idea, apart from the main linegit switch -c
                    sp switch [name]move to another line of work (no stashing, ever)git switch, plus git stash
                    sp conflictsunsettled files, with who changed each sideNone
                    sp settle <file>mark a file settled after you've edited itgit add <file> after a merge
                    sp folder add <path> [line]another folder for this project, on its own line of workgit worktree add
                    GitHub
                    sp github setup [client-id]connect Sprout to GitHub once: the steps to register its app on GitHub, then the app's client ID saved, then sign inNone
                    sp github loginsign in to GitHub with a code you approve on github.com (the key is kept in your system keychain); Git then uses it toogh auth login
                    sp github statuswho you're signed in to GitHub as, and where Git uses itgh auth status
                    sp github git everywhere|project|offwhere Git uses your GitHub sign-in: your global Git config, each project Sprout opens (the default), or nowheregh auth setup-git
                    sp github on|offswitch the GitHub module on or off on this computer (off: no GitHub sign-in, owner/repo stops meaning GitHub)None
                    sp pr [list] | show <n> | comment <n> "..."GitHub pull requests for a project shared on GitHubgh pr list, view, comment
                    sp pr open [line] --title "..." [--draft]open one from a shared line of workgh pr create
                    sp pr approve|ask-changes <n> ["..."]review onegh pr review
                    sp pr merge <n> [--squash|--rebase]merge one on GitHub (then sp bring-in)gh pr merge
                    Checks
                    sp checksthe project's checks, and on Sprout hosting how they went on your last save (signed results, GitHub Actions' beside them)gh run list
                    sp checks run [name...] [--isolation x]run them here exactly as a runner does: a clean copy, sandboxed (best|container|sandbox|none); sp share won't run them againNone
                    sp checks logs <job> [--follow]a job's log on Sprout hosting, live with --followgh run view --log
                    sp checks rerun <job>, sp checks cancel <job>run one finished job again, or stop onegh run rerun, gh run cancel
                    sp checks import <workflow.yml> [--write]turn a GitHub Actions workflow into .sprout/checks.tomlNone

                    The middle column quotes sp help. The Git column is the nearest Git or GitHub CLI command; Sprout runs Git underneath, so every save is an ordinary Git commit.

                    Also in sp

                    • sp review Reviews on Sprout hosting
                    • sp issue Issues on Sprout hosting
                    • sp inbox What needs you
                    • sp watch How much a project tells you
                    • sp files Big files
                    • sp lock, unlock, locks Files that can't be merged
                    • sp release Releases
                    • sp package Packages
                    • sp only Only these folders on disk
                    • sp watcher Fast status on big projects
                    • sp oplog Every action, for scripts and Pulse
                    • sp ls, go, cd, open Short paths
                    • sp setup-shell, completions Shell setup and tab completion
                    • sp login, logout, whoami, projects Sprout hosting sign-in
                    • sp deploy Deploys
                    • sp tools Developer tools and PATH
                    • sp ignore What Sprout does with a path, and why
                    • sp credential Git's credential helper (for Git only)
                    • sp git Any Git command, as is
                    • sp version Sprout's version
                    53commands, one list kept in step with what sp handles by a test
                    12 mssp status, warm, in a 1,016-file project
                    46 mssp save of 1 changed file there
                    37 mssp undo of a 1,000-file save there

                    Commands: counted in the command line's list (crates/cli/src/commands.rs), which drives “did you mean”, tab completion and a test against the commands sp runs. Timings: measured 28 October 2026 on the 4-core Linux build machine with another build running, release sp, one process per command, on a generated repository of 1,016 files with 301 saves; one run, so a figure can be off by a third. cargo test --release -p sprout-cli --test scale -- --ignored --nocapture sweep_1k

                    A terminal running sp on a practice project: sp bring-in brings in Kofi's save and saves a conflict in README.md; sp conflicts names who changed each side; sp settle README.md settles it; sp share checks and shares one save to origin on main; sp undo takes the share back on origin too.
                    Real output from a build of sp on 3 November 2026, on a practice project, set in a terminal frame for this page.
                    Status

                    Where Sprout is today.

                    In development. The first build is in place: the sp command line, the desktop app (Linux first), Sprout hosting with the same app in the browser, and the phone layout. Sprout and Pulse ship first, together. Downloads open through the waitlist.

                    Tested

                    • On a Linux build machine with 4 cores.
                    • The Rust core's tests, scale sweeps from 1,000 to 250,000 files, and the app's widget, accessibility and screen tests in Loam, Daylight and high contrast.
                    • Hosting, checks and the GitHub sync against stand-ins on the same machine.

                    Not tested yet

                    • Windows and macOS builds.
                    • The phone app on Android and iOS devices.
                    • Syncing with the real GitHub.
                    • Sprout hosting on a real server; the test server waits for the owner's go-ahead.
                    • No feature moves up a tier

                      A saved project always opens and exports, even after a plan ends.

                    • Never locked out offline

                      History and differences are on your computer, so work goes on when a server is down.

                    • Leaving is easy

                      Every project is an ordinary Git repository underneath, with nothing to convert.

                    • Free to start

                      Plans and prices are announced at launch. All the promises

                    Waitlist

                    Try Sprout First.

                    Sprout's downloads open through the waitlist. We'll email you when it's ready on your platform.

                    Which apps?

                    It helps us decide what to finish first.0 / 500