- Kotlin 99.5%
- Python 0.2%
- Shell 0.2%
- Java 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
ci/woodpecker/push/compliance Pipeline was successful
ci/woodpecker/push/quality Pipeline was successful
ci/woodpecker/push/draft-release Pipeline was successful
ci/woodpecker/tag/release Pipeline was successful
ci/woodpecker/cron/renovate Pipeline was successful
Forgejo parses only the first issue reference in a commit trailer, so a comma-separated list closes the first and silently leaves the rest open. |
||
| .woodpecker | ||
| app | ||
| authoring | ||
| catalog | ||
| contract | ||
| design-system | ||
| docs | ||
| engine | ||
| gradle/wrapper | ||
| persistence | ||
| platform | ||
| scripts | ||
| .gitignore | ||
| .taskrc.yml | ||
| AGENTS.md | ||
| build.gradle.kts | ||
| CLAUDE.md | ||
| DESIGN.md | ||
| ENGINE.md | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| mise.toml | ||
| PRODUCT.md | ||
| README.md | ||
| renovate.json | ||
| settings.gradle.kts | ||
| Taskfile.yml | ||
Macros
Android automation you can read from top to bottom.
Macros is a native Android app for building personal automations as clear, inspectable routes. A route starts with one or more triggers, passes records through actions and control flow, and keeps enough history to explain what happened afterward.
It is under active development. The editor and execution engine are already useful, but the project is not presenting itself as a finished consumer product yet. “Macros” is also still a working name.
What can it automate?
A workflow can begin from the app, a Quick Settings tile, a cron-style schedule, an external app, or Android events such as:
- an SMS arriving;
- the screen turning on or off;
- the device being unlocked;
- Wi-Fi, power, battery, audio-route, or Do Not Disturb changes.
From there, it can transform text, inspect device state, make an HTTPS request, run JavaScript, show a notification, vibrate the device, open a URL, send an SMS, wait, or branch with a Switch.
For example, the route above reads the current battery state and sends each record through Running low, Charging, or Otherwise. Branches remain visible in the editor instead of disappearing into a configuration screen.
The shape of a workflow
Trigger Action Control flow Outcome
Run manually ───▶ Get battery status ───▶ Switch ── Running low ─▶ Show notification
├─ Charging ────▶ Show notification
└─ Otherwise ───▶ Show notification
Macros uses a typed dataflow graph underneath this phone-friendly route view. Nodes have versioned contracts, named ports, and JSON Schema inputs and outputs. Values can be fixed, taken from the starting event, selected from an earlier action, interpolated, or written as an expression.
That gives the editor enough information to offer real output fields and reject obvious type mismatches without reducing advanced workflows to a form builder.
Useful parts already in place
Authoring
- Multiple saved workflows with search, duplication, deletion, and direct test runs
- Shared searchable catalogs for actions, triggers, and named event sources
- Schema-generated input controls and an earlier-output picker
- Visible Switch branches with first-match or all-match routing and a fallback
- Per-node evaluation using manual input or data retained from an earlier run
- A Compose-native JavaScript editor with schema-aware completions
Android integration
- One honest, manifest-backed Quick Settings tile slot with a user-defined name
- Named schedules using Android alarms rather than a permanently running process
- Durable Android event delivery through a SQLite inbox
- Explicit-broadcast contracts for events published by other apps
- Reconciliation after app launch, package replacement, and device boot
- A background-resources screen showing what the app has registered and why
Execution and recovery
- Durable runs, history, cancellation, and failure context
Wait untilandWait for eventcheckpoints that survive process death- Deduplicated event delivery and leased continuation claims
- Default-on runaway-loop protection, configurable per workflow
- Optional, bounded run-data capture for debugging
JavaScript without handing scripts your phone
Run JavaScript receives a list of JSON values and returns a list of JSON objects:
return inputs
.filter(input => input.enabled)
.map(input => ({ result: input.text.toUpperCase() }));
Returning [] filters records; returning more records fans out. Declared output fields become selectable by later nodes.
Rhino runs interpreted in a dedicated Android isolated process. Scripts receive only their explicit JSON input: no Android/Java bridge, app files, package imports, network access, or app permissions. Input and output cross the process boundary through bounded anonymous file descriptors, and the worker has cancellation, size, and time limits.
Safety and privacy
Automation apps sit close to personal data and device capabilities, so the project treats those boundaries as part of the workflow rather than incidental plumbing.
- External intents and broadcasts are validated before entering the event gateway.
- Package allowlists fail closed where Android cannot verify the sender.
- HTTP is HTTPS-only, with redirects, retries, cookies, and implicit authentication disabled.
- Full run-data capture is off by default and warns that retained inputs may contain credentials or personal data.
- JavaScript is isolated from the app UID and Android permissions.
- The app has no persistent idle service; active background resources are derived from saved workflows.
Macros is intended to remain F-Droid compatible. It uses Android platform facilities and open-source dependencies rather than proprietary push or analytics services.
Try it
The app supports Android 8.0 (API 26) and newer. Check the Forgejo releases for available APKs. Release artifacts are currently unsigned, so Android will not treat them like a store-installed build.
To build locally, install the pinned tools and use the same quality entry points as CI:
mise install
task build
task test
task lint
The app APK is written to app/build/outputs/apk/debug/app-debug.apk.
task ci:quality runs the complete build, JVM test, and Android lint gate. Device-only isolated-worker lifecycle tests require a connected emulator or phone:
./gradlew :app:connectedDebugAndroidTest
Building in Termux
The local SDK is expected at $HOME/android-sdk, with Android 36 and Termux-native build tools installed. When $PREFIX/bin/aapt2 exists, the Gradle wrapper selects it automatically; desktop Android Studio continues to use the normal Maven-provided toolchain.
For contributors
The repository is split by responsibility rather than by Android screen:
app/— product UI, workflow engine, persistence, and Android adaptersdesign-system/— reusable Compose tokens and model-free componentscatalog/— internal component catalog; never shipped as a release artifactENGINE.md— execution model, durability, events, and extension boundariesDESIGN.md— the “Pocket Routebook” interaction and visual systemPRODUCT.md— product intent, constraints, and principles
Android callbacks are adapters over the shared event gateway; they do not invoke workflows directly. Built-in and future contributed actions use the same registry seam. Third-party implementations are intended to run out of process rather than loading arbitrary code into the app.
Planned work and design decisions live in Forgejo issues. If you are considering a change, that is the best place to see current constraints and avoid building a second mechanism beside an existing one.