ai newsFr., 23. Okt.
Eilmeldung馃毃 Anthropic Just Dropped "Claude Duet" and It's the Most Proactive AI Yet (Here's How It Works)

Claude on a Nokia 3310: a J2ME client, HMAC instead of TLS, and 41 bundled games

I wrote VibeNokia: a Java ME client for the 2017 Nokia 3310 feature phone that turns it into a chat terminal for Claude, plus a small FastAPI server that stores history, verifies signatures and runs claude -p . The menu also has Telegram, voice messages and a catalogue of 41 mini games. It works on

dev.toFreitag 03:42 路 23.10.6 Min. Lesezeit
Bild: dev.to

I wrote VibeNokia: a Java ME client for the 2017 Nokia 3310 feature phone that turns it into a chat terminal for Claude, plus a small FastAPI server that stores history, verifies signatures and runs claude -p. The menu also has Telegram, voice messages and a catalogue of 41 mini games. It works on my physical phone, and along the way I had to re-solve several things that a smartphone gets from a one-line library call.

A caveat up front: the client has been tested on one real Nokia 3310 (TA-1030). I haven't tried other Series 30+ or Series 40 phones. The channel between the phone and the server is not encrypted; more on that below, without softening it.

The 2017 Nokia 3310 is Series 30+ on a MediaTek MT6260. It runs Java ME with CLDC 1.1 / MIDP 2.0, has a 240x320 screen, mobile data only and no Wi-Fi. It has no usable browser and no app store. A plain HttpConnection with POST and JSON does work (I've seen this on my device), and the battery lasts a week.

So the design is thin: the phone runs a client that draws the screen and sends requests, and my server does all the heavy work. The app installs as a.jad/.jar pair from the memory card, or over the air: the server itself serves the files at /ota/VibeNokia.jad.

docs/platform-notes.md collects observations I wish I'd had before starting. The ones that cost me time:

This is where I hit a wall. According to public sources, the Java stack in these phones stops at old TLS versions and an old certificate store, so modern HTTPS URLs don't open. In my notes this is marked "reported": I did not deliberately re-verify it on my own device. The outcome for the project is the same either way: the client uses plain HTTP.

That means you can't rely on channel secrecy, so the app is built not to depend on it. Hence signed requests.

The phone is paired with the server once and receives its own key. After that the key never crosses the network. Every request carries an HMAC-SHA256 computed over:

The server checks the signature and the counter. A replayed request is dropped: a window of the 64 most recent counters works like the sliding window in IPsec. The signature includes the server address ( VIBENOKIA_PUBLIC_HOST ), so a request signed for a different address is rejected. Repeated wrong signatures or codes get the source banned for 15 minutes.

Pairing works like this. Set VIBENOKIA_PAIRING=1 in.env. Press 5 on the phone, and the server writes a one-time six-digit code to data/pair_code.txt (mode 600); if a Telegram token and my chat are configured, the code is also sent there. The code lives for 10 minutes and works once. You type it on the phone, the device gets its key and stores it. Then you set VIBENOKIA_PAIRING=0 and the /pair/* paths answer 404. A phone can be revoked locally with tools/devices.py against the database file; there is deliberately no network admin API.

Signing protects against forgery, guessing and replay. It does not protect against eavesdropping at all. Anyone on the path between the phone and the server can read your questions and Claude's answers. Don't send anything secret from this phone. I say this in the README and in the deployment docs and repeat it here, because it's worse when people discover such things themselves.

The server is Python with FastAPI and SQLite: sessions, devices and contacts live in one file. To answer, it runs claude -p with a short system prompt written for a tiny screen. What matters:

Before opening the port, the docs have a short check: ss -ltn | grep -v 127.0.0.1 should show only the proxy port, and curl against /ping and /api/chat without a signature should return 403 and never 200.

The first version opened with every feature at once. In the second (v0.2.0) the app starts with a simple menu of two tiles: chat with Claude, and Settings. Everything else (Telegram, voice, sessions, a second tile for OpenCode, and the "advanced" group: server list, in-app update, key rotation) is switched on in Settings > Features. The choice is kept in the phone's RMS storage. The server-side ceiling is applied on top: a feature the server forbids is hidden in the app, and the list arrives in the /ping reply. Upgrading from an older version keeps everything that was visible before, while a fresh install starts simple.

Always available: chat, model choice (Opus, Sonnet or Haiku), new chat, language (Russian or English) and font size. Tiles are numbered in the order shown, the digit opens a tile, and 5 opens the selected one. Hold * to dictate: the recording goes to the server, is transcribed there (Gemini via OpenRouter, Groq Whisper as a fallback) and lands in the chat.

The screenshots are from MicroEmulator at 240x320.

The catalogue has 41 standalone apps with no permissions and no network. Nine were written in this repository; the other 32 are MIT-licensed games from the agneay/j2me-100-games archive. Third-party components are listed in THIRD_PARTY_NOTICES.md. One script, scripts/build-games.sh, builds them all.

You need Docker with Compose, make, and either a Claude API key or a Claude Code login:

git clone https://github.com/meshoklv/vibenokia && cd vibenokia./scripts/quickstart.sh # creates.env with a fresh key and starts the server on 127.0.0.1:8085 make -C client SERVER_URL = http://your.host:8080 # -> client/dist/VibeNokia.jar + VibeNokia.jad./scripts/build-games.sh # optional -> games/dist/ Enter fullscreen mode Exit fullscreen mode The client builds inside a public Docker image with a J2ME toolchain. Install VibeNokia.jad from the memory card, then pair with a code as described above. Without Docker the server runs with scripts/run-local.sh; you then need Python 3.10+, ffmpeg for voice and claude on PATH.

Tested: the client on a real Nokia 3310. For this release the client and all 41 games build in the J2ME container, and I drove the new menu and Features screen by hand in MicroEmulator (the screenshots come from there). The server image builds and answers 403 on loopback without auth, and pairing plus signed chat were exercised end to end with the phone emulator and a stub in place of claude.

Not tested: a real Claude call inside the published Docker image, other Series 30+ and 40 phones, and a TLS front together with the phone. Planned: prebuilt.jar files in releases and per-device tool allow-lists.

Part of the code was written together with an AI assistant (Claude); the commit history shows this through a Co-Authored-By line.

Repository: github.com/meshoklv/vibenokia, MIT license. Issues and PRs are open; the rules are in CONTRIBUTING.md. If you have another J2ME phone and try it, tell me what happened. I post notes on Telegram at t.me/meshoklv.

Quelle: dev.to (dev.to). Original 枚ffnen