Android Desktop mode (Android 17)

Tags:

Continuing my quest to using my Google Pixel 9 Pro Android phone as thin client in a docking station, with GrapheneOS build 2026062801, Android 17, previously Android 16.

Experience

With the 2026062801 build, you plug the phone into the docking station, select the display mode to extend the screen to the external display, and it just works. The mouse and keyboard input work anyway, and the phone asks you whether to connect the screen as a secondary display or to mirror the phone screen to the external display.

Improvements

The task bar on the external screen now works without alignment and mouse detection issues.

Opening an app to the big screen or moving it to the big screen now works by launching it from the big screen instead of mobile screen.

Opening the settings from the top pulldown menu on the external screen opens the settings on the small screen. Launching the settings app from the menu launches it on the external screen as it should.

Screenshot of screen settings

Screen dimensions can now be selected. Weirdly, on a 2560x1600 display, selecting 2560x1600 gave a crisp picture which still was constrained to a 1600x980 like screen with black bars to the left and right. I assume that the external DP alt mode has a limitation to 1600px width in data transfer. On my local 11" 4k display, the different resolutions top out at 2048x1152. This is acceptable for the size of the display, but I would still like to use a larger resolution.

Bluetooth audio output works, but the microphone remains mute.

Initially external cameras did not work inside the $work Citrix workspace app. They get shown by the app but don't show up in Teams. There was a permissions pop-up on the phone screen to allow the app access to the USB-connected external camera, after selecting the external camera in the Citrix app menu. Allowing that permission via the phone screen made the camera usable within MS Teams on the remote end. The camera resolution seemed to be degraded, but that's maybe due to the Logitech 920c camera having a subpar UVC implementation?

USB and Thunderbolt cables

The orders for the various USB-C / USB-C cables arrived since the last experiment, and the results vary, as seems to be expected with the new world of basically indistinguishable cabling we live in.

I ordered two Thunderbolt 5 120Gbps, 240W cables, one 0,5m length and one 1m length, with the "5" displayed on the connectors. I also ordered a "Compatible with Thunderbolt 5" cable by SUMPK.

The SUMPK cable has the mildly annoying disfeature that the display connection is not necessarily detected as 1600x900 , but sometimes only as 1280x720. I attribute this to the connection quality.

With the two Thunderbolt 5 "certified" cables, the display resolution gets up to 2048x1152 , but the external display still retains the DPI scaling, so the improvement in fidelity does not result in more information getting shown on the screen.

At least I now have a set of cables that are known good cables for the phone connection and I will bring such a cable with me for when I need to hook up the phone to a docking station.

In the end, the phone is now a workable brain to use as a remote desktop client with Android 17.

Setting up pi.dev with z.ai

Tags:

I'm not really happy with using Claude Code as my coding harness. Not that I have spent much time in the last three months using the slopmachines, but as the GLM subscription is already paid for and GLM 5.2 just came out, I'm revisiting coding harnesses other than Claude Code, and here is my setup for running pi.dev in a Podman container.

pi.dev running with GLM 5.1

Plugins

The agent now supports subagents and task lists via plugins. Obra's superpowers is indispensable to me.

Pi-subagents

I don't believe in large context or large agent conversations, so subagents are a must for me.

Pi-tasks

Maintaining a task list is also important to me.

Superpowers

The main thing I use for doing agent-driven development

Prerequisites

pi needs Nodejs 22+, so the container is based on Debian forky.

Containerfile for pi.dev

FROM docker.io/library/debian:forky-slim
# debian-forky-slim
RUN <<EOF
apt update

# Install our packages
DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get install -y npm perl build-essential imagemagick git apache2 wireguard wget curl cpanminus liblocal-lib-perl ripgrep

EOF

RUN <<EOF
# Install pi.dev
npm install -g --ignore-scripts @earendil-works/pi-coding-agent

mkdir /work

export HOME=/root

# 1. Install Superpowers, subagents and task-list plugins
pi install git:github.com/obra/superpowers
pi install npm:pi-subagents

# Create some directories that we want to mount from the outside
mkdir -p /root/.pi/agent/sessions/--work--/

EOF

ENTRYPOINT ["bash"]
CMD ["-i"]

Pi setup and configuration

API key

I created a separate API key via z.ai API keys, just in case the API key gets leaked due to a bad plugin.

Environment variables / login

Documentation from pi.dev providers:

Edit ~/.pi/auth.json:

{
  "zai": {
    "type": "api_key",
    "key": "your API key"
  }
}

Customization

Like all coding harnesses, pi.dev also uses a lot of blinking lights to keep the user entertained while they wait for tokens. I removed the background colors by editing ~/.pi/agent/settings.json:

{
    "theme": "transparent"
}

And adding transparent.json to ~/.pi/agent/themes/transparent.json:

{
    "$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
    "name": "transparent",
    "vars": {
            "cyan": "#00d7ff",
            "blue": "#5f87ff",
            "green": "#b5bd68",
            "red": "#cc6666",
            "yellow": "#ffff00",
            "gray": "#808080",
            "dimGray": "#666666",
            "darkGray": "#505050",
            "accent": "#8abeb7",
            "white": "#ffffff"
    },
    "colors": {
            "accent": "accent",
            "border": "blue",
            "borderAccent": "cyan",
            "borderMuted": "darkGray",
            "success": "green",
            "error": "red",
            "warning": "yellow",
            "muted": "gray",
            "dim": "dimGray",
            "text": "white",
            "thinkingText": "gray",

            "selectedBg": "",
            "userMessageBg": "",
            "userMessageText": "",
            "customMessageBg": "",
            "customMessageText": "",
            "customMessageLabel": "#9575cd",
            "toolPendingBg": "",
            "toolSuccessBg": "",
            "toolErrorBg": "",
            "toolTitle": "white",
            "toolOutput": "gray",

            "mdHeading": "#f0c674",
            "mdLink": "#81a2be",
            "mdLinkUrl": "dimGray",
            "mdCode": "accent",
            "mdCodeBlock": "green",
            "mdCodeBlockBorder": "gray",
            "mdQuote": "gray",
            "mdQuoteBorder": "gray",
            "mdHr": "gray",
            "mdListBullet": "accent",

            "toolDiffAdded": "green",
            "toolDiffRemoved": "red",
            "toolDiffContext": "gray",

            "syntaxComment": "#6A9955",
            "syntaxKeyword": "#569CD6",
            "syntaxFunction": "#DCDCAA",
            "syntaxVariable": "#9CDCFE",
            "syntaxString": "#CE9178",
            "syntaxNumber": "#B5CEA8",
            "syntaxType": "#4EC9B0",
            "syntaxOperator": "#D4D4D4",
            "syntaxPunctuation": "#D4D4D4",

            "thinkingOff": "darkGray",
            "thinkingMinimal": "#6e6e6e",
            "thinkingLow": "#5f87af",
            "thinkingMedium": "#81a2be",
            "thinkingHigh": "#b294bb",
            "thinkingXhigh": "#d183e8",

            "bashMode": "green"
    }
}

Recent Books

Tags:

Some short reviews of books that I recently read

Slow Gods (Claire North)

Quite good and entertaining. A space opera that follows a being that cannot be killed from a society of libertarian hyper-capitalism through other societies. The corporate-run society is shown quite imaginatively, with the protagonist trapped in its value system.

Some Desperate Glory

I really disliked the protagonist, so props to the author for writing some really unlikeable, trapped protagonist. Content-wise, the story follows the protagonist from a fascist rebel cell through several timelines until they find a timeline that they are happy with.

The book is actually very good, I finished it despite disliking the protagonist on every page in the first act.

The afterword lists interesting (non-fiction) book references the author used. Very interesting, ranging from how Fascism works, over how Scientology works, to the North Korean internal structure.

Steel Beach (John Varley)

John Varley died this year and I read some recommendations of his books. The most memorable quote about John Varley is by Isaac Asimov:

Long, long ago, when I was yet unpublished, I found myself talking with Isaac Asimov at I forget which convention, when John Varley cruised by, trailed by enthusiastic fans. Asimov gazed sadly after him and said, "Look at him. A decade ago, everybody was asking, 'Who is John Varley?' A decade from now, everybody will be asking, 'Who is Isaac Asimov?'" And that was John Varley's moment.

Steel Beach is set on a colonized moon after the destruction of the earth. It follows a reporter that is tasked by the de-facto ruling moon AI with finding out why the AI and the reporter are suicidal.

The book is quite entertaining and wittily written.

Press Enter (John Varley)

A quite interesting throwback to 1984 and the computers back then. The novella is about an investigation into a mysterious killing of what turns out to be a computer hacker.

The names of the persons are names of (then current) home computers. Otherwise, the novella isn't all that remarkable in retrospect but for 1984, it was quite prophetic.

Hawksbilll Station (???)

On the flip side of the "Press Enter" book, there was another short story of a prison set back in the Cambrian where political dissidents (and mostly, economists) get exiled to. Not really remarkable.

Starter Villain (John Scalzi)

Not as much science fiction. The novella revolves around a substitute teacher suddenly becoming head of a shadowy worldwide enterprise that provides services to governments that would otherwise be featured in James Bond movies. He and his intelligent cats need to outmaneuver rockets, dolphin unions and hired killers.

Entertaining as most of the John Scalzi books are.

More tools for note-selecting

Tags:

Sometimes I want to select a markdown note from the shell for further work. Maybe I want to launch an LLM with the note or I want to edit the note from within a terminal to fix some bug.

Since I've discovered fzf and its preview feature I find more and more uses for it. The following shell script shows all notes that contain a given label and offers them for selection:

#!/bin/bash

# Maybe we can even get tab completion here?!
LABEL=$1; shift

find ~/bin/App-notes-htmx/notes_corion/ -maxdepth 1 -name '*.markdown' -print0 \
  | xargs -0 grep -l -- " - $LABEL" \
  | perl -lpe 'BEGIN{$\="\0"; s!([\s/*?])!\\$1!g }' \
  | fzf --read0 --preview='cat {}'

Having not only a selection but also a custom preview makes things convenient. Perl was useful for properly escaping the filenames. fzf has the --read0 option, but it still passes the item to the shell without escapes. Using double quotes around the {} does not work.

Automating some file history with git snapshots

Tags:

My Note taking tool is part journal, part shopping list, part blog posts, part programs. Most notes get written once. Some get revised, some get posted or implemented. The tool is fully self-hosted and written by me, so I get to decide on its (lack of) features. For simplicity I avoided keeping a full note history. But then I realized that maybe some kind of history is actually nice, for the case when a wonky network failure erases or corrupts some note.

My solution for this feature is to simply snapshot the directory where I keep my notes every hour into a git repository. This gives me some change history, but it does not record every keystroke. The cron job is the following shell script:

SOURCE=/home/corion/bin/App-notes-htmx/notes_corion
TARGET=/home/corion/backup/notes_corion_history
if git --git-dir=$TARGET --work-tree $SOURCE diff --quiet; then
    git --git-dir=$TARGET --work-tree $SOURCE add  --all
    git --git-dir=$TARGET --work-tree $SOURCE commit -m "Hourly"
fi

I've "implemented" the tool as a shell script, but if I add more features, I will likely move it to Perl and use Git::Raw to do the adding/filtering/pruning myself. But then I would lose the convenience of .gitignore for example.

I still have on my list some kind of git history-prune, that coalesces adjacent git commits if they are too close, just to eliminate changes that don't matter anymore. Maybe after a month, compress all commits older than one month and less than 24 hours apart into a single commit.

I think having all changes of a single day in one commit is a sensible granularity for my use case.