日本語で読む

# Shelly — User Manual This is the manual. If [README.md](../README.md) is the pitch, this is the walkthrough — what to actually do, in order, the first time you open the app and every time after. It assumes nothing except that you have the APK installed. If you haven't installed it yet, go do that first: [Quick Start → Install](../README.md#install). --- ## 1. Before you start Shelly asks for more Android permissions than most apps, and it asks for a reason: it's a terminal, and a terminal that can't touch your files isn't a terminal. The one that matters most is **All files access** (`MANAGE_EXTERNAL_STORAGE`). Shelly asks for it the moment you open the app for the first time. Say yes. Without it, everything inside the app's own private storage still works — but `/sdcard/Download` and anywhere else on shared storage will throw `Permission denied` the instant you try to `cd` into it or `source` a script from it. That's Android's Scoped Storage doing exactly what it's designed to do, not a Shelly bug. If you deny it by mistake, it's recoverable but not automatic: go to **Settings → Apps → Shelly → Permissions → Files and media → Allow management of all files**, then fully close and reopen Shelly. The app only re-checks this permission when it opens, not while it's already running. Everything else — notifications, foreground service, microphone — Shelly asks for individually, closer to the moment you'd actually use the feature, and each one degrades gracefully if you say no. The full breakdown, including exactly what breaks and what doesn't, is in [README → Permissions](../README.md#permissions). I build and test Shelly on a Galaxy Z Fold6 — that's the only device it's been run through properly, N=1. Most of it will behave identically on your phone. The parts that are genuinely more device-dependent — unattended agent firing while the screen is off, mainly, because it depends on manufacturer-specific battery management — are called out where they come up, both here and in the README's [Status](../README.md#status) table. --- ## 2. Your first session Open the app. You land on a single terminal pane — a real shell, not a text box pretending to be one. There's a blinking cursor and a prompt, the same as opening a terminal on a laptop. Type something ordinary first: ``` ls pwd git status ``` Nothing about this should surprise you. Underneath everything else Shelly does, there's a real PTY — a pseudo-terminal, the same kind your laptop's terminal talks to — running a real bash, with real coreutils. Now break something on purpose, and ask about it instead of scrolling up to read the error: ``` npm run build ``` If that fails (it will, in an empty directory), don't go hunting for the stack trace. Look for the **AI pane** — if you only have one pane open, tap the pane-type pill in the header (it says `[TERMINAL ▾]`) and switch to `AI`, or use the Command Palette to add one alongside the terminal. Then say: > fix the error When you send that, the AI pane takes a snapshot of the current terminal transcript and reasons over it — you never paste anything. It'll tell you what went wrong and offer a runnable fix with a **[▶ Run]** button. Tap it, and the fix lands directly in the terminal pane and executes. That loop — break something, ask, tap Run — is why Shelly exists. Everything else in this manual is either making that loop richer (more panes, more context, more AI backends) or making it unnecessary (an agent that runs the loop for you, on a schedule, while your phone sits in your pocket). --- ## 3. Talking to the AI pane The AI pane can already see your terminal. That's the one thing a general chat app can't do. **By default, you are talking to Shelly.** The local-persona chat presents as one persistent companion named Shelly rather than exposing whichever model answered underneath — replies never carry a provider-name tag, no matter which model actually generated them; if you want to know who's currently bound to the pane, that's shown once in the pane header, not repeated on every message. Agent registration and confirmation happen as a conversation rather than a form. Every AI pane bound to this default persona opens the same continuous conversation, so moving to another pane or split does not start over. A pane explicitly bound to an external provider such as Gemini (via the pane-header agent badge or an `@mention`) keeps its own per-pane history. **Switching a pane's binding carries a little context with it.** Whether you're moving a pane from the companion to an explicit provider or back again, Shelly copies the last few on-topic messages from the thread you're leaving into the one you're entering, with a small system notice explaining the hand-off. It's meant as a continuity nudge, not a full merge of the two histories — switching back and forth doesn't duplicate messages, and a pane-scoped copy doesn't survive an app restart (only the shared companion thread itself does). **Shelly can remember a preference for itself and every agent.** In the default companion chat, say something natural such as “remember that my deploy branch is staging.” No all-agents scope marker or special syntax is required. Shelly asks for confirmation before writing the note; once confirmed, that `_global` memory is recalled in later companion conversations and included in every scheduled agent's execution context. (Phrasing like “I prefer …” or “I like …” is separately picked up by Shelly's ambient usage-pattern learning — see [Privacy](../README.md#privacy) — so a sentence combining both can leave two notes instead of one; a plain factual “remember that …” avoids that overlap.) **Separately, Shelly also keeps a journal on its own — no confirmation needed.** Every time a pane switches away from the companion, Shelly distills what the conversation established into a short note using the on-device local LLM, and saves it to its own `_companion` memory scope. This is companion-only: unlike the `_global` notes above, journal entries are never handed to background agents. Later companion replies only pull back the handful of journal notes relevant to what you're currently asking (ranked by BM25 plus recency, capped at five), so it stays useful instead of turning into a wall of everything you've ever said. You can browse, edit, or delete these notes any time from **Settings → Companion Memory** — that screen is reachable even before you've registered a single agent. **You can remove one message without clearing the thread.** Long-press any message bubble in the AI pane and confirm **Delete**. Only that individual message is removed from the conversation. **`@mention` picks who answers.** By default, Shelly routes your message to whichever configured provider fits the task. If you want a specific one, say so: `@gemini`, `@cerebras`, `@perplexity`, `@openrouter`, or `@local` for the on-device model. There's also `@team`, which fans the same prompt out to every provider you have configured at once — useful for comparing answers, but it spends credits on all of them simultaneously with no confirmation step, so use it deliberately. (Groq is configurable as a provider and powers voice transcription, but it isn't wired to its own `@groq` mention yet.) **It reads your terminal, not your intentions.** In a split layout with more than one terminal, it prefers the one immediately to its left, then whichever terminal is currently focused, then the first one — keep the terminal you're asking about visually adjacent to the AI pane if you're running more than one shell. **A fenced ` ```bash ` reply block can go straight into your terminal.** It shows an **Insert** button next to **Copy** — tap it and the code lands in the focused Terminal pane's input line (no auto-Enter, so you can look it over before running it). If no terminal pane is open, Shelly opens one and queues the insert for the moment its shell is ready. **AI Edit is the golden path for actually changing files.** Tap a file in the sidebar's File Tree — non-Markdown files open in the Preview pane's Code tab (Markdown files open in a separate Markdown pane that doesn't currently support AI Edit staging). Hit the **`[✨ AI]`** button in the Code tab's toolbar, which stages that file into the AI pane's context, then describe the change in plain language: "add error handling to the fetch call," whatever you need. The model replies with a unified diff, and Shelly renders it as an **InlineDiff**: green additions, red removals, an **Accept** / **Reject** button on every hunk. Accept a hunk and it's written to disk immediately. The Preview pane doesn't always repaint itself automatically after that write — if what you see doesn't look updated, switch the Diff/Full toggle or reopen the file. If a later hunk's line numbers have drifted because an earlier hunk already changed the file, Shelly searches forward from where it's currently reading for the hunk's original context to re-anchor it; it only searches forward, so a hunk that needs to land earlier in the file than the last edit won't be found, and you'll see a "regenerate" prompt for it instead. **Voice works the same way.** Long-press the mic icon in the terminal's action bar to open VoiceChat — speech goes through Groq's transcription, the text goes through the same input router your keyboard uses. (Voice input itself is confirmed working.) **Local means local.** `@local` routes to whatever GGUF model you have running through the bundled llama.cpp / llama-server integration — no network call, full privacy, at the cost of being slower and less capable than the cloud providers. Qwen3.5-2B is the default that balances speed and quality on-device; there are lighter and heavier options in Settings. --- ## 4. Building your layout Folded, Shelly is a single terminal, and that's a complete way to use the app. But a phone screen — especially a foldable's inner screen — can hold more than one thing open at once, so the layout system exists. Tap the **`+`** button in the AgentBar (the top bar) — it opens a sheet with an ADD tab and a LAYOUT tab; switch to LAYOUT to pick an arrangement. You can go up to four live panes at once (at most three of them can be terminals), in eight preset shapes: single, two-column, top/bottom split, three-way splits from either side or top/bottom, or a full four-pane grid. Switching to a smaller preset doesn't close your other panes — they're hidden, not lost, and come back if you switch to a bigger preset. Each pane has a type pill in its header (`[TERMINAL ▾]`, `[AI ▾]`, `[BROWSER ▾]`, …) you can tap to swap what that slot shows in place. **On a Fold-class device, the full grid is the layout Shelly is designed around.** Folded, you get the single-pane terminal — a genuinely good phone terminal on its own. Unfold, and the same live session — same shell, same scrollback, same running processes — expands into up to four panes without restarting anything: sidebar for repos and files, terminal doing the work, AI pane reading over its shoulder, browser pane for docs or a `localhost:3000` preview. One caveat: folding and unfolding rapidly *while* a CLI stream is actively printing (mid-build, mid-AI-response) isn't something Shelly guarantees survives cleanly — Android can recreate the underlying Activity. If something long-running is in flight, let it finish or interrupt it (Ctrl-C) before you fold or unfold. Ordinary use — fold at the end of a session, unfold to start the next — is fine. The sidebar (visible whenever there's room for it) holds more than repos and files: Tasks (your registered and running agents), Skills, Quick Launch shortcuts, recent Codex sessions, your repositories, worktrees, the file tree, quick-access device folders, and saved SSH profiles. Tapping a repository re-roots the File Tree to it — it changes what you're browsing, not the working directory of your existing terminal panes. On a genuinely fresh install, the sidebar opens with Tasks and Skills expanded, while the more developer-facing sections — Repositories, File Tree, Device, Worktrees, Quick Launch, Codex Sessions — start collapsed under a single **DEVELOPER** divider. Nothing is removed or hidden away permanently; it's one tap to open any of them. If you've already got Shelly installed and have your own sections open or closed the way you like them, this default doesn't touch your existing choices. --- ## 5. Setting up your AI providers Shelly draws a hard line between two different kinds of AI access, and it's worth understanding why before you configure anything. **Codex is the foreground CLI.** It runs your ChatGPT subscription — Plus, Pro, Business, or Enterprise — over the native terminal, the same way it would on a laptop. Sign in by typing bare `codex` (with no arguments) in any terminal pane: if `~/.codex/auth.json` doesn't exist yet, Shelly opens a device-code login page right inside the app's own Browser pane. Approve it there, and Shelly writes the auth file and drops you into the normal Codex TUI. No API key — this rides the subscription you already pay for. The flow times out after 15 minutes if you leave it sitting; just run `codex` again. `shelly-doctor` reports whether the auth file exists. **Everything else is an explicit API key**, deliberately. Gemini, Cerebras, Groq, Perplexity, OpenRouter, and OpenAI-compatible local servers are configured through **Settings → API Keys** (or `shelly config` from any terminal), one masked field per provider. This is a compliance boundary, not an implementation accident: background agents and the AI pane's automated routing never reuse your Codex subscription silently. If a background agent needs cloud intelligence, it needs its own key, configured by you, explicitly. (OpenRouter is stricter still: it's attended-only — even with a key set, an unattended agent run never routes through it.) You don't need every provider. A reasonable starting set: Codex signed in, one fast API key for the AI pane (Gemini or Cerebras both work well), and Perplexity if you want an agent that can research and cite sources. If you want zero network dependency at all, skip API keys and set up the local model instead — see `@local` in [Talking to the AI pane](#3-talking-to-the-ai-pane). --- ## 6. Registering your first autonomous agent Everything up to this chapter has been you, present, typing. This is the part that runs without you. An agent is a plain-language instruction plus a schedule. You register one by typing `@agent` followed by both, in a single sentence, in any pane. Here's the one I actually run: ``` @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 ``` Send that, and Shelly parses the schedule and the task separately, shows you what it understood, and — once you confirm — registers a real Android alarm. From that point on, nothing needs to be open. When the alarm fires, the phone wakes just enough to run the task and drops the result where you told it to. A notification confirms it ran, and Shelly also says the result in the shared companion conversation, so it is waiting in chat when you open the app later. The same chat re-entry happens after a manual **Run Now**. The agent's own row in the sidebar's Tasks section shows last-run and next-run times, with a missed-run flag in the row's detail view if an expected run didn't happen. One thing to set up before an agent like this will actually do what it says: **by default, unattended runs are only allowed to use Codex and on-device tools, not cloud API keys.** An agent registered exactly as above will, when it fires unattended, fall back to researching through Codex instead of Perplexity unless you turn on **Settings → Autonomous Cloud** (off by default) — that setting is the one place you explicitly allow a scheduled agent to spend a configured cloud API key while you're not watching. Turn it on if you want the agent above to actually use Perplexity when it fires on its own. A few more things worth knowing: **Vague requests get a real back-and-forth, not a single canned question.** If you type `@agent help me out` with no object and no domain, an LLM — not a fixed script — drives the rest of the conversation in its own words, asking one follow-up at a time until it has enough to propose a registration (a fast cloud provider first if you've configured one, then the on-device model, then Shelly's older fixed-question fallback if nothing is reachable). If your answer turns out to describe several ordered steps — "look this up, summarize it, then post it" — it's registered as a real multi-step chain instead of getting flattened into one instruction. This is on by default; toggle it off in **Settings → Agents → LLM-Led Agent Registration** if you'd rather always get the fixed one-field-at-a-time prompts. Either way, nothing is registered until you confirm it, and any value the model proposes is independently re-checked — a schedule phrase still goes through the same deterministic parser, a posting destination still has to match a connector you actually registered. **"Starting next week" means what it says** — `@agent starting next week, check the news every morning` registers the agent immediately but holds its first fire until the resolved date. The relative-start vocabulary currently understands "next week / next month / tomorrow / in N days" — day-of-week phrasing like "starting Monday" isn't recognized yet. (The registration behavior itself is confirmed.) **A schedule isn't the only trigger** — phrasing like `@agent when I get a notification, summarize it and save it as a memo` registers an agent that fires when a matching app notification arrives instead of on a clock; during registration Shelly asks which app's notifications should trigger it. By default only the notification's *arrival* triggers the run — the notification text itself is not read. If you long-press the agent's row and add exact sender display-names, the text is passed to the agent only when the sender matches exactly, always marked as untrusted data rather than instructions; notifications from anyone else are dropped without being read. **Output isn't limited to a note** — an agent's result can go to a notification, an Obsidian draft, or out to Bluesky, Discord, Slack, Telegram, Mastodon, Misskey, WordPress, X, or a webhook, configured with that platform's key once. Naming several platforms in one sentence — "post this to Bluesky and X" — can register a single agent that posts to all of them, as long as you have exactly one connector configured for each platform you named; if a named platform has no connector (or more than one), Shelly falls back to whichever platforms it could resolve and tells you which one it dropped. Bluesky is verified against a real account; posting to two platforms from one agent at once is implemented but hasn't yet been fired against a live multi-connector setup. If a single request asks for both — "post this and notify me" — the local notification wins and the post is dropped, on purpose: turning a private notification into a public post is the one direction here you can't take back, so it's the one direction Shelly won't do without a clearer, separate request. (You'll still see a run-completion notification for a posting agent regardless — that's Shelly telling you the agent ran, not the "notify" action type described here.) Unless you've added the destination host to an allowlist, a social post also waits for your approval tap before it actually goes out — it doesn't post unattended by default. **Successful runs can be remembered and reused.** Put "remember the result" in an agent's instruction and each successful run leaves a note the agent recalls on later runs. Shelly can also distill a successful run into a reusable skill — the steps, provider, and budget that worked — and quietly reuses that plan when you ask for something similar later. Attended runs ask before saving ("Save as skill?"); an unattended run of a remembering agent saves the skill automatically and posts a notification with a one-tap **Delete skill** action instead of interrupting you. There's also a shared layer. An explicit command such as `@agent remember across all agents that I prefer short answers` needs both the remember phrasing and an all-agents phrase. In the default Shelly conversation, ordinary “remember …” wording is enough because the request is already addressed to the companion. Both paths ask for confirmation before writing the shared note that Shelly and every agent recall. **You don't need the app open to register one, either** — the same `@agent` syntax works from the ASK box on Shelly's home-screen Scouter widget, typed or spoken through its mic button (the recognized text lands in the field for you to review, it never auto-submits). A widget-typed `@agent` command goes through the exact confirmation Shelly would show if you'd typed it in the AI Pane. If you'd rather widget-registered agents skip that confirmation and register immediately — with a notification afterward instead of a prompt beforehand — turn on **Settings → Widget No-Confirm Register** (off by default). It only changes how agents registered *from the widget* are confirmed; typing `@agent` in the AI Pane itself always asks first. **The honest caveat that matters most:** unattended background execution on Android depends on manufacturer-specific battery management, and it varies. Samsung, Xiaomi, Oppo, and OnePlus all freeze background work more or less aggressively depending on settings you don't control from inside any single app — and if Android denies Shelly the precise-alarm permission, it silently falls back to a less exact alarm rather than failing loudly. Grant the battery-optimization exemption when Android offers it, and check the agent's run history the first few times until you trust it on your specific phone. --- ## 7. The terminal itself Everything above sits on top of an actual terminal, and most of what makes a terminal usable on a phone has to be rebuilt from scratch. Here's what that produced. **It's bundled, not fetched.** bash, GNU coreutils, Node.js, Python 3, git, curl, ssh, sqlite3, ripgrep, jq, tmux, vim, make, less, `gh`, nano, and unzip all ship inside the APK as real compiled binaries, extracted to app-private storage on first launch. There's no Termux dependency, no distro bootstrap, no `pkg install` step standing between opening the app and having a working toolchain. (Termux itself works fine *alongside* Shelly if you need something outside the bundled set — `busybox` and `htop` are two examples that aren't included.) **Fig-style autocomplete does not exist yet.** The old JS completion engine was unreachable from the app and has been removed. Terminal input goes straight through the native PTY and does not expose the in-progress input buffer or cursor to JavaScript. Restoring the popup therefore needs a scoped native (Kotlin) input event and new JS integration, not a setting you can turn on today. Terminal output highlighting, clickable file paths and stack-trace lines, and the **SmartKeyBar** are available now; SmartKeyBar swaps between four context-adaptive key sets by default — Default, Git, REPL, Navigate — so the symbols you actually need (`|`, `~`, `Ctrl`, arrow keys) are one tap away instead of buried in a symbol picker. A fifth set (Vim) is available via Settings → Terminal → "Show Vim key bar," off by default so it doesn't clutter the bar if you don't use Vim. **Sessions survive backgrounding.** tmux keeps your shell alive underneath when you switch apps or the screen locks, and you can resume any named session later exactly where you left it — including mid-edit in vim, cursor position and unsaved buffer intact. **Git status is ambient in the sidebar**, and every file edit — whether you typed it or an AI Edit hunk wrote it — is auto-committed to a hidden savepoint index in the background, so you can revert to any point with one tap without touching your real git history. A pre-commit secret scanner blocks API keys and private keys from landing in a savepoint before you'd ever notice they were there. **SSH profiles live in the sidebar.** Save a connection once — host, user, port, key file — and tapping it inserts the full `ssh -i KEY user@host -p PORT` command into your active terminal pane, ready to run. Long-press to edit or delete. `Import from ~/.ssh/config` bulk-adds every host you already have configured elsewhere. Only key-file auth is supported; Shelly never persists a password or a passphrase. **Snippets** are short commands you use often, saved once and dispatched from the Command Palette (it shows your first 20). The in-app create/import/edit UI was removed in an earlier cleanup pass and hasn't been rebuilt — snippets live in Android's AsyncStorage (`store/snippet-store.ts`), not a plain file, so there's currently no supported way to bulk-add them outside that removed UI. **If you use [Nacre](https://github.com/RYOITABASHI/Nacre) as your keyboard, Shelly and it talk to each other.** While Shelly is in the foreground, it writes your current directory, git branch, and a handful of sanitized recent-command terms (never raw commands or secrets) to a small context file that Nacre reads to bias its kana-kanji conversion toward what you're actually doing; the file is deleted the moment Shelly leaves the foreground. On Nacre's own side, its Dev Mode detects that focus is inside Shelly specifically and suppresses auto-punctuation conversion (no more `!=` silently becoming `≠` mid-command), defaulting its symbol panel to a programming tab instead. It's on by default — toggle it off in Settings → Nacre Bridge if you don't use Nacre. --- ## 8. When things go wrong Something will eventually not work the way you expect. Here's the order to check things in. **Run `shelly-doctor` first.** It checks whether the app's core native binaries are present, and — separately — whether Codex actually responds to `--version`. It's a quick sanity check, though it's worth knowing its limits: it doesn't probe whether a local LLM server is actually reachable (it only reports the addresses it *would* check), and it doesn't run any of the bundled shell tools to confirm they work — it's a presence/liveness check, not a full smoke test. **If it's specifically Codex**, run `shelly-codex-diagnose` for deeper smoke/canary/edit/patch checks, or `shelly-update-clis codex --check-only` to probe which runtime is actually active. If `codex --version` fails outright, **Settings → Updates → Repair Codex / Reset** falls back to the runtime that shipped inside the APK, which is guaranteed to at least start. **If `/sdcard` paths throw `Permission denied`**, that's almost always the All Files Access permission — see [Chapter 1](#1-before-you-start) for the exact Settings path, and remember to fully reopen the app afterward. **If a scheduled agent didn't fire**, open the agent's row in the sidebar's Tasks section for a missed-run flag, then check whether your phone's battery-optimization settings exempted Shelly — this is the single most device-dependent part of the app, covered honestly in [Chapter 6](#6-registering-your-first-autonomous-agent). **If something feels dangerous and Shelly let you type it anyway** — command-safety in Shelly is a regex-based risk classifier with five severity levels, not a sandbox. It's a seatbelt, not a firewall. Read commands before you run them, especially ones an AI generated for you. The full threat model is in [SECURITY.md](../SECURITY.md). **For anything this manual and `shelly-doctor` don't resolve**, the [issue tracker](https://github.com/RYOITABASHI/Shelly/issues) is the fallback — and the [Known Limitations](../README.md#known-limitations) section of the README documents every rough edge that's already known about, so it's worth a search there first. --- ## 9. Retro theme, realtime voice, and reaching Shelly from your PC A few newer features are worth a short walkthrough of their own. All four are opt-in and off by default. **Case File theme.** `Settings → Theme` now offers a fifth color preset, **Case File** — a cream-paper, black-hairline look modeled on old database-terminal UIs, distinct from the four neon presets. It pairs with an independent font picker (`Settings → Font`): **Default** or **DotGothic16**, a bitmap-style font, selectable no matter which color theme is active. Switching into Case File briefly flashes a pseudo-boot overlay and suspends any wallpaper you have set for as long as it's active. **Realtime voice.** `Settings → Realtime Voice` turns on a full-duplex voice mode, separate from the existing tap-to-record VoiceChat: once active, you can talk and get spoken replies back continuously, with the app handling interruptions the way a phone call would, instead of a strict record → transcribe → send → wait loop. It needs a Gemini API key configured (`Settings → API Keys`). One thing worth knowing before you turn it on: unlike Shelly's other Gemini usage, audio through this specific API is billed per token even on a free-tier key — text elsewhere in the app is unaffected. **Reaching Shelly from your PC (A2A / MCP).** Two more toggles, both under `Settings → Developer`, start a small local server on the phone that a tool on the same network can talk to: - **A2A Server** starts an [Agent2Agent protocol](https://a2a-protocol.org/) endpoint with one read-only skill, `list_agents` — useful if you're experimenting with other A2A-aware agent tooling and want them to see what Shelly has registered. - **MCP Server** starts a bearer-token-protected [Model Context Protocol](https://modelcontextprotocol.io/) endpoint with four read-only tools: `read_terminal_output`, `git_status`, `list_agents`, `list_repos`. This is the more immediately useful one if you develop Shelly itself from a PC — point Claude Code or Claude Desktop's MCP client at it and it can read your phone's terminal output and repo status directly. Turn the toggle on, then use `Settings → MCP Server → Copy Token` to get the bearer token, and configure your MCP client with `http://:8767/mcp` plus that token. Both are deliberately read-only for now — neither exposes a way to execute a command or write a file from outside the phone. That gate is a known, intentional scope limit, not an oversight; see [`docs/superpowers/DEFERRED.md`](superpowers/DEFERRED.md) if you want the reasoning. --- ## 10. Updating, security, and where the rest of the detail lives **Updating** happens from inside the app — the cloud-download icon in the top bar, or **Settings → Updates**. It reads a public release manifest, checks the SHA-256 of the downloaded APK before handing it to Android's installer, and Android will still ask you to confirm the install because Shelly is distributed outside the Play Store. It's a normal in-place Android app upgrade — your data and settings are untouched. The **Codex runtime updates separately from the app**, on its own release lane, so it isn't stuck waiting for the next full APK release. Shelly verifies a candidate runtime's hash and smoke-tests it (`--version`, `exec --help`) before promoting it to active. **Security, briefly:** Shelly is a normal Android app sandbox, not a hardened VM — terminal commands and approved AI-agent actions run as the app's own uid and can touch whatever the app can touch. API keys are stored through Expo's SecureStore, Keystore-encrypted where the device supports it, and are never written to logs. There's no telemetry — no analytics, no crash reporting, no usage tracking — though note that, while Profile Learning is enabled, messaging a cloud AI provider includes Shelly's on-device usage-pattern profile in that request to improve response quality. You can disable this with **Settings → Agents → Profile Learning**, or erase the learned profile with **Reset Profile**. The full picture is in [README → Security](../README.md#security) and [SECURITY.md](../SECURITY.md). Every capability described in this manual is one I use myself, and where it's incomplete or flaky, I've tried to say so plainly instead of rounding up. [`docs/superpowers/DEFERRED.md`](superpowers/DEFERRED.md) is the project's own running ledger of what's shipped, what's flag-gated off, and what's known-broken — when this manual hedges, that's where the hedge comes from. If something here still doesn't match what the app does, [open an issue](https://github.com/RYOITABASHI/Shelly/issues).