A version switcher for Oracle SQLcl, in the spirit of nvm / pyenv / rbenv.
$ sqlv ls
* 25.3.2.317.1117
26.1.0.086.1709
$ sqlv 26.1
Now using SQLcl 26.1.0.086.1709
$ sql -V
SQLcl: Release 26.1.0.0 Production Build: 26.1.0.086.1709
No more hard-coding the SQLcl path in your shell rc. No more reinstalling brew casks every time you need a different build. One stable PATH entry, one symlink, one command.
The official SQLcl distribution channels (Homebrew Cask, Oracle's download page) only ever expose one version at a time. If you need to test against multiple SQLcl releases — for APEX migrations, regressions, or just because a customer is on an older build — you have to either juggle hand-rolled paths or reinstall every time you switch.
sqlv:
- Holds multiple SQLcl versions side-by-side under
~/sqlv/versions/ - Exposes a stable PATH entry (
~/sqlv/current/bin) that always points at "the active version" - Switches versions instantly by re-linking the
~/sqlv/currentsymlink — no shell reload, no PATH rewrite, no fork - Resolves friendly version queries (
25.3,26.1,latest) against an index it builds by crawling Oracle's archive pages, so you never need to know the full build identifier (25.3.2.317.1117) - Downloads the matching zip from Oracle, extracts it, and switches to it — all in one step
curl -fsSL https://raw.githubusercontent.com/United-Codes/sqlv/main/install.sh | bashThen open a new shell (or source ~/.zshrc) and you're done.
The installer will:
- Clone this repo into
~/sqlv - Make
~/sqlv/bin/sqlvexecutable - Append a 3-line loader to your
~/.zshrc(or~/.bashrc)
Override the destination by setting SQLV_HOME before running the installer.
If you'd rather not pipe a script into your shell:
git clone https://github.com/United-Codes/sqlv.git ~/sqlv
chmod +x ~/sqlv/bin/sqlv
cat >> ~/.zshrc <<'EOF'
# sqlv — Oracle SQLcl version switcher
[ -f "$HOME/sqlv/sqlv.sh" ] && . "$HOME/sqlv/sqlv.sh"
export PATH="$HOME/sqlv/bin:$HOME/sqlv/current/bin:$PATH"
EOF| Command | What it does |
|---|---|
sqlv / sqlv ls |
List installed versions (* marks the active one) |
sqlv current |
Print the active version |
sqlv <version> |
Switch to an installed version (prefix match — sqlv 25.3 matches the highest 25.3.x.x.x you have) |
sqlv which |
Print the resolved path to the active sql binary |
sqlv path [<version>] |
Print the install dir of the active or matched version |
sqlv install <version> |
Resolve, download, install, and switch. Accepts short labels (25.3.2), full labels (25.3.2.317.1117), or latest |
sqlv search [<query>] |
List versions in Oracle's index, filterable by prefix |
sqlv update |
Refresh the Oracle version index |
sqlv uninstall <version> |
Remove an installed version |
sqlv help |
Show inline help |
# What's available upstream?
$ sqlv search 25.3
25.3 -> 25.3.0.274.1210
25.3.1 -> 25.3.1.311.1257
25.3.2 -> 25.3.2.317.1117
# Install the latest 25.3.x — sqlv resolves the build code for you
$ sqlv install 25.3
Resolved 25.3 -> 25.3.2.317.1117
Downloading https://download.oracle.com/otn_software/java/sqldeveloper/sqlcl-25.3.2.317.1117.zip
...
Installed SQLcl 25.3.2.317.1117 at /Users/you/sqlv/versions/25.3.2.317.1117/sqlcl
Now using SQLcl 25.3.2.317.1117
# Install latest while you're at it
$ sqlv install latest
Resolved latest -> 26.1.0.086.1709
...
Now using SQLcl 26.1.0.086.1709
# Flip between them
$ sqlv 25.3
Now using SQLcl 25.3.2.317.1117~/sqlv/
├── sqlv.sh # function definitions, sourced from your rc
├── bin/
│ └── sqlv # standalone wrapper (so non-zsh contexts work)
├── versions/
│ ├── 25.3.2.317.1117/sqlcl/... # one full SQLcl install per version
│ └── 26.1.0.086.1709/sqlcl/...
├── current -> versions/26.1.0.086.1709/sqlcl
└── index.tsv # crawled Oracle index (gitignored)
Your shell adds ~/sqlv/bin (the sqlv wrapper) and ~/sqlv/current/bin (the active SQLcl) to PATH — once, at startup. Switching versions never touches PATH; it just relinks ~/sqlv/current. Subprocesses, new shells, even running sql from a different terminal all immediately see the new version.
The Oracle version index is built by walking the chain of archive pages on oracle.com/sqlcl/download/sqlcl-downloads-<ver>.html (each one links to the previous version). The result lives at ~/sqlv/index.tsv and auto-refreshes every 7 days.
All configuration is via environment variables. Defaults work for everyone.
| Variable | Default | Purpose |
|---|---|---|
SQLV_HOME |
$HOME/sqlv |
Where everything lives |
SQLV_INDEX_MAX_AGE_DAYS |
7 |
Auto-refresh threshold for the version index |
SQLV_DOWNLOAD_BASE |
https://download.oracle.com/otn_software/java/sqldeveloper |
CDN base for the .zip files |
SQLV_MAIN_PAGE |
https://www.oracle.com/database/sqldeveloper/technologies/sqlcl/download/ |
Crawl entrypoint |
SQLV_UA |
a recent Safari UA string | User-Agent for the crawl |
- A POSIX shell environment (
bash,curl,unzip,awk,find,sort,grep,sed,stat,date) — already present on macOS and on every mainstream Linux distro. - A JDK that SQLcl supports. SQLcl 25 needs Java 11+; SQLcl 26 needs Java 17+. Set
JAVA_HOMEaccordingly. - macOS or Linux. The script handles BSD/GNU
statdifferences. Windows is unsupported (but WSL works fine).
sqlv: cannot find ~/sqlv/sqlv.sh — the wrapper couldn't find the function file. Either you're running it from a non-default location, or the install didn't finish. Set SQLV_HOME to the right directory.
sqlv: crawl returned no versions (network problem?) — the Oracle download pages returned nothing. Usually a transient network issue or a UA block; retry with sqlv update. Override SQLV_UA if Oracle is fingerprinting you.
sqlv: archive layout unexpected — Oracle changed the zip's internal layout. Open an issue with the version you tried to install.
The sql command still points at the old version after switching — make sure ~/sqlv/current/bin comes early on your PATH and that no other entry (e.g. a stale brew cask) shadows it. sqlv which shows the resolved binary.
zsh: local path clobbers PATH — for the curious, this is a real footgun: $path is a zsh special array tied to $PATH. sqlv uses a different name internally to avoid it. If you ever extend the script, never declare local path in a function.
brew uninstall --cask sqlcl
sqlv install latestThe old /opt/homebrew/Caskroom/sqlcl/... path goes away; the new ~/sqlv/current/bin/sql is everything you need.
MIT.