While everyone is pushing the limits of AI, I've been busy pushing the limits of a Lenovo Duet Chromebook tablet I inherited from my son. He used it as a school tablet for a year, but eventually got frustrated with its performance under their heavy workload. The tablet comes with just 4GB of RAM, but as a Chromebook, it has the unique ability to run both Android and Linux software.
I've been trying to move to a portable, lightweight development machine for the past 5+ years. After experimenting with (and eventually giving up on) Android and Termux paired with a Bluetooth keyboard, I decided to give this Duet a serious shot. This article covers my journey optimizing this 4GB tablet into my primary development machine—one that I use both on the go as a tablet and docked via USB-C to a larger monitor, keyboard, and mouse.
The very first thing I did was disable the Android VM. I simply didn't have a use for Android apps on a dev setup. Disabling Android (ARC++) reclaims about 1GB of RAM immediately, which is a massive 25% gain on a 4GB device.
One minor hiccup: I briefly regretted this when it broke my Android-based Tailscale configuration. Luckily, I solved this by running Tailscale directly inside the Linux container using its userspace networking mode and SOCKS5 proxy:
tailscaled --tun=userspace-networking --socks5-server=localhost:1055
Next, I tweaked a specific set of ChromeOS flags to maximize memory savings, force GPU acceleration across both Chrome and the Linux container, and stop Chrome from wasting CPU cycles and RAM prefetching pages:
chrome://settings/performance
)#ignore-gpu-blocklist
→ Enabled#enable-gpu-rasterization
→ Enabled#enable-zero-copy
→ Enabled#crostini-gpu-support
→ Enabled#scheduler-configuration
→ Enables Hyper-Threading on relevant CPUs#enable-parallel-down
→ Enabled#prerender2
& #prerender2-cross-origin-iframes
→ DisabledChromeOS uses ZRAM (compressed memory swap). By default, Linux container swappiness is set higher than ideal, causing active terminal tools to get pushed into swap too early.
Ctrl
-
Alt -
T
) and expanded the ZRAM swap limit to 8GB to give the system plenty of breathing room during heavy multitasking:
swap enable 8192
/etc/sysctl.d/99-custom.conf
inside Linux and added:
vm.swappiness=20
vm.vfs_cache_pressure=150
vm.overcommit_memory=1
This keeps active CLI processes in physical RAM while allowing smooth swapping when under memory pressure.
Since I don't use Linux GUI apps or Linux audio, I wanted to strip out background overhead.
sommelier
sommelier
(the Wayland/X11 proxy display service), but the terminal crashed and Termina failed to start. In ChromeOS, sommelier
manages the host-to-container IPC sockets. sommelier
running!pipewire
and packagekit
, but they kept restarting. The trick in systemd
is that socket-activated services will automatically respawn whenever their socket is triggered. Using mask
instead of disable
permanently stops them:
systemctl --user stop pipewire.service pipewire-pulse.service wireplumber.service filter-chain.service pipewire.socket pipewire-pulse.socket 2>/dev/null
systemctl --user mask pipewire.service pipewire-pulse.service wireplumber.service filter-chain.service pipewire.socket pipewire-pulse.socket 2>/dev/null
sudo systemctl stop packagekit 2>/dev/null
sudo systemctl mask packagekit 2>/dev/null
After this round of optimizations, I can happily say that I'm using the Lenovo Duet as my primary development machine. It easily handles AI harnesses, terminal code editors (like Neovim/Micro), and web browsing.
If you prefer VS Code, I recommend running VS Code Server inside Linux and accessing the editor interface directly through the Chrome browser:
code serve-web
This gives you the full VS Code experience without incurring the heavy RAM overhead of the Linux GUI container stack!