
Smartphones are more powerful then ever, with processors rivaling old laptops. So let’s try to use them like a laptop to develop web-applications on the go. In this weeks blog post I’ll show you how to do use run and develop a CAP Java Spring Boot application on your smartphone and how to run VSCode locally to develop and modify it. This, of course, works only on Android phones, as they a Linux at their core.

Termux
We first need a proper Linux environment with a package manager and more. The most popular app that facilitates this is Termux:
Termux is an Android terminal emulator and Linux environment app that works directly with no rooting or setup required. A minimal base system is installed automatically – additional packages are available using the APT package manager.
TERMUX Website
Termux allows us to run Linux applications natively on device and use it to e.g. use OpenSSH to connect to another server, or interact with the Android filesystem using UNIX tools. Of course there are differences to other Linux distributions like Debian or Ubuntu, many of them stem from the fact that Termux wants to integrate directly into Android.
We have now two ways to go forward, we could
- Run everything directly in Termux
- Use an emulated Ubuntu in Termux
- Use the new Linux Terminal App
Develop Directly in Termux
We start by using pure Termux, as it’s faster and more integrated into Android than the second approach. But we’ll also see soon, why running in Ubuntu can have it’s benefits.
We start our pure Termux approach by installing our basic dependencies (and yes I like ohmyzsh and don’t want to miss it anywhere):
apt install git zsh wget htop sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
Now we want to install Java. Termux lacks the pthread library and a few others so simply getting the Linux aarch64 built of my favourite JDK, SapMachine, running on my phone seemed too much work, so I’m using OpenJDK which already available in the Termux packages.
apt install openjdk-21
Now we have a proper OpenJDK JVM running on our phone:

But developing code in shell tools like VIM is cumbersome, so we let’s install VSCode. The cool part about VSCode is that it consists of two parts, a backend and a front-end. We can run the backend in Termux and the front-end in the browser.
The official VSCode distribution doesn’t support Termux. But Code-Server by Coder is a fork/variant of VSCode that has support for running directly in Termux (via dev.to). It requires a few packages from the termux-user-repository and can be installed via:
apt install tur-repo apt update apt upgrade apt install build-essential python nodejs code-server
Now just start it:
nohup code-server --auth none &
This launches a local version and ignores the shell output. Code-server is by default password-protected, which is great. But we don’t need authentication as the device is in home WIFI where nobody from the outside can access it anyway. If for what-ever reason, you want to password protect it, then remove --auth none
and you’ll find the auto-generated password in $PREFIX/.config/code-server/config.yaml
.
Go to localhost:8080 to access it. Now we have a IDE, running locally directly on our device:

That was simple, wasn’t it? The only Problem: The official VSCode extensions and accessing the official VSCode market place is not supported, as code-server is a fork of VSCode:

You can still install the Java extensions from file by downloading the latest Linux arm64 release via wget from GitHub and then use “Install from VSIX” in the front-end, but this is cumbersome.
This is why I looked for other possibilities.
Use an Emulated Ubuntu
The problem with trying to run the official VSCode directly in Termux is that the Termux environment is too different from a normal Linux. Using proot we can emulate an Ubuntu environment and use it to install VSCode (dev.to) and even a proper SapMachine on our phone.
We’re especially interested in proot-distro. To quote the termux proot wiki page:
Termux provides a package proot-distro which takes care of management of the Linux distributions inside Termux.
TERMUX PROOT WIKI
This allows to easily install an Ubuntu on our phone, which looks a little bit like Windows Subsystem for Linux:
pkg install proot-distro proot-distro install ubuntu
Now you can login via the following to run as root and use the Termux home folder as home:
proot-distro login ubuntu --termux-home
Running in this environment is, as I told you before, slower than running directly in Termux. To quote a reddit user:
Proot is slower. It uses Linux debugging interface (ptrace) to control the process execution and hijack arguments and return values of system calls, so it can simulate a different file system layout and user/group ids. This cause a lot overhead. In my experience the biggest performance penalty can be observed when working with a lot of files (e.g. extracting tarball).
REDDIT
As before, we want install some basic utilities and ohmyzsh:
apt install git zsh wget htop sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
Now we can install SapMachine as explained in the SapMachine Wiki:
# Add the SapMachine GPG key wget -qO- https://dist.sapmachine.io/debian/sapmachine.key | tee /etc/apt/trusted.gpg.d/sapmachine.asc > /dev/null # Add the SapMachine repository echo "deb https://dist.sapmachine.io/debian/$(dpkg --print-architecture)/ ./" | tee /etc/apt/sources.list.d/sapmachine.list > /dev/null # Install SapMachine 21 apt update apt install sapmachine-21-jdk
Resulting in a proper JVM:

After that, we can install the official VSCode distribution:
wget 'https://code.visualstudio.com/sha/download?build=stable&os=linux-deb-arm64' -O code.deb apt install ./code.deb # Install the missing packages apt --fix-broken install rm code.deb
Installing the missing packages to around half an hour on my Pixel 8a.
Starting the VSCode backend is as easy as before with code-server:
nohup code serve-web --port 8080 --without-connection-token &
Now we have a proper official VSCode and can view it in the browser at localhost:8080:

In this we can install all the extensions we want and can start developing applications.
I would recommend to use “Add to Home screen” in your browser menu to create a VSCode web app on your home screen. This app then omits the browser menu bar, giving you more space to see your code.
SAP CAP SFlight
Let’s start running and developing our application. You can of course create any application to your hearts content and use either Termux or the emulated Ubuntu. But I’ll choose the latter and as a sample application the SAP CAP SFlight application.
CAP is the framework agnostic application framework of SAP for writing applications in Java and NodeJs and SFlight a simple sample application:
This is a sample app for the travel reference scenario, built with the SAP Cloud Application Programming Model (CAP) and SAP Fiori Elements.
The purpose of this sample app is to:
README of CAP-SFLIGHT
- Demonstrate SAP Fiori annotations
- Demonstrate and compare SAP Fiori features on various stacks (CAP Node.js, CAP Java SDK, ABAP)
- Run UI test suites on various stacks
I’m neither a CAP nor an SAP Fiori expert, but CAP is really important in the SAP context and can be used to write Java web applications. The initial idea for this whole blog post came out-of a discussion with the CAP Java folks (Robin de Silva Jayasinghe), which is why I’m choosing SFlight.
Building and Running SAP CAP SFlight
Let’s start by building SFlight on device. First we clone it:
mkdir code # some hygiene cd code git clone https://github.com/SAP-samples/cap-sflight cd cap-sflight # install the Maven build system and npm apt install maven npm
For those curious, this took:
# Emulated Ubuntu 3.22s user 2.05s system 81% cpu 6.457 total # Pure Termux 2.98s user 1.19s system 99% cpu 4.184 total # Mac M4 for reference 1.47s user 0.55s system 58% cpu 3.457 tota
Now we build and run it.
npm ci # NodeJS based CAP tools npm run build:ui mvn spring-boot:run
But the CAP tools run into a problem:

Seems like nobody prebuilt their npm packages from the Android arm64 target. And no, self-building all packages doesn’t work and even if. mvn spring-boot:run
, which uses the CAP’s NodeJS tools internally, crashes with a double free:

Because I still want to build SFlight on my phone, I need to get creative. The problem here are solely the CAP tools, not anything written in Java. So yes, you might call the following hacky, but this would be no problem in standard Spring Boot applications. It only means that you should be aware of the dependencies that your project needs, especially of natively compiled dependencies.
The Idea is: CAP Java generates database model helper classes and the UI using a complex toolchain, so let’s directly commit the files to GitHub from a machine that can run all tools (my MacBook) and push all into a seperate branch. Developing with this branch is fine, as long as you only modify the backend and don’t change the database schema.
Is it hacky? Yes. Is this a problem for a demo? No.
We add the new branch as follows:
git remote add fork https://github.com/parttimenerd/cap-sflight git pull fork git checkout cap-in-the-pocket
Now we can build and run the application again:
mvn spring-boot:run
It might exclaim that JAVA_HOME
is not set correctly, this can be remedied by
export JAVA_HOME=/usr/lib/jvm/sapmachine-21
You might want to add this to your .zshrc
to make it permament.
Do this
To access the most basic page of the app, visit localhost:4004

Or visit http://localhost:4004/travel_processor/dist/index.html to a proper page with which we can easily interact. When the website wants you to sign in, choose “privileged” as a user and an empty password.

Leading you to:

Modifying the Application via VSCode
We can use the VSCode instance that we launched before to access our SFlight project (nohup code serve-web --port 8080 --without-connection-token &
to start it again if you stopped yours) and work with the code:

Now let’s have some fun: The SFlight admin screens allows the privileged user to application deductions to the cost of a flight. We now introduce a small bug in the code that computes the discount in the DeductDiscountHandler
class to always calculate a ten times higher discount than requested. This might not make any sense, but the reverse (fixing this bug) is a nice demo of how one can use VSCode on their phone to fix a serious bug on the go.
The discount is computed in DeductDiscountHandler
as follows:
BigDecimal discount = BigDecimal.valueOf(context.percent()) .divide(BigDecimal.valueOf(100), new MathContext(3)); BigDecimal deductedBookingFee = travel.bookingFee() .subtract(travel.bookingFee().multiply(discount)) .round(new MathContext(3)); BigDecimal deductedTotalPrice = travel.totalPrice() .subtract(travel.totalPrice().multiply(discount));
We can now introduce the bug by dividing context.percent()
in the first two lines not by 100, but by 10.

When we rebuild and run the application via mvn spring-boot:run
, deducting 10% of the travel costs:

Decreases the price to 0 USD:

Nothing prevents us from using git to commit our change to some repo. This shows how we can easily modify our CAP/Spring-Boot application locally on our phone.
Android Linux Terminal
In March Google launched the native Linux Terminal app for Android on Google Pixel devices. Luckily the Android phone I use for all these tests is Pixel 8a which is one of the supported devices. The app offers essentially the same experience as the emulated Ubuntu in Termux:
The Terminal app operates by launching a Debian Linux environment within a virtual machine, powered by Android’s Virtualization Framework (AVF). Rather than exposing the underlying Android file system, it gives you an isolated Linux shell—much like what ChromeOS has offered developers and enthusiasts for years.
ikkaro.net
To enable it, you have to setup Developer Mode (by repeatedly clicking the Build Number in the settings) and activate the Linux Development Environment in the settings, as described at ikkaro.net.
But of course the app has limitations compared to Termux:
ikkaro.net
- Slow startup times: Booting the Terminal can take 10-20 seconds since it loads a full virtual machine (especially on mid-range hardware).
- Limited file system access: By default, you can only access your phone’s Downloads directory (via
cd /mnt/shared
), not the entire Android file system. For privacy and security, other folders remain off-limits. […]- Resource constraints: The VM’s allotted disk space is adjustable (from the Terminal app settings), but heavy use—like AI models or large database systems—can quickly fill storage.
One tiny but significant limitation is that the terminal app currently doesn’t support tabs, but this feature will apparently be available soon with Android 16. Overall the app feels far less stable than Termux (but supports pasting via external keyboard) and sometimes restarts the UI, clearing the terminal but killing the underlying user session. You should definitely adjust the disk space which is by default limited to 5GB which quickly fills up.
Let’s install the utitlities and SapMachine as before with the main difference that we’re not running as root by default:
# Install the utilities sudo apt update sudo apt install git zsh wget htop sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" su # change to root # Add the SapMachine GPG key wget -qO- https://dist.sapmachine.io/debian/sapmachine.key | tee /etc/apt/trusted.gpg.d/sapmachine.asc > /dev/null # Add the SapMachine repository echo "deb https://dist.sapmachine.io/debian/$(dpkg --print-architecture)/ ./" | tee /etc/apt/sources.list.d/sapmachine.list > /dev/null # Install SapMachine 21 apt update apt install sapmachine-21-jdk exit # exit root
And of course you should set JAVA_HOME
as before to prevent maven from complaining later.
We now have a SapMachine:

There are now technically two SapMachines and one OpenJDK installed on my tiny phone. Maybe I should install an OpenJ9 build just for good measure…
We install VSCode as before too:
wget 'https://code.visualstudio.com/sha/download?build=stable&os=linux-deb-arm64' -O code.deb sudo apt install ./code.deb # Install the missing packages sudo apt --fix-broken install rm code.deb
During the installation I got asked whether I want to add the Microsoft apt repository, having this prompt on my phone just looks funny:

Unsuprisingly, launching VSCode via nohup code serve-web --port 8080 --without-connection-token &
and then accessing the front-end via localhost:8080 works:

Now the thing you’re all waiting for: How long does a git clone take and do the CAP Java tools work in building the SFlight CAP app on this system?
Though first we have to update the NodeJS version (via nodejs.org): Report bug, that it contains “\.. source …” which doesn’t work
# Download and install nvm: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash # in lieu of restarting the shell . "$HOME/.nvm/nvm.sh" # Download and install Node.js: nvm install 22
Now we can run the commands as before:
mkdir code # some hygiene cd code git clone https://github.com/SAP-samples/cap-sflight # took: 3.58s user 1.52s system 109% cpu 4.643 total # which sits in between pure Termux and the emulated Ubuntu cd cap-sflight # install the Maven build system and npm sudo apt install maven npm ci # NodeJS based CAP tools npm run build:ui mvn spring-boot:run
And well, it worked… Which I find surprising. The UI of the new Linux Terminal App might be lacking and the partition size limit might be limiting, but I can build and run the stock CAP SFlight application without any changes.
Well it worked till I opened the browser and then the Linux Terminal App crashed. I’m happy that I documented everything. I tried it two times more. But this means that despite it’s apparent benefits, it’s basically unusuable for this specific use case for now.

Hopefully I can revisit this in a few months and it’s fixed.
Update: This terminal works much better with Android 16. It’s still flaky, but it can run a proper CAP build-pipeline and VSCode without any issues.
Extra: CAP-in-the-Pocket VSCode Extension
Switching between VSCode for editing and the shell for killing the previous SFlight server instance is too cumbersome for my demo. So I created the CAP-in-the-Pocket extension for VSCode:

To install it, download the extension from GitHub and open with the Termux app to make it available to VSCode. Then open the Extensions view in VSCode, click the “…” at the top of the Extensions view, select “Install from VSIX…” and select the downloaded file.
Please be aware that this extension is highly experimental and only created with the specific demo in mind.
The “(Re)Launch CAP App” button tries to kill the previous running instance and relaunches it:
(lsof -ti:4004 | xargs kill -9) || killall java || true mvn spring-boot:run
Did I say this extension is highly experimental?
Below the button, you see the output of the commands and links to the CAP application. By default I show buttons that open the two main views of SFlight. But you can configure it via the settings.json
file. The default configuration is equivalent to:
"cap-in-the-pocket.urlButtons": [ { "label": "Travel Processor", "url": "http://localhost:4004/travel_processor/dist/index.html" }, { "label": "Travel Analytics", "url": "http://localhost:4004/travel_analytics/dist/index.html" } ]
Creating this little plugin (with the help of Claude Sonnet and GitHub Copilot) allows me to have a more immersive demo.
Please be aware that you should only use the extension when you access VSCode in the normal browser, as opening links in the web-app added to the home-screen doesn’t work properly.
Conclusion
In this blog post, I showed you how to install and use VSCode and Java on your Android phone and develop applications, using three different options. Of course there a cloud-offerings that allow you to develop applications from mobile devices too, but I like the simplicity of running the web application directly on your phone, with full control. All of this is possible because Android phones use Linux as their base level operating system.
You could go even further and use the newly introduced Android Desktop Mode with an external screen, connect a keyboard and a mouse to your device and you come close to a basic Linux computer. And if you use the phone directly, you have a laptop with really good battery life, albeit not the best performance. It probably won’t become my daily Linux driver but to do coding when I’m on the go.
Thank you for joining me on this journey to learn how to develop your web applications on your phone and see in a few weeks for something (most probably) sched-ext related.
P.S.: This blog post is the foundation of my submission to SAP d-com Demo Jam.
P.P.S.: I tried compiling the OpenJDK on my phone but Termux killed the process and the Linux Terminal App ran out of disk memory.
This article is part of my work in the SapMachine team at SAP, making profiling and debugging easier for everyone. Thanks to Antje Luttenberger and Guilherme Dellagustin from the SAP OSPO for inspiring this work and Robin de Silva Jayasinghe from CAP Java for helping to setup SFlight and fixing bugs along the way.