📱 Chat-first SSH runner for Android.
Read command output like a conversation, not a terminal wall.
Inspired by the UX feel of RikkaHub, built clean-room from scratch under Apache-2.0.
| Focus | What You Get |
|---|---|
| 💬 Readability-first UX | Command + output timeline, Markdown + code cards, streaming-friendly rendering |
| 🔐 Security-by-default | Known-hosts verification, mismatch warning flow, encrypted key storage |
| ⚡ Ops velocity | Copy / rerun / export session, profile-level shell and auth options |
| 🧠 Codex bridge | Remote codex exec --json --full-auto with tolerant JSONL parsing and progress summaries |
| 📈 Diagram rendering | Optional Mermaid detection, card rendering, and fallback path |
| 🌍 i18n | Chinese + English resources, Chinese-first UX wording |
| Domain | Status | Notes |
|---|---|---|
| Compose app shell | ✅ | Profiles, editor, chat session, settings, known hosts, about |
| SSH engine (Mode A) | ✅ | sshj exec, stdout/stderr/exit streaming, connection reuse |
| Auth chain | ✅ | Password, key, passphrase, PuTTY .ppk |
| Host key safety | ✅ | TOFU + mismatch warning + replacement confirmation |
| Codex integration | ✅ | Profile toggle, workdir, API key injection, JSONL events, thread/turn/item progress summary |
| Rendering pipeline | ✅ | Markdown + CodeCard + truncation/full-output affordances |
| Mermaid rendering | ✅ | Feature flag, segmented rendering, WebView card, retry + source fallback |
| CI quality gate | ✅ | Unit test + lint + assemble + artifacts + summary |
- Non-interactive SSH command execution (exec channel)
- Structured streaming into chat bubbles
- Day-to-day operator workflow (rerun, copy, share, export)
- PTY terminal emulation (
vim,top,htop, cursor control) - Default server-side HTTP command relay
- Fully autonomous remote action without explicit user command
:app -> Screens, Navigation, ViewModels, DI wiring
:core:model -> Domain models (profile, message, status)
:core:ssh -> SSH runner, JSONL parser, host key store interfaces, connection pool
:core:storage -> Room + DataStore persistence
:core:ui -> Reusable Compose components (bubble/code/markdown/input)
User command
-> ChatViewModel
-> SshExecRunner.run(profile, command)
-> Flow<ExecEvent>
-> stdout/stderr/structured/exit
-> message persistence + UI update
- JDK 17+
- Android SDK (target API 35)
- Gradle wrapper (included)
Windows note (if JAVA_HOME is missing):
$env:JAVA_HOME="C:\Path\To\JDK17"
$env:Path="$env:JAVA_HOME\bin;$env:Path"./gradlew test
./gradlew :app:lintDevDebug
./gradlew assembleDevDebugInstrumentation (requires device/emulator):
./gradlew :app:connectedDevDebugAndroidTestInstrumentation tips and emulator setup:
docs/testing-android-instrumentation.md
Debug APK output:
app/build/outputs/apk/dev/debug/app-dev-debug.apk
For fast local regression on current core paths:
./gradlew :core:storage:testDebugUnitTest :core:ssh:testDebugUnitTest :app:testDevDebugUnitTestFor UI-heavy regression before a release candidate:
./gradlew :app:testDevDebugUnitTest --tests "io.rikka.agent.ui.screen.HostKeyDialogsTest"
./gradlew :app:lintDevDebug :app:assembleDevDebug| Chat Session | Profile Editor | Settings |
|---|---|---|
Notes:
- Current gallery uses placeholder SVG assets generated from project visual direction.
- Replace with real screenshots before release tag.
- Create a profile in the editor (host/user/auth).
- Test SSH connection and trust host key fingerprint.
- Open chat session and run
uname -a. - Re-run, copy, export, and share output from action row.
- (Optional) Enable Codex mode for JSONL streaming tasks.
Q1: Why no interactive terminal mode?
Mode A intentionally focuses on exec-channel reliability and readable output. PTY is out of v1 scope.
Q2: Does RikkaAgent store private keys in plaintext?
No. App-managed keys are encrypted at rest via AndroidX Security Crypto.
Q3: Why does host key mismatch require confirmation?
To reduce MITM risk. Replacing trust should only happen after out-of-band verification.
Q4: Mermaid toggle is enabled but a diagram still falls back to source. Why?
Fallback is intentional when parsing or local rendering fails. The source block remains visible so the session stays readable and recoverable.
- CI validates unit tests, lint, and a dev debug APK on every PR.
- Dependabot monitors Gradle and GitHub Actions dependencies weekly.
- PR template is included for verification notes and rollback planning.
- Issue templates guide bug reports and feature requests with security-safe prompts.
Track execution details in ROADMAP.md.
| Milestone | Theme | Status |
|---|---|---|
| M0 | Spec freeze | ✅ Mostly complete |
| M1 | App core UX | ✅ Mostly complete |
| M2 | Rendering pipeline | ✅ Mostly complete |
| M3 | SSH engine | ✅ Mostly complete |
| M4 | Codex integration | ✅ Mostly complete |
| M5 | Release quality | ✅ Mostly complete |
- Private keys are encrypted at rest via AndroidX Security Crypto.
- Host key mismatch is treated as high-risk and requires explicit confirmation.
- Never commit secrets (keys, tokens, passphrases, real infrastructure identifiers).
Hardening references:
| Category | Entry |
|---|---|
| Spec index | docs/spec/00-index.md |
| Instrumentation testing | docs/testing-android-instrumentation.md |
| Verification checklist | docs/verification.md |
| Test mapping | docs/spec/71-test-mapping.md |
| Release acceptance | docs/spec/81-release-acceptance-matrix.md |
| Release checklist | docs/release-checklist.md |
| Troubleshooting | docs/troubleshooting.md |
| Glossary | docs/glossary.md |
| CI notes | docs/ci-notes.md |
| Architecture | docs/architecture.md |
| Product plan | docs/plan.md |
| i18n key audit | docs/i18n-key-audit.md |
| RikkaHub UX study (research) | docs/research/rikkahub-android-ui-study.md |
Before opening PRs, read:
Licensed under Apache-2.0.