openstf/stf
Control and manage Android devices from your browser.
Stale — last commit 3y ago
weakest axisnon-standard license (Other); last commit was 3y ago
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓12 active contributors
- ✓Other licensed
- ✓CI configured
- ✓Tests present
- ⚠Stale — last commit 3y ago
- ⚠Concentrated ownership — top contributor handles 53% of recent commits
- ⚠Non-standard license (Other) — review terms
What would change the summary?
- →Use as dependency Failing → Mixed if: clarify license terms
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Earn the “Healthy” badge
Current signals for openstf/stf are Mixed. The embed flow is reserved for repos showing Healthy signals — the rest stay informational on this page so we're not putting a public call-out on your README. Address the items in the What would change the summary? dropdown above, then return to grab the embed code.
Common quick wins: green CI on default branch, no Critical CVEs in dependencies, recent commits on the default branch, a permissive license, and a published README.md with a quickstart.
Onboarding doc
Onboarding: openstf/stf
Generated by RepoPilot · 2026-05-06 · Source
Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/openstf/stf shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
Verdict
WAIT — Stale — last commit 3y ago
- 12 active contributors
- Other licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 3y ago
- ⚠ Concentrated ownership — top contributor handles 53% of recent commits
- ⚠ Non-standard license (Other) — review terms
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live openstf/stf
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/openstf/stf.
What it runs against: a local clone of openstf/stf — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in openstf/stf | Confirms the artifact applies here, not a fork |
| 2 | License is still Other | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 1101 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of openstf/stf. If you don't
# have one yet, run these first:
#
# git clone https://github.com/openstf/stf.git
# cd stf
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of openstf/stf and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "openstf/stf(\\.git)?\\b" \\
&& ok "origin remote is openstf/stf" \\
|| miss "origin remote is not openstf/stf (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Other)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Other\"" package.json 2>/dev/null) \\
&& ok "license is Other" \\
|| miss "license drift — was Other at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "bin/stf" \\
&& ok "bin/stf" \\
|| miss "missing critical file: bin/stf"
test -f "lib/cli/index.js" \\
&& ok "lib/cli/index.js" \\
|| miss "missing critical file: lib/cli/index.js"
test -f "lib/db/index.js" \\
&& ok "lib/db/index.js" \\
|| miss "missing critical file: lib/db/index.js"
test -f "lib/db/setup.js" \\
&& ok "lib/db/setup.js" \\
|| miss "missing critical file: lib/db/setup.js"
test -f "gulpfile.js" \\
&& ok "gulpfile.js" \\
|| miss "missing critical file: gulpfile.js"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1101 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~1071d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/openstf/stf"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
TL;DR
STF (Smartphone Test Farm) is a web application that allows you to control and debug Android devices remotely through a browser interface. It connects to physical or emulated Android devices via ADB, streams live video/touch input to a web UI, and provides remote device management capabilities like installing APKs, capturing screenshots, and executing shell commands—enabling QA teams and developers to test on multiple devices simultaneously without physical proximity. Monolithic Node.js application with a clear separation: lib/cli/ contains the CLI entry point (bin/stf), lib/cli/api/ provides the REST API layer, and a browser-based frontend (likely in res/ based on logo path). The project uses Express for the web server, adbkit for ADB communication, and a mix of Passport strategies (SAML, OAuth2, OpenID) for authentication. Docker support via multiple Dockerfiles (including ARM variants) suggests deployment flexibility.
Who it's for
QA engineers, mobile app developers, and device lab administrators who need to test Android apps across multiple devices simultaneously. Originally built at CyberAgent for managing 160+ devices, now used by testing teams who want centralized remote device control without proprietary device cloud solutions. Currently deprecated but still used in production by organizations maintaining their own forks.
Maturity & risk
Production-ready but officially unmaintained as of v3.4.1 (last npm release). The codebase shows substantial maturity: 1M+ lines of JavaScript, Docker support, CI via Travis, and comprehensive CLI tooling. However, active development ceased ~2024; the project was archived and development moved to the DeviceFarmer organization. Use at your own risk for new projects; existing deployments remain stable.
Significant maintenance risk: the entire OpenSTF project is officially deprecated with a warning in the README directing users to DeviceFarmer. Dependencies are dated (Bluebird 2.10.1, Express 4.14, Passport 0.3.2) and likely have unpatched security vulnerabilities. Single-maintainer dependencies on adbkit (^2.11.1) and minicap-prebuilt-beta mean feature gaps in newer Android versions. Recommended only for maintaining existing installations, not new deployments.
Active areas of work
No active development. The repository is archived with a clear warning that active development has moved to DeviceFarmer (github.com/DeviceFarmer). The last release noted in package.json is v3.4.1; no recent commits visible in the file list. Maintenance mode only: expect no new features, security updates, or Android version compatibility improvements.
Get running
git clone https://github.com/openstf/stf.git
cd stf
npm install
bower install
npm test
Note: Requires Node version specified in .nvmrc and .tool-versions. The prepublish script will automatically run bower install && gulp build on npm install.
Daily commands:
npm install
gulp build
stf start
Or for Docker: docker run -d --name stf openstf/stf stf start --adb-host <host> --adb-port 5037. The CLI at bin/stf delegates to lib/cli/ commands. See doc/DEPLOYMENT.md for production setup (requires ADB daemon, multiple services, optional auth config).
Map of the codebase
bin/stf— Main CLI entry point—all contributors must understand how commands are routed and how the application bootstraps.lib/cli/index.js— Core CLI dispatcher that registers all subcommands (device, app, provider, processor, etc.)—essential for understanding command architecture.lib/db/index.js— Database abstraction layer using RethinkDB—critical for all data persistence and query patterns across the platform.lib/db/setup.js— Database schema initialization and migrations—required reading for understanding data model and backward compatibility.gulpfile.js— Build orchestration for assets, tests, and deployment artifacts—defines the entire development and production build pipeline.lib/cli/device/index.js— Device management subsystem—core feature for discovering, managing, and controlling Android devices via ADB.lib/cli/websocket/index.js— WebSocket server for real-time device communication with browsers—backbone of the remote control architecture.
How to make changes
Add a new authentication provider
- Create a new directory under lib/cli/auth-{provider} following the pattern of lib/cli/auth-oauth2/index.js (
lib/cli/auth-oauth2/index.js) - Implement the standard auth module interface with middleware and strategy exports (
lib/cli/auth-oauth2/index.js) - Register the new provider in lib/cli/app/index.js by importing and mounting it to the Express stack (
lib/cli/app/index.js) - Add CLI flag and option parser in lib/cli/please.js for auth configuration (
lib/cli/please.js) - Update documentation in doc/DEPLOYMENT.md with provider-specific configuration instructions (
doc/DEPLOYMENT.md)
Add a new device control command
- Create a new handler in lib/cli/device/index.js that wraps adbkit commands (e.g., shell, install, push) (
lib/cli/device/index.js) - Register the command via lib/cli/index.js subcommand registration with yargs (
lib/cli/index.js) - Wire the command through lib/cli/processor/index.js to translate device events and state updates (
lib/cli/processor/index.js) - Emit WebSocket messages from lib/cli/websocket/index.js to propagate changes to connected browsers (
lib/cli/websocket/index.js)
Add a new storage backend
- Create a new module at lib/cli/storage-{backend}/index.js following the API contract of lib/cli/storage-s3/index.js (
lib/cli/storage-s3/index.js) - Implement get(), put(), remove(), and list() methods for file operations (
lib/cli/storage-s3/index.js) - Register the backend in lib/cli/app/index.js with condition checks (e.g., if S3_ENABLED, use S3Backend) (
lib/cli/app/index.js) - Update DEPLOYMENT.md with backend-specific configuration variables and setup instructions (
doc/DEPLOYMENT.md)
Add a new notification service
- Create a new notifier module at lib/cli/notify-{service}/index.js following lib/cli/notify-slack/index.js pattern (
lib/cli/notify-slack/index.js) - Implement the notification interface with connect() and post() methods for event delivery (
lib/cli/notify-slack/index.js) - Subscribe to relevant RethinkDB table changes in lib/db/api.js or through event emitters (
lib/db/api.js) - Register the notifier in lib/cli/app/index.js and provide CLI flags in lib/cli/please.js (
lib/cli/please.js)
Why these technologies
- RethinkDB — Real-time database with change cursors enables live device state synchronization across multiple browser sessions without polling; native support for watches and joins simplifies multi-user concurrent access.
- adbkit (Node.js ADB library) — Pure JavaScript ADB implementation allows running on any platform without installing native Android SDK; event-driven interface fits Node.js async model for handling many concurrent device connections.
- WebSocket + reverse proxies (triproxy/poorxy) — WebSocket enables real-time screen streaming and input relay; reverse proxies decouple browser from device communication allowing horizontal scaling via load balancing.
- Express.js + modular auth/storage plugins — Lightweight web framework with middleware pattern allows swappable authentication (OAuth2, LDAP, SAML2) and storage backends (S3, local, temp) without recompilation.
Traps & gotchas
ADB daemon requirement: STF expects a running ADB daemon accessible at --adb-host/--adb-port; without it, device connection fails silently. Minicap/Minitouch prebuilts: Must match Android OS version on target devices; mismatches cause screenshot/touch failures with opaque error messages. Node version: .nvmrc specifies exact version; npm install may fail with mismatched major versions. Bower dependencies: The prepublish hook runs bower install automatically; if Bower registry is down, npm install blocks. Docker ARM build: The arm7l variant requires cross-compilation tools; standard Docker daemon may not support it without docker-buildx. Authentication state: CSRF tokens via csurf and cookie-session; deployments behind proxies must configure cookie-session secret and secure flags correctly or sessions will fail silently.
Architecture
Concepts to learn
- Android Debug Bridge (ADB) — STF's entire device control layer is built on ADB protocol communication via adbkit; understanding ADB commands (shell, install, logcat, input) is essential to debugging device integration issues
- Protocol Buffers (protobufjs) — Used for minicap and minitouch binary protocol parsing (screenshot/touch streaming); decoding these requires protobuf knowledge
- Server-Sent Events (EventEmitter3) — STF streams device state (screenshots, logs) to the browser via push events; eventemitter3 provides the pub/sub backbone for real-time updates
- Image Compression (jpeg-turbo, GraphicsMagick) — Screenshots are compressed to JPEG via libjpeg-turbo and resized via GraphicsMagick before streaming; poor compression settings cause bandwidth spikes and latency
- CSRF Protection (csurf) — STF uses Express CSRF middleware to prevent cross-site attacks on device control endpoints; required for secure API design in multi-user deployments
- HTTP Proxy (http-proxy) — STF proxies WebSocket and streaming connections to devices; understanding proxy behavior is critical for debugging latency and connection drops
- APK Signing & Manifest Parsing (adbkit-apkreader, jws) — STF validates APK signatures and reads AndroidManifest.xml to extract app metadata before installation; critical for security and app discovery features
Related repos
DeviceFarmer/stf— The active fork and successor to OpenSTF; where all development moved after v3.4.2; go here for bug fixes and new Android version supportopenstf/adbkit— The ADB protocol client library (adbkit npm package) maintained under OpenSTF; critical dependency for all device communication in STFNetflix/Falcor— Conceptual inspiration for real-time device state sync; not a direct dependency but relevant to understanding STF's streaming architectureappium/appium— Complementary mobile test automation tool; Appium tests often run against devices discovered and managed by STFandroid/platform_system_adb— The upstream Android Debug Bridge source; understanding ADB protocol (used by adbkit) requires knowledge of this AOSP component
PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for CLI authentication modules
The repo has multiple authentication strategies (LDAP, OAuth2, OpenID, SAML2, Mock) in lib/cli/auth-* directories but TESTING.md doesn't specify test coverage for these critical security modules. Given the project's production use cases, adding unit tests for auth flows would prevent regressions and security issues.
- [ ] Create test/unit/cli/auth/ directory structure mirroring lib/cli/auth-*
- [ ] Add tests for lib/cli/auth-ldap/index.js covering bind failures, user resolution, and edge cases
- [ ] Add tests for lib/cli/auth-oauth2/index.js covering token exchange and callback validation
- [ ] Add tests for lib/cli/auth-saml2/index.js covering assertion parsing and validation
- [ ] Update TESTING.md with instructions for running auth-specific tests
- [ ] Integrate new tests into gulpfile.js test task
Add integration tests for device management CLI commands
lib/cli/device/index.js and lib/cli/generate-fake-device/index.js handle core device operations, but there are no visible integration tests for device lifecycle (list, add, remove, status). Adding these tests would ensure device management reliability across releases.
- [ ] Create test/integration/device/ directory
- [ ] Add tests for device listing and filtering scenarios
- [ ] Add tests for device addition with various Android versions and configurations
- [ ] Add tests for device removal and cleanup
- [ ] Add tests for lib/cli/generate-fake-device/index.js to verify fake device generation
- [ ] Document integration test setup in TESTING.md (adb mock or emulator requirements)
Create GitHub Actions workflow for multi-platform Docker image builds
The repo has multiple Dockerfiles (standard, Debian armhf, x86_64, and armv7l variants) but relies on .travis.yml. Modern GitHub Actions would provide faster CI/CD, better integration with GitHub, and native multi-platform builds. This replaces the outdated Travis CI setup.
- [ ] Create .github/workflows/docker-build.yml for building standard Dockerfile on push/PR
- [ ] Add matrix builds in workflow for docker/armv7l/Dockerfile and Dockerfile-debian-x86_64
- [ ] Integrate Docker buildx for multi-platform (linux/amd64, linux/arm/v7) image generation
- [ ] Add workflow step to push images to Docker Hub on releases (with version tags)
- [ ] Update README.md with GitHub Actions badge and deprecation notice for Travis CI
- [ ] Add workflow to run 'npm test' (gulp test) before building images to catch failures early
Good first issues
- Add TypeScript type definitions for adbkit and adbkit-apkreader: The codebase is vanilla JS with no typing; create @types stubs or a .d.ts file in lib/ to reduce bugs and improve IDE support for device control logic.
- Expand doc/DEPLOYMENT.md with systemd service examples: The file exists but is sparse; add example .service files for stf-adb, stf-minicap, stf-minitouch daemons to match the docker/armv7l/*.service files already in the repo.
- Write integration tests for lib/cli/api/index.js: The REST API layer has no visible test coverage; create test/api.test.js using a mock ADB daemon to validate device list, screenshot, and APK install endpoints.
Top contributors
- @koral-- — 53 commits
- @denis99999 — 16 commits
- @sorccu — 9 commits
- @lukzeg — 8 commits
- @dependabot[bot] — 4 commits
Recent commits
2b96490— Update README.md (koral--)390e021— Update issue templates (koral--)6d4f793— Clarify deprecation notice (koral--)ad68823— Update README.md (koral--)3e1ec50— Fix changelog (koral--)866b726— Add changelog for 3.4.2 (#1235) (koral--)632d80f— Merge pull request #1229 from openstf/stf-service-apk (koral--)8665298— Update required STFService.apk (koral--)abaaa28— Merge pull request #1213 from att55/update-node-sass-4.13.1 (koral--)e642f25— update node-sass v4.13.1 (att55)
Security observations
- Critical · Outdated and Vulnerable Dependencies —
package.json - dependencies section. Multiple dependencies are significantly outdated with known security vulnerabilities. Key concerns include: express (4.14.0 from 2016), passport (0.3.2), body-parser (1.13.3), and request (2.67.0). These versions contain publicly disclosed CVEs including prototype pollution, denial of service, and authentication bypass vulnerabilities. Fix: Update all dependencies to their latest stable versions. Minimum critical updates: express to ^4.18.0+, request to a maintained alternative or migrate to native fetch/axios, passport to ^0.6.0+, and audit remaining dependencies using 'npm audit' and 'npm audit fix'. - High · Insecure Authentication Libraries —
package.json - passport-saml, passport-oauth2, openid dependencies. The project uses outdated authentication libraries (passport-oauth2 ^1.1.2, passport-saml ^0.15.0, openid ^2.0.1) with known vulnerabilities. SAML library version 0.15.0 is from 2016 and contains XML External Entity (XXE) vulnerabilities and other SAML-specific attacks. Fix: Upgrade passport-saml to ^1.2.0+, passport-oauth2 to ^1.7.0+. Review SAML implementation for XXE protection. Consider using modern alternatives like 'node-saml' or '@boxyhq/saml-jackson'. - High · Insecure HTTP Client Library —
package.json - request dependency. The 'request' module (^2.67.0) is deprecated and unmaintained since 2020, with multiple unpatched security vulnerabilities including Server-Side Request Forgery (SSRF) and improper certificate validation issues. Fix: Replace 'request' with modern alternatives: 'axios', 'node-fetch', or native 'fetch' API. Ensure all HTTP calls validate SSL certificates and implement proper timeout and request size limits. - High · Exposed Service Port in Docker —
Dockerfile - EXPOSE 3000. The Dockerfile exposes port 3000 without restriction. Combined with the embedded nature of STF (remote device control), this could allow unauthorized access to device control interfaces if deployed without proper network segmentation. Fix: Implement proper network policies: 1) Only expose port 3000 to internal networks, 2) Use reverse proxy with authentication, 3) Implement rate limiting and WAF rules, 4) Document and enforce network segmentation requirements. - High · Insecure Cookie Session Configuration —
package.json - cookie-session dependency. The 'cookie-session' package (^2.0.0-alpha.1) is an alpha version from 2015. It lacks secure default cookie settings and modern security headers. No evidence of secure cookie flags (HttpOnly, Secure, SameSite) in visible configuration. Fix: Update to a stable version (express-session with secure store). Implement secure cookie flags: HttpOnly=true, Secure=true (HTTPS only), SameSite=Strict. Add security headers middleware (helmet). - High · Missing Security Headers Middleware —
package.json - dependencies (missing). No 'helmet' or equivalent security headers middleware is present in dependencies. STF lacks protection against clickjacking, MIME sniffing, XSS, and other header-based attacks. Fix: Add and configure 'helmet' package (npm install helmet). Implement it early in the Express middleware chain to set security headers: CSP, X-Frame-Options, X-Content-Type-Options, Strict-Transport-Security. - Medium · CSRF Protection Present but Outdated —
package.json - csurf dependency. The 'csurf' package (^1.7.0) is from 2015 and relies on deprecated Express practices. While present, it may not be properly configured across all endpoints. Fix: Update csurf to latest version. Audit all form submissions and state-changing operations to ensure CSRF tokens are properly validated. Consider alternatives like 'csrf-csrf' for more modern implementations. - Medium · Insufficient Input Validation —
undefined. Express-validator (^2.20 Fix: undefined
LLM-derived; treat as a starting point, not a security audit.
Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.