<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Satyajit Pradhan: Notes from building</title><link>https://satyajiit.dev/writing/</link><description>Notes on product ideas and the systems behind them.</description><language>en</language><atom:link href="https://satyajiit.dev/feed.xml" rel="self" type="application/rss+xml"/><item><title>Giving AI an Android phone</title><link>https://satyajiit.dev/writing/giving-ai-an-android-phone/</link><guid>https://satyajiit.dev/writing/giving-ai-an-android-phone/</guid><pubDate>Mon, 14 Sep 2026 12:00:00 GMT</pubDate><dc:creator>Satyajit Pradhan</dc:creator><description>&lt;p&gt;Giving an AI agent access to an Android phone turns a conversation into a systems problem. The agent needs a way to observe the interface, request an action, and find out what changed. The person holding the phone needs to understand and control that access.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://satyajiit.dev/work/aster/&quot;&gt;Aster&lt;/a&gt; is the Android companion I built around that boundary. It is separate from &lt;a href=&quot;https://satyajiit.dev/work/openally/&quot;&gt;OpenAlly&lt;/a&gt;, the cross-platform AI product I’m building at Matterward Labs.&lt;/p&gt;
&lt;h2 id=&quot;a-request-is-not-an-outcome&quot;&gt;A request is not an outcome&lt;/h2&gt;
&lt;p&gt;An instruction such as “open that app” sounds complete in conversation. On a device, it is a request made against a particular state. The app may already be open. A dialog may be covering it. The screen may have changed since the agent last looked.&lt;/p&gt;
&lt;p&gt;I think of that interaction as a short loop: observe the available state, choose an action, then observe again. Treating an attempted action as proof of success would hide from both the agent and the person whether the action worked.&lt;/p&gt;
&lt;p&gt;This is a design principle I take from working across interfaces and systems. It does not require a model to be infallible. It requires the surrounding software to keep the difference between intention and evidence visible.&lt;/p&gt;
&lt;h2 id=&quot;give-the-device-layer-a-clear-job&quot;&gt;Give the device layer a clear job&lt;/h2&gt;
&lt;p&gt;Aster exposes Android capabilities to agents. I built it as an open-source project for the OpenClaw era, with connection options that do not require a second computer. The Android app can host its own Model Context Protocol server for clients that connect directly to the phone. OpenAlly’s native Android integration uses a separate Binder IPC path between apps on the same device.&lt;/p&gt;
&lt;p&gt;The on-device MCP server embeds Ktor and uses Streamable HTTP. Binder IPC avoids the network altogether, with token authentication and on-device approval. Aster also has an optional remote WebSocket mode through a separate server. The &lt;a href=&quot;https://github.com/satyajiit/aster-mcp&quot;&gt;Aster repository&lt;/a&gt; documents all three transports and their different tool catalogs; the project is MIT-licensed.&lt;/p&gt;
&lt;p&gt;A stable boundary is useful even when the interface on either side changes. The agent decides what it wants to attempt. The device layer decides which capabilities it exposes, under what permissions, and what result it can report. Those responsibilities should remain understandable independently.&lt;/p&gt;
&lt;h2 id=&quot;permission-belongs-in-the-experience&quot;&gt;Permission belongs in the experience&lt;/h2&gt;
&lt;p&gt;Android accessibility access is powerful because it can reach an interface rather than a narrow purpose-built API. A person needs an explicit way to approve access and stop it. Aster includes device approval and an on-device stop control.&lt;/p&gt;
&lt;p&gt;The design question is broader than whether a connection is technically possible. Can the person tell that control is active? Can they intervene when the agent is wrong? What happens if the connection is lost? These questions are useful requirements for any agent that acts outside its chat window.&lt;/p&gt;
&lt;h2 id=&quot;keep-platform-claims-precise&quot;&gt;Keep platform claims precise&lt;/h2&gt;
&lt;p&gt;Aster’s screen-control role is Android-specific. OpenAlly has a broader cross-platform scope. Combining those two descriptions into “an AI Android app” would lose the architecture and confuse what is available on another device.&lt;/p&gt;
&lt;p&gt;OpenAlly can share an agent runtime without promising identical device capabilities everywhere. I prefer to explain the shared job first, then identify which capability needs a particular platform.&lt;/p&gt;
&lt;h2 id=&quot;the-part-i-keep-returning-to&quot;&gt;The part I keep returning to&lt;/h2&gt;
&lt;p&gt;The interesting work is the connection between a useful intention and a dependable action. A model can suggest the next step; the product still has to manage state, permissions, and feedback.&lt;/p&gt;</description></item><item><title>Designing interactions around a laptop hinge</title><link>https://satyajiit.dev/writing/designing-around-a-hinge/</link><guid>https://satyajiit.dev/writing/designing-around-a-hinge/</guid><pubDate>Mon, 14 Sep 2026 12:00:00 GMT</pubDate><dc:creator>Satyajit Pradhan</dc:creator><description>&lt;p&gt;A laptop hinge is an unusually good invitation to think about interaction. It already moves for a reason. It has a physical range. And the person using it does not need to learn a new gesture.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://satyajiit.dev/work/unfoldmymac/&quot;&gt;UnfoldMyMac&lt;/a&gt; began around that possibility: connect desktop effects to the MacBook lid. The app now includes lid effects, dynamic wallpapers, and creative scenes, with a native Swift, AppKit, and Metal implementation.&lt;/p&gt;
&lt;h2 id=&quot;begin-with-the-physical-relationship&quot;&gt;Begin with the physical relationship&lt;/h2&gt;
&lt;p&gt;When an effect responds to a hinge, the relationship between movement and image matters more than an elaborate animation. If the lid moves a little, the visual response should make that movement understandable. If the lid stops, the effect should not seem to continue on an unrelated schedule.&lt;/p&gt;
&lt;p&gt;That is a different design problem from a timed transition. A transition has a beginning and an end chosen by software. A physical input can reverse halfway through, pause, or arrive in small, uneven updates. The visual system needs a meaningful state for all of those moments.&lt;/p&gt;
&lt;h2 id=&quot;a-useful-model-of-the-interaction&quot;&gt;A useful model of the interaction&lt;/h2&gt;
&lt;p&gt;I think about the experience in three parts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Input:&lt;/strong&gt; what movement or device state is available?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mapping:&lt;/strong&gt; how does that input become a position, amount, or visual parameter?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presentation:&lt;/strong&gt; how does the result appear without fighting the desktop?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Separating those questions makes the behaviour easier to reason about. A rendering change need not redefine the input. A different device capability need not mean inventing a new visual language.&lt;/p&gt;
&lt;p&gt;This is a design model, rather than a claim that every effect uses the same implementation. The &lt;a href=&quot;https://github.com/satyajiit/UnfoldMyMac&quot;&gt;UnfoldMyMac source&lt;/a&gt; has the details of the current native app.&lt;/p&gt;
&lt;h2 id=&quot;let-people-see-what-a-design-does&quot;&gt;Let people see what a design does&lt;/h2&gt;
&lt;p&gt;A still image explains appearance, but it does not explain an interaction. A person choosing a lid effect needs to understand the relationship to movement. A person choosing a wallpaper needs to know whether it reacts to a different input or behaves independently.&lt;/p&gt;
&lt;p&gt;So the UnfoldMyMac library has to show a preview and say what each effect responds to. The question is not simply “Do I like this picture?” It is also “Do I want my desktop to behave like this?”&lt;/p&gt;
&lt;h2 id=&quot;motion-has-a-lifecycle&quot;&gt;Motion has a lifecycle&lt;/h2&gt;
&lt;p&gt;A delightful effect is still a running system. It has resources to manage and moments when it is no longer visible. Its behaviour around closing, reopening, and changing context is part of the design.&lt;/p&gt;
&lt;p&gt;That concern carries into this portfolio. The machine has short responses to a person’s selection, and the page remains useful without them.&lt;/p&gt;
&lt;h2 id=&quot;follow-the-small-question&quot;&gt;Follow the small question&lt;/h2&gt;
&lt;p&gt;What interested me was noticing a control already present in the object, rather than adding another to a screen. Following that question led from a laptop hinge into native rendering and a collection of effects.&lt;/p&gt;</description></item></channel></rss>