# sluuz (`slu`)
> **Canonical:** [gitlab.com/safteinzz/sluuz](https://gitlab.com/safteinzz/sluuz) · **Mirror:** [github.com/safteinzz/sluuz](https://github.com/safteinzz/sluuz)
git, but it sleuths - a git superset with cross-repo search, secret scanning, and multi-repo management
## Install
```bash
cargo install sluuz
slu self check # is a newer release out?
slu self update # install the latest
```
No cargo yet? Rust installs the same way on every distro: [rustup.rs](https://rustup.rs).
## It is still git
Anything git understands is forwarded verbatim, with your editor, pager,
prompts, colors and exit codes intact:
```bash
slu commit -m "fix"
slu push
slu rebase -i HEAD~3
```
Then come the parts it does not. Each one below is an interactive tool and the
plain command that prints the same answer, for scripts and pipes.
## Every repo at once, and a way into them

Legend: `✚` uncommitted · `↑` unpushed commits · `↓` unpulled commits
```bash
slu irepos # every repo under here, with a way in; `s` syncs them all, `S` also pulls
slu irepos ~/projects # or under somewhere else
slu repos # the same list, printed
slu repos --dirty # only the ones needing attention
```

The same app opens at the branches, tags, commits or stashes of the repo you
are in with `slu ibranch`, `slu itag`, `slu ilog` and `slu istash`.
## Find a leaked string in every repo's history

```bash
slu iscan # type the terms, browse the hits
slu search -r "1337-let-me-in" # one string, every repo, printed
slu scan # the usual terms, printed
slu scan -t "AKIA,BEGIN RSA PRIVATE KEY"
```

`notifications-worker` is the case a file listing cannot find: `.env` was
untracked afterwards, so the secret survives only in history, and the `origin/`
refs say it survives on the server too.
## Read history in a real diff view

```bash
slu ilog # this branch
slu ilog --all -n 500 # every branch, more history
slu ilog src/main.rs # only commits touching that path
slu trace [-a] [-g] [-n N] # the aligned log, printed; every branch, with a graph
```


Highlighted in pure Rust, so no external diff tool is needed, though `Enter`
hands the file to yours if you want it.
## Stage and review in one place

Legend: left column staged (green) · right column unstaged (red) · `MM` both · `??` untracked
```bash
slu istatus # the two columns, with the diffs
slu status -sb # real git, passed straight through
```

`git status` you can act on, in git's own two-column code: `s` stages, `u`
unstages, and `S` and `U` do it to every file the list shows. `c` commits
what is staged, and `d` throws a file's changes away once you type its name.
## See what a stash holds

```bash
slu istash # every stash, its files and their diffs
slu stash list # real git, passed straight through
```

No more `git stash show -p stash@{2}` to find out what you parked. `a` applies,
`p` pops and `d` drops, asking for the stash's name first, since its changes are
kept nowhere else.
## Know what you have not pushed, and delete what is finished

Legend: `↑N` ahead of upstream · `no remote` never pushed · `⚑ gone` upstream was deleted · `synced` in step
```bash
slu ibranch [-r|-g] # push state of your branches; `d` deletes, `s` syncs, `S` also pulls
# -r opens on the remote's, -g on the finished ones (upstream gone)
slu tidy [path] [-a] # finished branches across every repo, with a delete command to paste
slu tidy -p # the same, after dropping remote branches that are gone
```

"Finished" means **upstream gone**, not "merged", so a branch still alive on the
remote is never suggested, and one holding work the remote does not have is
listed apart for you to look at.
## Know which tags the remote has

Legend: `↑` not pushed · `⚑` the remote's tag is not the same as yours · `↓` only the remote has it
```bash
slu itag # every tag against the remote, and what went into each
slu tag -n # real git, passed straight through
```

git keeps no record of a remote's tags, so `slu itag` asks the remote once the
list is up and never stops for a password. `t` adds one fetch rule so git keeps
a copy of them, and the marks then show at once.
## See where every remote stands

Legend: `↑N` commits that remote lacks · `↓N` commits only it has · `·` no local branch tracks it
```bash
slu iremote # every remote against this branch; `p` pushes, `s` syncs, `S` also pulls
slu branch -vv # real git, passed straight through
```

`p` never forces and sets an upstream only on a branch that has none, so pushing
a fork's work to `upstream` never changes where it pulls from.
## Commands
```bash
slu sync [path] [--pull] # fetch and prune every repo, optionally fast-forward
slu each <git args> # run any git command in every repo, in parallel
```
Multi-repo commands take a `path` (default `.`) and `-d N` (default 3),
`slu <command> --help` has every flag, and `?` in any screen lists every key.
Every interactive tool has a plain command that prints the same answer for
scripts and pipes, and anything passed through keeps git's own output and exit
code.
## Tab completion
Completion reuses git's own, so `slu branch v<Tab>` completes a real branch name
and every git subcommand, alias and flag behaves exactly like `git`.
```bash
slu completions bash --add # writes the loader into ~/.bashrc
slu completions zsh --add # ~/.zshrc
slu completions fish --add # ~/.config/fish/config.fish
```
Restart your shell afterwards; without `--add` it just prints the script. Works
in Git Bash and WSL too.
## What it edits
```
.git/config one fetch rule for the remote's tags, when you press t in slu itag
refs/remote-tags/ git's copy of the remote's tags, kept apart from branches
```
## Notes
- `scan` terms are case-insensitive and default to `password,secret,token,api_key,passwd,credentials`, and being pickaxe-based they also read binary and encrypted blobs.
- Git marks a branch gone only once its remote-tracking ref is pruned, so on a repo that never prunes `tidy` can miss branches and says so; `tidy -p` or `s` in `ibranch` prunes first, and `git config --global fetch.prune true` fixes it for good.
- A stash's diff is against the commit it was made on, as `git stash show -p` prints it, and untracked files stashed with `-u` are not listed.
## Compatibility
Linux, macOS and Windows. Everything is passed through to your own `git`, so
anywhere git runs, `slu` runs.
## License
AGPL-3.0-only