Plug in a USB. Get an offline AI coding agent on any laptop. One stick. Five targets — Windows, macOS (Apple Silicon + Intel), Linux (x64 + ARM64). Zero install on the host.
npx code-stick installYou want an AI coding agent that works on:
- Airgapped or restricted machines — banks, defense, hospitals, lab VMs.
- Shared / borrowed laptops — internships, school computers, client sites.
- Spotty wifi — flights, trains, cafes, conferences.
- Privacy-sensitive code — closed-source clients, NDAs, personal projects.
Cloud agents won't work. Installing Ollama + a 5 GB model on every machine you touch won't either. code-stick is the in-between: install once on a USB, then run the agent from the stick on whatever laptop is in front of you. Host stays clean.
Under the hood it's opencode (terminal coding agent) talking to Ollama (local model runner), both pre-built for every target, both serving from the USB on 127.0.0.1:11434. Quit the agent, the Ollama process dies, the host has no residue.
v0.1.1 — early release. What works today:
- Full install flow on Windows, macOS, Linux (x64 + ARM64) — tested manually per target.
- Docker-based Linux smoke test in CI (
npm run smoke:docker). - Vitest unit suite for launcher rendering, lock files, manifest, MAX_PATH preflight.
- Bug reports auto-write a redacted crash report to
%TEMP%; manual upload only. - No telemetry. No background HTTP. See
docs/SECURITY.md.
Rough edges:
- macOS binaries are not yet notarized — first-launch Gatekeeper dialog, workaround in Troubleshooting.
- Windows long-path installs need either a short USB mount or
LongPathsEnabled— the installer detects and bails clearly. - No Windows / macOS CI runners yet — those targets rely on manual smokes.
File an issue or open a PR if you hit anything: github.com/MuhammadUsmanGM/code-stick/issues.
- Auto-detects your USB drive (or takes
--target <path>). - Lets you pick a coding model.
- Asks Fast vs Direct install mode (see below).
- Downloads Ollama + opencode binaries for all 5 targets onto the stick.
- Pulls the model into a USB-local Ollama store (
<USB>/data) — host temp is auto-cleaned. - Writes
start-windows.bat,start-mac.command,start-linux.shat the USB root. - Cleans up installer archives and temp dirs.
Press Esc at any prompt to step back.
| Mode | What it does | Needs | Best when |
|---|---|---|---|
| Fast | Pull model into host temp, then copy blobs to USB. | ~2× model size of free space in %TEMP%//tmp (auto-cleaned) |
Slow USB sticks — usually much faster |
| Direct | Pull model straight onto the USB. | Nothing extra on host | Tiny host disk; fast USB 3 stick |
If the host and USB resolve to the same physical device, Fast is auto-skipped (no perf gain, doubles disk use).
Plug the stick into any supported machine, double-click the launcher for that OS. opencode runs in the terminal talking to a USB-local Ollama on 127.0.0.1:11434. Quitting opencode kills the Ollama process. Nothing is left behind on the host.
Pick one at install time. Add more later with code-stick add-model.
| Model | Ollama tag | Size | Best for |
|---|---|---|---|
| Qwen2.5-Coder 7B ⭐ | qwen2.5-coder:7b |
~4.7 GB | All-rounder for coding (recommended) |
| DeepSeek-Coder 6.7B | deepseek-coder:6.7b |
~3.8 GB | Debugging, 80+ languages |
| CodeGemma 7B | codegemma:7b |
~5.0 GB | Fill-in-middle, code completion |
| Phi-3 Mini 3.8B | phi3:mini |
~2.2 GB | Lightweight, low-spec hardware |
| Command | Description |
|---|---|
code-stick install |
Set up code-stick on a USB |
code-stick start |
Start opencode + Ollama from a USB |
code-stick status |
Show what's installed |
code-stick doctor |
Live audit (port + Ollama + opencode + model store) |
code-stick update |
Refresh launchers + opencode config |
code-stick upgrade-engine |
Re-download Ollama + opencode without nuking the model store |
code-stick add-model [id] |
Pull another model onto the stick |
code-stick remove-model [id] |
Remove a model from the stick |
code-stick add-targets [list] |
Add OS targets to a stick installed with --targets (restore portability) |
code-stick uninstall |
Wipe code-stick from the stick (binaries, models, config, launchers) |
code-stick install --target E:\ # skip USB picker
code-stick install --model phi3-mini # non-interactive model pick
code-stick install --no-cleanup # keep archives + temp for debugging
code-stick install --targets host # only stage binaries for this OS (saves ~3-4 GB, breaks portability)
code-stick install --targets mac,linux # multi-OS subset (still portable across listed ones)
code-stick add-targets all # restore full portability later
code-stick add-model qwen25-coder-7b --set-default
code-stick remove-model phi3-mini
code-stick uninstall --target E:\ --yesAvailable model IDs: qwen25-coder-7b, deepseek-coder-6_7b, codegemma-7b, phi3-mini.
The default is fully portable. code-stick install with no --targets flag stages binaries for all 5 OS/arch combinations so the same stick boots anywhere. That's the whole point of the product.
--targets is a power-user escape hatch for one specific use case: "I only want this on my own machine — I'll never plug this stick into another OS." It saves ~3–4 GB of disk and ~5 minutes of download. In exchange, the stick will only boot on the OSes you list.
Accepted tokens (comma-separated):
| Token | Stages |
|---|---|
all (default) |
all 5 targets — fully portable |
host |
just the OS+arch you're installing from |
windows / mac / linux |
every arch in that OS family |
windows-x64, darwin-arm64, darwin-x64, linux-x64, linux-arm64 |
one specific target |
Any value other than all prints a loud warning and asks for confirmation (unless --yes is set). The chosen subset is persisted in code-stick.json, so later you can fill in missing targets without wiping the model store:
code-stick add-targets darwin-arm64,darwin-x64 # add macOS later
code-stick add-targets all # restore full portabilitycode-stick upgrade-engine will only refresh the targets actually present on the stick — it never silently grows the set.
- USB with 8+ GB free (more for larger models)
- Format exFAT or NTFS — FAT32's 4 GB file limit blocks Qwen and CodeGemma blobs (the installer detects this and bails with a clear message)
- Node 20+ on the install machine. Target machines need nothing.
drivelist has native bindings. Without Visual Studio Build Tools the prebuild-install step can fail. Two options:
- Install Visual Studio Build Tools 2022 with the Desktop development with C++ workload, then retry.
- Skip auto-detection entirely:
code-stick install --target E:\does not needdrivelist. The CLI will warn and fall back to manual path entry on its own if drivelist failed to load.
drivelist is declared as an optional dependency, so a build failure should not abort npm install — it just disables auto-detection.
Gatekeeper quarantines unsigned binaries that arrived via "external media." We are not yet notarized (notarization needs an Apple Developer Program account — on the roadmap). Until then, the supported workflow on macOS Sonoma+ is:
- Right-click
start-mac.command→ Open → Open. This adds a per-binary exception so future double-clicks work. - If the launcher exits with a "translocated to a read-only sandbox" message, that's macOS App Translocation copying the launcher to a randomized scratch mount before run. The right-click-Open ritual above also clears it.
- As a last resort:
xattr -dr com.apple.quarantine /Volumes/<your-usb>
Neither launchers nor code-stick install are affected — only the per-machine first-launch dialog. code-stick doctor runs the same probes from a CLI context where Gatekeeper does not apply.
FAT32 and exFAT cannot store the POSIX +x bit, so binaries copied to such a stick lose executability. The installer warns about this at install time. Workaround: invoke launchers via bash:
bash start-linux.sh
bash start-mac.commandFor long-term use, format the stick as NTFS (Windows + Linux) or APFS/HFS+ (macOS-only) — or exFAT if you accept the bash workaround for cross-OS use.
Windows caps individual paths at 260 chars by default. Pre-staged opencode
dependencies live deep under <USB>\cache\opencode\node_modules\@ai-sdk\ openai-compatible\dist\internal\..., and a USB mounted at a long path
(e.g. C:\Users\Long Name\Downloads\code-stick-stage\) overflows the limit
mid-install. The installer detects this up-front and refuses to start.
Three fixes, in order of preference:
- Mount the USB at a short path. Assign a single drive letter via Disk
Management, or
subst X: <current-path>in Command Prompt, then re-run with--target X:\. - Enable Win10 1607+ long paths system-wide (PowerShell as Admin):
Reboot, then re-run the installer.
New-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem ` -Name LongPathsEnabled -Value 1 -PropertyType DWORD -Force
- Re-run from a shorter working directory. The installer's host-side
stage dir lives under
%TEMP%; if your user profile path is itself long, pointTMP/TEMPatC:\tand retry.
Stop your host's Ollama process first. The launchers refuse to start a second instance on the same port.
CODE_STICK_DEBUG=1 code-stick install --target E:\ --no-cleanup--no-cleanup keeps .code-stick-tmp/ and the downloaded archives so you can inspect them.
When code-stick crashes it writes a redacted report to your OS temp dir
(e.g. %TEMP%\code-stick\bug-report-install-2026-...md). The path is printed
to your terminal. The report has your home dir, hostname, USB path, and
common token shapes scrubbed before it is written. Open it, eyeball it, then
attach it to a new issue at
github.com/MuhammadUsmanGM/code-stick/issues.
We do not ship telemetry. No background HTTP calls, no auto-reporting.
Bug submission is fully manual and entirely under your control. See
docs/SECURITY.md for the full trust model.
<USB>/
├── code-stick.json manifest (v2: multi-model)
├── start-windows.bat launcher → engine/windows-x64/ollama.exe + opencode
├── start-mac.command launcher → engine/darwin-{arm64,x64}/...
├── start-linux.sh launcher → engine/linux-{x64,arm64}/...
├── engine/<target>/ ollama binary per target
├── opencode/<target>/ opencode binary per target
├── data/ OLLAMA_MODELS — model blobs (OS-agnostic)
└── config/opencode/ opencode.json (XDG_CONFIG_HOME / APPDATA redirect)
Launchers spawn ollama serve from the USB with OLLAMA_MODELS=<USB>/data and OLLAMA_HOST=127.0.0.1:11434, redirect opencode's config dir at <USB>/config, then run opencode in the foreground. On exit, only the Ollama process they spawned is killed (by PID — never taskkill /IM ollama.exe).
npm install
npm run typecheck # tsc --noEmit
npm test # vitest run (unit + launcher snapshot tests)
npm run build # tsup → dist/cli.js
npm run smoke:docker # full end-to-end install + launch in Linux Docker (needs network)scripts/smoke.mjs is a Linux-x64 end-to-end smoke: build → install with
phi3-mini (smallest model) → boot Ollama → probe /api/version → smoke
opencode --version. macOS / Windows smokes need licensed CI runners and
are not part of the default smoke:docker flow — run the launcher manually
on each target instead.
MIT — Muhammad Usman (github.com/MuhammadUsmanGM)
