GitHug Android
Native Android adaptation of the Ruby Githug learning game, built with Kotlin + Jetpack Compose. The product goal is a shippable mobile implementation that preserves GitHug's CLI-first learning style while making repository state easier to inspect on a phone.
Implementation Strategy
The app is organized around GitHug parity rather than simplified command quizzes:
- The level catalog follows the upstream Ruby Githug order from
Githug::Level::LEVELS. - Each exercise lives in its own Kotlin source file under
app/src/main/java/solutions/tretter/githugandroid/levels/. - Each level file documents the intended repository setup, evaluation strategy, hints, command suggestions, and embedded solution scenarios.
- Validators prefer repository state and Git objects over raw command text. Direct command-answer validation is reserved for upstream answer-style levels such as identifying a hash, filename, remote URL, author, or count.
- Shared tests execute the embedded solution scenarios for every level and assert that the Android catalog still matches the upstream level order.
- The runtime prepares an isolated sandbox per level and requires a bundled native Git binary for the device ABI. If no native Git binary is available, the app shows an unavailable-build message instead of starting a playable session.
The UI supports a terminal-centered workflow with optional inspection panes:
- CLI ONLY: hide visualization and play with terminal-style input.
- HYBRID: command line with optional repository panels.
- VISUAL: repository panels visible by default, still backed by the same command engine.
Development Workflow
Development tasks should be run through the project tooling script. It provisions the local toolchain, keeps paths project-relative, and runs Gradle with the project configuration expected by this repository.
Android project tooling
This repo includes a root-level tooling script:
bash ./AndroidProjectTooling.sh
It is designed to be idempotent and uses project-relative paths to:
- install a project-local JDK into
./jdk - install Android command-line tools into
./android-sdk - restore
gradle/wrapper/gradle-wrapper.jarif missing - install required Android SDK packages
- write
local.properties
Available commands:
| Command | Purpose | Output |
|---|---|---|
bash ./AndroidProjectTooling.sh |
Provision or refresh the local Android/JDK toolchain only. | Toolchain under ./jdk and ./android-sdk |
bash ./AndroidProjectTooling.sh --test |
Compile host Git, set GITHUG_TEST_GIT_BINARY, and run JVM unit tests. |
Test reports under app/build/reports/ |
bash ./AndroidProjectTooling.sh --build |
Build the debug APK. | app/build/outputs/apk/debug/githug-android-debug.apk |
bash ./AndroidProjectTooling.sh --build-release-aab |
Build the release Android App Bundle. | app/build/outputs/bundle/release/githug-android-release.aab |
bash ./AndroidProjectTooling.sh --compile-git |
Compile Git for the development host and all Android target ABIs. | Host and Android libgit.so binaries |
To run the JVM unit test suite after ensuring the local toolchain is ready:
bash ./AndroidProjectTooling.sh --test
To build installable/debuggable artifacts:
bash ./AndroidProjectTooling.sh --build
To build the release AAB intended for Play Store style distribution work:
bash ./AndroidProjectTooling.sh --build-release-aab
The script avoids depending on the system Java version by provisioning a project-local JDK 17, which is required by current Android SDK command-line tools.
To avoid repeated expensive SDK verification, the script writes a small state file named:
./.android-project-tooling.state
If all required components were verified successfully, the script will skip SDK verification/reinstallation for the next 24 hours unless required directories are missing.
When --build or --build-release-aab is used, the script also:
- increments
versionCodeby 1 - increments the patch component of
versionName, for example0.1.0to0.1.1 - bundles full Git manpage source files from Git's
Documentation/directory into app assets - renames the generated artifact to a stable
githug-android-*filename - attempts to create a git commit after a successful build if there are source changes
The build commands currently run these Gradle tasks:
--build:assembleDebug--build-release-aab:bundleRelease
Git Binary Compilation
Native Git compilation is integrated into the root tooling script:
bash ./AndroidProjectTooling.sh --compile-git
Options:
| Command | Purpose | Output |
|---|---|---|
bash ./AndroidProjectTooling.sh --test |
Ensure the host Git binary is current, then run tests with it. | build/host-git/libgit.so and test reports |
bash ./AndroidProjectTooling.sh --compile-git |
Ensure host Git and Android ABI Git binaries are current. | Host and Android outputs |
Android ABI outputs:
app/src/main/jniLibs/arm64-v8a/libgit.soapp/src/main/jniLibs/armeabi-v7a/libgit.soapp/src/main/jniLibs/x86/libgit.soapp/src/main/jniLibs/x86_64/libgit.so
The --test tooling command automatically builds host Git only when the Git source checkout has changed, then exports GITHUG_TEST_GIT_BINARY=build/host-git/libgit.so. This keeps JVM tests on the same GitRepositoryRuntime path as the app, including the packaged-runtime helper resolution behavior.
Git build outputs are stamped with a Git source fingerprint. Re-running --test or --compile-git reuses existing libgit.so binaries when the checked-out Git sources and target build flavor are unchanged.
Git manpage assets are also refreshed from the checked-out Git source whenever Git is compiled or an app artifact is built.
Runtime Architecture
The command engine has one app-facing runtime:
- Native Git path: the packaged executable for the device ABI runs Git commands in a real per-level repository sandbox in app-private storage.
The runtime exposes a RepoState surface to validators. In addition to files, commits, branches, tags, remotes, and config, the model tracks learning-relevant effects such as stashes, fetched remote refs, pushed branches/tags, submodules, and repository maintenance actions.
Helper shell-like commands (ls, pwd, cat, touch, mkdir, rm, echo, cd) remain implemented in Kotlin so the mobile terminal behaves consistently across devices.
Level Authoring
When adding or changing a level:
- Keep one source file per exercise.
- Keep
allGithugLevels()in upstream Ruby Githug order. - Document the setup and validation intent in the level file.
- Prefer validators that inspect
RepoStateover validators that match command strings. - Add multiple
LevelTestCasescenarios when more than one solution path should be accepted. - Run
bash ./AndroidProjectTooling.sh --testbefore building.
Production Focus
Current work is focused on:
- improving parity with upstream Ruby Githug setup and validation semantics
- expanding native-Git-backed behavior across complex repository workflows
- improving onboarding, accessibility, UI polish, icons, and Play Store readiness