Shelly is a native terminal IDE for Android that integrates an AI assistant directly alongside the terminal, eliminating the need to copy-paste between tools. It bundles real Linux utilities (bash, Node.js, Python, git, and others) and enables workflows where the AI can read terminal output and execute fixes with a single tap, creating a complete mobile development environment.
AI-powered chat-first terminal IDE for Android. Built entirely on a phone, by someone who can't write code.
README
See it run
AI reading a runtime error and suggesting the fix in real time
https://github.com/user-attachments/assets/113ec26e-d289-4a06-a6d8-ef48158e874c
No Termux. No root. No remote dev server. A real AI coding CLI — today, OpenAI Codex — invoking on Android, plus an API-backed AI pane that reads terminal output and produces a one-tap fix.
An autonomous agent, scheduled in plain language, that wakes itself to do the work
https://github.com/user-attachments/assets/ab272ae8-c741-4acb-b71d-2da151f50d75
Type @agent and a plain-language instruction. Shelly turns it into a scheduled on-device agent that fires on its own alarm — here it set itself for 16:16, woke up while the screen was off, collected sources with the user's own API key, and wrote a primary-source summary to the Obsidian vault. Observed end-to-end once on a Galaxy Z Fold6 (N=1); cross-OEM and deep-Doze behavior is not yet tested beyond this device — see Status.
Why Shelly?
Termux is a terminal. ChatGPT is an AI chat. Replit is a cloud workspace. Desktop AI coding CLIs are desktop-first.
Shelly is the workspace that connects those pieces on the Android device you already carry: local terminal work, app-owned native PTYs, Codex CLI, AI panes, browser/docs, previews, and background API agents.
The copy-paste problem
You're running an AI coding tool in a terminal — Codex, or any other AI CLI. It throws an error. You copy it. You switch to ChatGPT. You paste. You ask "what went wrong?" You read the answer. You copy the fix. You switch back. You paste. You run it.
Seven steps. Every single time.
This is a familiar workflow for developers using CLI-based AI tools. The terminal and the AI live in different worlds, and you are the copy-paste bridge between them.
Shelly puts the terminal and the AI side by side. The AI reads your terminal output automatically.
Say "fix the error on the right". Shelly reads the terminal output, explains the error, and generates an executable command. Tap [Run] and the fix lands directly in the Terminal pane.
No copy. No paste. No tab switching.
Three levels of value:
- Single pane: a native terminal that is faster, smarter, and more usable than Termux alone — with inline content blocks, autocomplete, syntax highlighting, and clickable errors.
- Split panes: terminal + AI side by side — the AI reads what the terminal shows and executes fixes with one tap. No copy-paste bridge needed.
- Full layout: sidebar + up to 4 live panes + agent bar — a mobile IDE. Browse docs in the browser pane, preview code or markdown on the right, use API-backed agents in the background, and keep your terminal front and center.
Important Android Notes
- APK is ~800 MB because Shelly bundles real tools, not shims. bash, Node.js, Python 3, git, curl, ripgrep, jq, tmux, vim, less, sqlite3, make, ssh — plus the OpenAI Codex CLI runtime — ship inside the APK. No Termux, no repository server, no package manager bootstrap. First launch extracts the binaries into app-private data.
- All files access is requested on first launch so
/sdcardworks the way a desktop terminal expects (cd /sdcard/Download, editing files there, etc.). Scoped Storage without this permission silently blocks writes. You can refuse — Shelly still works inside its own sandbox, but/sdcardpaths willPermission denied. - LD_PRELOAD + /system/bin/linker64 is how Shelly runs Linux-layout
binaries on Android bionic (SELinux blocks direct execve on
app-private ELFs). The wrapper rewrites
/bin/Xand/usr/bin/Xto/system/bin/Xand routes app-bundled ELFs throughlinker64. Source is inmodules/terminal-emulator/android/src/main/jni/exec-wrapper.c. - Not Termux-compatible by design. Shelly does not use Termux packages, Termux paths, or Termux's prefix assumptions. If you already have Termux installed, Shelly still bundles its own copies of everything. No conflict, but also no sharing.
Quick Start
Install
Download the current Android APK from GitHub Releases. The rolling android-latest release is the source of truth for the newest Shelly build, and the latest tagged vX.Y.Z release APK is cut from that same build — the exact versionCode, commit, and SHA-256 are live in android-latest/latest.json.
After the first install, Shelly can update itself from inside the app: open the cloud-download button in the top bar or Settings → Updates. Shelly reads the public android-latest/latest.json manifest, compares Android versionCode, enqueues the APK with Android DownloadManager under /sdcard/Download/shelly-update-<versionCode>/, verifies SHA-256, then opens Android's package installer. The system download keeps running if Shelly is backgrounded or restarted. Android still asks you to confirm the install because Shelly is distributed outside the Play Store.
Expo OTA is disabled for release APKs. JS, native, and bundled-tool changes ship together through a new APK so the installed binary and app code stay in sync.
Build from source
git clone https://github.com/RYOITABASHI/Shelly.git && cd Shelly
pnpm install && pnpm android
Requirements:
- Android device
- Node.js 20+ (CI currently builds on Node 20)
- pnpm
- Android NDK 26.1.10909125 (or an Android SDK/Gradle setup that resolves that pinned NDK)
Expo Go is not supported — Shelly uses native Kotlin/C modules.
Termux is not required. Shelly ships with bash, Node.js, Python 3, git, curl, sqlite3, tmux, vim, less, jq, make, and ripgrep. For tools beyond the bundled set, Termux can be used alongside Shelly.
First launch
On first launch Shelly asks for All files access so the terminal can read scripts in /sdcard/Download and anywhere else on your phone. Tap Allow and you're done — source /sdcard/Download/foo.sh just works. Shelly is distributed through GitHub Releases for now; Play Store / F-Droid submission is still future work.
Configure AI
After that, open Settings → API Keys (or run shelly config from the terminal pane) to paste API keys for Gemini, Cerebras, Groq, Perplexity, OpenAI-compatible local servers, or other explicit API providers. Keys are stored in expo-secure-store and never written to logs.
Sign in
Shelly's foreground AI CLI is Codex. Everything else is an API provider you configure with a key.
| Surface | How to sign in | Notes |
|---|---|---|
| Codex CLI (ChatGPT subscription) | Run codex, or codex-login --open directly |
The supported foreground CLI. If ~/.codex/auth.json is missing or invalid, the codex wrapper starts Shelly's device-code login, opens the OpenAI device-code page in the in-app Browser Pane, writes ~/.codex/auth.json (mode 0600) on success, then launches the normal Codex TUI. No OpenAI API key required — this rides your ChatGPT subscription. |
| API providers (Gemini, Cerebras, Groq, Perplexity, local) | Settings → API Keys or shelly config |
Paste a key per provider for AI-Pane / @mention / @team / background-agent use. Keys live in expo-secure-store. Local/OpenAI-compatible servers need only a base URL. |
Codex login note.
codex /logininside the REPL is not the supported path on Shelly. Use barecodexand let Shelly's wrapper launch device-code auth, or runcodex-login --openfrom bash.
Bundled Shelly commands
| Command | Use |
|---|---|
codex |
Launch the foreground Codex TUI in the native terminal. If auth is missing, Shelly starts the device-code login flow first. |
codex-login --open |
Start ChatGPT subscription device-code auth and open the verification page in Shelly's Browser Pane. |
shelly-doctor |
Check shell/native binary presence, bundled Codex binaries, JS dispatcher, local LLM endpoints, and Codex auth file presence. |
shelly-codex-diagnose |
Run deeper Codex smoke/canary/edit/patch diagnostics. |
shelly-update-clis codex --check-only |
Probe the active Codex runtime. Runtime installs are normally driven by the Updates UI. |
shelly-cs / cs |
GitHub Codespaces helper commands. |
Runtime model
Shelly's headline advantage is the runtime itself: a native PTY and a managed Codex CLI running in the same on-device shell as your files, with API-backed agents layered on top — not a WebView terminal, not a remote IDE client.
If your AI coding CLI workflow stalled in Termux, proot, or another Android terminal setup, Shelly gives you a maintained on-device environment built around the constraints of real Android devices (bionic libc, linker64 exec rules, SELinux on app_data_file).
No fragile terminal stack. No WebView terminal crashes. No copy-paste-driven workflow.
- Native execution path — Codex runs through Shelly's app-owned native PTY (JNI
forkpty), not a remote bridge or socket terminal. - Managed latest, not blind latest — Shelly ships a pinned Codex runtime in each APK, and the Updates UI can install a newer verified Codex runtime from the rolling
codex-runtime-latestrelease without waiting for the next APK. - Visible state — the app can show recent terminal logs, so version drift and startup failures are easier to debug on the device itself.
- Compliance boundary — Codex is a foreground, user-controlled terminal CLI. AI-Pane / background automation uses explicit API providers; it does not run a hidden subscription worker.
This is the part that makes Shelly more than a terminal skin. It is the reason the app can ship a fast-moving CLI on Android without turning the user into the update mechanism.
Release surface
| Surface | Status | What that means |
|---|---|---|
| Codex CLI | Supported | The foreground CLI. Bare codex launches the normal Codex TUI after Shelly verifies or creates ~/.codex/auth.json through in-app device-code auth, running over the native PTY. |
| AI Pane / background agents | Supported through APIs | Uses configured providers: Gemini API, Cerebras, Groq, Perplexity, and local OpenAI-compatible servers. Provider-key based, no hidden subscription reuse. |
| Gemini API | Supported where configured | Available for the AI Pane, @gemini routing, @team, multimodal/API-backed tasks, and background agents when a Gemini API key is set. (This is the API provider — there is no bundled Gemini CLI.) |
What Shelly is not
Shelly is not a Termux skin, a WebView terminal, or a remote IDE client. It owns the Android terminal stack inside the app, runs Codex on-device in the same shell as your files, and layers API-backed agents next to that terminal instead of forcing you through copy/paste or a cloud workspace.
No Termux install. No proot. No ttyd. No remote bridge.
Features
Features below describe implemented paths in the current build. Items with limited device validation (e.g. voice dialogue, immortal sessions, unattended agent firing) are caveated here and in Status / Coming Soon.
Highlights
| On-device autonomous agent | Say it in plain language → a scheduled agent runs on the phone by itself (screen off), on your own keys and tools, and tells you when it ran. It works where a cloud agent can't reach — your files, terminal, local LLM, the device itself. One unattended run observed end-to-end on one device (N=1) — cross-OEM reliability not yet proven; see Status. (details) |
| Cross-pane intelligence | Say "fix the error." AI reads your terminal, suggests a fix, one tap to run. Zero copy-paste. |
| AI Edit golden path | Tap a file in the sidebar → preview it → hit [✨ AI] → describe the change → accept per hunk → the file is rewritten on disk, the preview reloads automatically. |
| Codex apply_patch on-device | Codex file edits land through the agent's native patch tool on Android, not a shell-only fallback. |
| Native PTY (JNI forkpty) | Kotlin + C, direct PTY fd, no TCP/socket bridge — an embedded native terminal, not a WebView terminal. |
| Batteries included | bash, Node.js, Python 3, git, curl, sqlite3, tmux, vim, ripgrep, jq ship inside the APK. Termux not required. |
| 7 pane types | Terminal, Agent Chat, AI, Browser (+ background audio), Markdown, Preview, and Ask. Split up to 4 live panes freely. |
| Multi-agent AI | API-backed Gemini, Cerebras, Groq, Perplexity, Local LLM, plus the foreground Codex terminal CLI. Auto-routed or @mention where supported. |
| Local LLM (on-device, llama.cpp) | Qwen3.5 models run on-device through the bundled llama.cpp / llama-server flow, with Qwen3.5-2B as the daily-driver default, Qwen3 1.7B / Qwen3.5 0.8B as lighter fallbacks, and 4B+ models reserved for short quality checks. |
| Codex on Android | Shelly keeps Codex on a managed-latest path without trusting upstream blindly: each APK bundles a pinned runtime, the Updates UI can promote verified runtime releases, and Reset falls back to the bundled runtime. Codex runs over the native PTY with a Shelly-owned device-code login wrapper. No proot, no root. |
| Scouter home widget | A translucent Android widget shows Codex state, model, always-on token / context / limit cells, local LLM health, device load, and the next scheduled agent without opening the app. It is interactive: RUN starts that already-registered agent through the unattended execution gates; ASK, Allow / Deny, and choice pills control the foreground Codex PTY. |
| Color themes | Blue / Red / Purple palettes run on the existing preset IDs, so runtime swaps keep your shell alive without settings migration. |
| Voice input | Speak your commands or AI prompts. Groq Whisper handles transcription, then VoiceChain routes the text through the same input router the keyboard uses. |
Autonomous agents
Say what you want in plain language; Shelly registers a scheduled agent that runs on the device, by itself — even with the screen off. It wakes via Android AlarmManager (setExactAndAllowWhileIdle, designed to fire under Doze, unlike cron-under-Termux), runs on-device with your own keys and tools, and tells you when it ran (notification + per-agent next/last-run, with a missed-run warning if an expected run didn't record).
The wedge isn't "smarter than a cloud agent" — it's that it works where a cloud agent can't reach: your files, your terminal/scripts, your local LLM, the phone itself.
It's a capability you point at your own tools, not a fixed feature. One example (mine):
@agent every weekday at 8am, collect the latest STEAM×AI education papers and news,
and write the primary-source links + a short summary to my Obsidian vault
The schedule above registers an agent that, when it fires, wakes the phone, researches via Perplexity, and drops a dated, sourced summary into Obsidian — unattended. (Observed end-to-end once so far; see the demo and Status for what's actually been verified.) Swap in your own schedule, source, and output.
Honest caveat: unattended firing depends on Android's background limits, which vary by manufacturer (Samsung / Xiaomi / Oppo / OnePlus battery-freezers). Shelly uses Android's highest-priority alarm path (named above) and surfaces missed runs, but it can't guarantee a fire on every device — grant the battery-optimization exemption and check the agent's run view.
Scouter Widget
Scouter is Shelly's home-screen status layer. It keeps the current Codex session, local LLM endpoint, token / context flow, rate-limit windows, and device load visible while the phone stays in the launcher or another app. It is not read-only — the widget can drive the foreground Codex terminal, resume a stale binding, cold-start a new Codex PTY for a queued prompt, or run the next already-registered scheduled agent without opening Shelly.
- State-colored status — the status dot and title track the bound Codex state (idle / thinking / running tool / waiting / error), with the current
DOINGline - Model / cost line — the active Codex model plus derived
$costwhen token counts are available - Always-on usage cells —
CTX,TOK,LIMIT,5H, andWKstay visible even when Codex is not running; live Codex data wins, otherwise Scouter falls back to the latest sanitized usage snapshot or placeholder dashes - Rate-limit quota gauge — a 5-cell remaining-quota bar per window (
5H/WK), green while healthy and red once it drops to its last cell (~<=25% left) - Rate-limit override — when the session is throttled the line collapses to
RATE LIMITEDwith the reset detail - Reset / session timer — a self-ticking chronometer counts down to the rate-limit reset, or counts up the running session
- Privacy-safe prompt preview — only the current widget ASK / approval / choice / error state can occupy the preview; historical JSONL prompts and replies are not surfaced, and closing all Agent Chat tabs blanks the preview area instead of shrinking the widget
- Scheduled-agent status — shows the next registered agent and fire time plus the latest widget-triggered running / success / error result
- Local LLM row — endpoint, backend, queue depth, and ping for the local server
- Footer — CPU / RAM load and last-updated time
- Codex pets — an optional PET button / pet image renders the bundled demo pet or the user's imported Codex pets without bundling private user pets into the APK
- ASK — tap the ASK pill to type a prompt; Shelly writes it into the bound foreground Codex terminal (clear line, paste, Enter) and returns you to the launcher
- RUN scheduled agent — starts the next enabled, scheduled agent directly through the foreground service without opening the app; Shelly revalidates its disk metadata at tap time, honors STOP-ALL, and keeps unattended per-action approval fail-closed
- Cold-start ASK — if no Codex or Agent Chat session is available, Shelly queues the widget prompt, opens a terminal, waits for the PTY to become alive, starts
codex, waits for the Codex input surface, then delivers the queued prompt - Approval pills — when Codex is waiting for permission, Allow / Deny pills write
y/nstraight to the Codex PTY - Choice pills — for a numbered interactive prompt, up to six widget pills write the chosen digit to the PTY, each carrying the option label; Android notifications expose the first three actions
- Pet cycle — PET starts hidden by default; tap PET to show the first pet, tap the pet image to cycle through available pets, and the cycle hides again after the last pet. Approval / choice action rows take priority over pet controls
- Pet import — Settings -> Scouter -> Import pet ZIP installs user pets into app-private storage. Shelly also discovers
Codex/petsandshelly-personal-pets.zipsidecar files on shared storage for users who manage Codex pets outside the APK - Stale-tap guard — Allow / Deny / choice taps re-parse the live terminal screen and only fire if the same approval anchor or numbered option is still on screen; otherwise they no-op
- Resume when unbound — if the bound terminal has exited, ASK (and a pending approval) queue the prompt/decision and open Agent Chat to resume the session, then drain the queued action
- How controls are dispatched — ASK / approval / choice controls write to the live PTY through the in-process terminal session registry; RUN uses a direct foreground-service PendingIntent matching scheduled fires. Neither path shells out through
am start
- Single-screen layout — AgentBar (top) + Sidebar (left, collapsible) + PaneContainer (center) + ContextBar (bottom)
- 7 pane types — Terminal (native PTY), Agent Chat (Codex session companion), AI (streaming + context injection), Browser (WebView + bookmarks + background audio), Markdown (viewer), Preview (Code / Image / PDF / CSV / Markdown renderers), and Ask (Shelly help)
- Preset slot layout — up to 4 live panes in single, two-column, three-pane, or four-pane presets; drag the accent-green grip to resize, double-tap it to restore 50/50
- Layout presets — Single Terminal / Terminal + AI / Terminal + Browser / 3-Way Triple, all reachable from the Command Palette
- Pane-type pill — header left shows
[TERMINAL ▾]/[AI ▾]/ …; tap to change the pane type in place - CLI tab strip inside terminal panes — multiple shell tabs per pane,
[● SHELL][+], close×on non-last tabs - Empty-pane recovery — the last pane cannot be closed; if the tree ever empties, a 3-button CTA (Terminal / AI / Browser) brings it back
- ContextBar — always-visible footer showing cwd, git branch, and connection status
- "Fix the error on the right" — AI reads the current terminal transcript and responds with executable fixes
- ActionBlock — code blocks in AI responses get
[▶ Run]buttons that dispatch to the active terminal pane - Pane-aware terminal selection — in split layouts, the AI pane prefers the terminal immediately to its left, then the focused terminal, then the first terminal
- Real-time terminal awareness — AI pane snapshots the terminal transcript on dispatch so the model sees what you just saw
- Terminal-safe context — ANSI/OSC/control sequences and TUI redraw noise are stripped before injection; terminal output is treated as untrusted evidence, not instructions
- Local LLM compaction —
@localkeeps important header/status/error lines and the recent tail so small on-device models still see the useful terminal state - Error-file auto-stage — when terminal output references a file path, Shelly can stage that file so an AI diff can be accepted directly
- CLI Co-Pilot — in-flight translation of output, approval prompt explanations, session summaries
- Approval Proxy — terminal
[Y/n]prompts are lifted into chat-styleApprove / Deny / Ask AIbuttons so you never type blind 'Y' - Error Summary — detected errors surface as persistent chat bubbles with
[Suggest Fix] - Auto-savepoint — every edit is auto-committed to a hidden git index so you can revert to any point with one tap
- Pre-commit secret scan — API keys, private keys, and other secrets are blocked before they land in a savepoint commit
- Chat over the foreground Codex — a chat-style pane that mirrors the bound Codex session's timeline (user prompts, Codex replies, tool runs, approvals, errors) parsed from the session JSONL and Scouter snapshots
- Reply composer — type a reply and send; it writes to the bound foreground Codex PTY, not a hidden API worker — consistent with Shelly's compliance boundary
- READY / LOCKED — a pill shows whether the bound terminal can accept a reply; when locked, the composer explains why (terminal exited, Codex busy, waiting on a terminal choice, not bound yet)
- Approve / Deny — approval requests surface as bubbles with Allow / Deny buttons that send the decision to the bound Codex terminal; only the latest pending approval is actionable
- Interrupt — a stop button sends a terminal interrupt to the bound Codex while it is working
- Resume — the play button reopens or focuses the bound Codex terminal for the selected session, rebinding it for replies
- Session tabs — recent Codex sessions are shown as tabs (deduped per workspace + model), each with a binding dot; dismiss hides a session from Agent Chat without touching its JSONL on disk
- Session strip — project, status, binding, model, token count, and last-update time for the selected session
- Staged file — tap a file in the FileTree; it opens in the Preview pane's Code tab. The
[✨ AI]toolbar button stages the file in the AI pane's context. - Dispatch — write "make the first function Japanese-comment" (or anything) and send. Shelly's system prompt asks the model to respond with a unified diff.
- InlineDiff — the assistant reply is scanned for unified diff blocks and each hunk is rendered with
+/-/ context coloring plus Accept / Reject buttons. - Per-hunk accept writes to disk — accepting one hunk calls
acceptStagedDiff()with a re-serialised single-hunk diff; the file is rewritten via the nativewriteFileNativebridge and the Preview pane auto-reloads. - Fuzzy re-anchor — if the
@@ -Nline numbers are stale (because a previous hunk already edited the file on disk), the applier searches forward for the hunk's leading context block so successive hunks still land. - Accept All — takes the same write-back path but applies every pending hunk in one pass.
- Fig-style autocomplete — top-level commands with subcommand and flag completion, rendered as an inline popup
- Syntax highlighting — terminal output colorized by content type
- Clickable paths and errors — tap a file path or stack trace line to jump to it
- Inline content blocks — JSON, markdown, images, and tables rendered inline inside the terminal output (Command Blocks)
- CLI notifications — long-running commands surface a system notification when they complete
- Codex notification channels — Scouter posts per-category Android notifications, each on its own channel so you can tune importance / sound / mute from Android's notification settings: approvals, choices, and errors arrive as heads-up alerts, rate limits at default importance, completions and long-running quietly. Approval notifications carry one-tap Allow / Deny buttons and choice notifications expose the first three numbered actions; the widget itself can show up to six choice pills. The expanded notification view shows the full request or menu text, and resolved cards are deduped and cancelled so nothing stacks or lingers
- SmartKeyBar — 5 context-adaptive key sets (Default / Vim / Git / REPL / Navigate), swipe to switch
- Immortal sessions — tmux keeps your shell alive when the app is backgrounded; resume any session by name
- Japanese input in terminal — compose CJK characters directly in the terminal pane
- Readable terminal glyphs — the native Kotlin terminal view renders the PTY grid with JetBrains Mono so lowercase, columns, and code output stay legible
- Atomic paste — all paste paths converge on
TerminalEmulator.paste(), which wraps payloads in bracketed-paste markers (\e[200~..\e[201~) unconditionally. IME multi-line or ≥16-char commits, middle-click mouse paste, and the CommandKeyBar Paste key all reach the same normalizer; multi-line and complex one-liners arrive as one event so readline executes only the trailing newline.
- Multi-agent routing — the router picks the best AI for the task; override with
@mention - @mention — direct AI Pane providers are
@gemini,@cerebras,@groq,@perplexity, and@local; utility routes include@team,@agent,@git,@open/@browse,@plan,@arena, and@actions/@ci. There is no@claude— Claude Code is not a current provider. Codex remains available as the foreground terminal CLI viacodex. - Terminal context injection — the AI always has access to the current terminal transcript without you pasting anything
- InlineDiff with per-hunk write-back — see above
- Voice input — long-press the mic in the terminal action bar to open VoiceChat; speech → Groq transcription → AI → TTS response
- Local LLM support — use the built-in GGUF catalog and llama.cpp / llama-server controls, then route via
@localfor fully on-device inference. Qwen3.5-2B Q4_K_M is the default, Qwen3 1.7B and Qwen3.5 0.8B are lighter fallbacks, and 4B/9B models are intended for short quality checks.
- Full WebView — navigate any URL inside a pane; keep docs open next to your terminal
- Bookmarks — save and organize URLs; preset icons for YouTube, X, GitHub, and
localhost:* - Background audio — audio keeps playing when you switch panes
- Link capture — share a URL to Shelly from any Android app; it opens in the browser pane
- Desktop UA toggle —
📱/🖥button in the URL row swaps the user agent so desktop-only sites behave - Video fullscreen — six detection paths (W3C / WebKit / video element / monkey-patched APIs) catch YouTube-style fullscreen and maximize the pane, hiding the system nav bar
- Active-repo file list —
ls -1palisting for the current working directory with per-extension icon coloring (.tsxsky,.tsblue,.jsonamber,README.mdred, …) - Search — incremental filter over the current directory
- Open actions — tap a Markdown file to open the Markdown pane, tap anything else to open the Preview pane's Code tab
- Create / Rename / Delete —
+file and+folder buttons next to the search field; long-press a row forRename / Copy path / Delete; modals use the active app palette - Breadcrumb — tap the
..row to go up
- Code tab — per-file syntax-highlighted view with line numbers; the
[✨ AI]button stages the current file for AI Edit - Markdown renderer —
react-native-markdown-displayplus the Shelly palette - Image / PDF / CSV renderers — inline viewers for common non-code attachments
- Git diff view —
git diff <file>shown in the Code tab with neon+/-coloring - Recent files — quick switcher inside the Preview header
- Repositories — list of bound repo paths; tap to switch; the active repo shows an amber badge with the number of uncommitted files, polled every 20 seconds from
git status --porcelain - File Tree — see above; embedded as a section so it flexes with the sidebar height
- Tasks — recent background-agent runs with duration and status
- Device — quick-access folders (
~,/sdcard/Download, …) that re-bind the file tree in one tap - Ports — designed to list loopback / wildcard listeners and open
http://localhost:<port>in the Browser pane. Android 10+ SELinux currently blocks the/proc/net/tcp{,6}reads for normal apps, so this remains tracked as a platform limitation in Status. - Profiles — saved SSH connections. Tap to insert
ssh -i KEY user@host -p PORTinto the active terminal pane; long-press to edit or delete;Import from ~/.ssh/configbulk-adds hosts. Key-file auth only — no passwords or passphrases are persisted.
Cloud storage? Shelly deliberately doesn't ship a Google Drive / Dropbox / OneDrive UI. A terminal app should lean on the tools that already solve this — install
rclonefrom your package manager, runrclone configonce, and mount or sync any of 40+ cloud backends from the terminal pane.
Opens from the search icon in the top bar (or from the AgentBar's git badge). Fuzzy search across every registered action, plus a persistent Recent list of the last five you ran.
Currently registered:
- Settings — open the terminal-style Settings TUI
- Terminal — Clear / New session / Restore tmux / Tmux attach
- Git — Status / Diff / Log / Add all / Commit / Push / Pull --rebase (routed through the active terminal pane's
pendingCommandchannel) - Panes — Add Terminal / AI / Browser / Markdown / Preview
- Layouts — Single Terminal / Terminal + AI / Terminal + Browser / 3-Way Triple
- Theme presets — Blue / Red / Purple
- Font presets — Silk / 8bit / Mono and legacy editor palettes
- Voice — Open dialogue (VoiceChat modal)
- Snippets — first 20 entries from your snippet store, each dispatches to the terminal
- Package Manager — bundled tools status
- Color presets — Blue is the default cool palette, Red is red-orange chrome, and Purple is purple with neon green accents.
- Visible presets — Settings and the Command Palette expose the three color themes. Legacy and editor palette IDs remain accepted for old saved settings but are no longer the primary UI surface.
- Runtime swap — presets are swapped by mutating the live
colorsobject in place (identity preserved) and bumping a theme-version store that key-remounts the shell layout. PTY sessions survive the switch — your vim stays open. - Single-family rendering — every Text is forced through JetBrains Mono regardless of its
fontWeight, keeping UI and terminal typography consistent. - Text.render monkey-patch —
Text.defaultProps.styleis replaced (not merged) when a child passes its ownstyle, which would otherwise let 100+ call sites escape the theme font. The patch prepends{ fontFamily }to every Text's style array so the preset font reaches every call site without touching them. - Neon glow — eight per-color
textShadowstyles (teal / blue / sky / purple / pink / green / red / amber) for the mock's "reading terminal" vibe - Haptic toggle — per-interaction feedback on/off
- Dirty badge — AgentBar (amber pill, global) and Sidebar (on the active repo row) both show the uncommitted-file count, polled every 20 seconds by a single writer in
useGitStatusStore. Tapping the AgentBar badge opens the Command Palette filtered toward git actions. - Command Palette — the seven git actions listed above
- Auto-savepoint — background git-based save system (
lib/auto-savepoint.ts) with secret pattern scanning before each commit - Git diff preview — Preview pane Code tab renders
git diff <file>with the neon diff palette
- Inline API key editor — Gemini / Cerebras / Groq / Perplexity and local/OpenAI-compatible API keys in the Settings dropdown with masked display and per-row
EDIT / CLEAR / SAVE / CANCEL. Keys live inexpo-secure-store. - Settings TUI — full settings also accessible via a terminal-style text UI
- Command safety — regex-based 5-level risk assessment (seatbelt, not firewall — see Security)
- Workspace isolation — per-project cwd / env / AI context
- Background agents —
@agent list,@agent status,@agent run <name>,@agent stop <name>,@agent history <name>, or@agent <natural language>to create one. Scheduled agents run through AlarmManager when configured. - Managed Codex runtime updater — the Updates UI reads the public
codex-runtime-latest/codex-runtime.jsonmanifest, downloads the tarball, verifies SHA-256, smoke-testscodex_tui --versionandcodex_tui exec --help, then promotes the runtime under~/.shelly-runtime/codex/current. The new runtime is used by newly opened terminal tabs; Reset falls back to the APK-bundled runtime. shelly-doctor— diagnostic command that checks shell/native binary presence, bundled Codex binaries, JS dispatcher, local LLM endpoints, and whether~/.codex/auth.jsonis present; run it when something feels broken
Codex Runtime
- Native runtime — the npm
@openai/codexpackage is only part of the JS dispatcher story. Release APKs bundle the pinned Android-native unifiedcodex_tuibinary from.ci-versions/, and runtime updates install the same shape under~/.shelly-runtime/codex/current. - Managed promotion — a new runtime candidate is promoted only after download, SHA-256 verification, extraction, executable checks, and
codex_tui --version/codex_tui exec --helpsmoke checks. - Repair / reset path — if the app-data runtime is broken or unwanted, the Updates UI can repair it from the latest runtime release or reset to the APK-bundled Codex runtime.
Status
| Area | State |
|---|---|
| Native PTY, sessions, tmux revival | ✅ shipping |
| Multi-pane layout (7 types, splits, presets, drag resize, empty-state CTA) | ✅ shipping |
Atomic paste (bracketed-paste wrap when guest opts in via DECSET 2004, single TerminalEmulator.paste() choke point, IME chunk-split coalesced) |
✅ shipping (bugs #91, #94, #97, #106) |
/sdcard access via MANAGE_EXTERNAL_STORAGE (first-launch grant flow) |
✅ shipping (bug #92) |
Comments (0)
Sign in to join the discussion.
No comments yet
Be the first to share your take.