The Problem
2007-era Nokia S40 phones (Java ME, CLDC 1.1/MIDP 2.0) can no longer search the modern web. This project bridges that gap by bringing Claude's AI capabilities to these legacy devices, enabling text-based interactions, web search, calendar integration, and moreāall within the constraints of a 240x320 pixel screen and a numeric keypad.
What This Does
claude-s40 is a two-part system:
- J2ME Client (
app/): - A Java MIDlet that runs on Nokia S40 phones, providing a full-featured Claude client. - Features include chat bubbles, typing indicators, reading mode, message actions, and calendar/to-do integration. - Built withMakefileand assets inapp/, using stubs for JSR-75 PIM APIs inapp/stubs/.
- Go Server (
server/): - A lightweight Go server (server/main.go) that mediates between the phone and the Claude API. - Handles pairing, request limits, and chat history via SQLite (server/store.go). - Deployable via Docker (server/Dockerfile) and configurable via.env(server/.env.example).
The project also includes tools for emulation testing (app/emu/) and deployment scripts (server/deploy/).
How It Is Wired
Client Flow (J2ME)
- Entry Point:
ClaudeS40MIDlet.javainitializes the app and sets up the UI. - Key Components:
ChatCanvas.java: Renders chat bubbles and handles user input.ChatSession.java: Manages active chat sessions and interactions with the server.Setup.java: Handles first-run configuration and pairing with the server.CalendarForm.javaandCal.java: Bridge Claude's responses to the phone's calendar via JSR-75 PIM APIs.
Control flows through these classes to handle UI events, network requests, and local storage (e.g., chat history in ChatStore.java).
Server Flow (Go)
- Entry Point:
main.gostarts the HTTP server and sets up routes. - Key Components:
claude.go: Interfaces with the Claude API viaprotocol.go.store.go: Manages SQLite storage for chats and device metadata.sanitize.go: Pre-processes messages before sending to Claude (e.g., truncation).
The server uses a simple protocol (protocol.go) for communication with the phone, handling requests asynchronously.
Integration
- The phone sends messages to the server via HTTP, which forwards them to Claude.
- Responses are sanitized, formatted, and sent back to the phone. The phone renders them using
Text.javaandChatCanvas.java. - Calendar/to-do items are parsed from Claude's responses and exposed via
Cal.javaandPim.java.
How To Use It
Setup
- Build the Client: ``
sh cd app make`Outputs a.jarfile (e.g.,claude-s40.jar`) for deployment to the phone.
- Run the Server: - Configure environment variables via
server/.env(copy.env.example). - Build and run the Docker container: ``sh cd server docker-compose up -d`- Alternatively, build and run the Go binary directly:`sh go build -o server ./server``
Configuration
- Client: Configure the server URL in
app/app.properties(e.g.,SERVER_URL=https://example.com). - Server: Set Claude API keys and rate limits in
.env(e.g.,CLAUDE_API_KEY=your-key).
Running It
- Install the
.jaron the Nokia phone. - Run the server and ensure it's reachable from the phone (via local network or internet).
- Open the app on the phone, pair with the server, and start chatting.
Real-World Use
A user with a Nokia 6300 can:
- Type a message like "What's the weather in Istanbul?" using the numeric keypad.
- Receive a formatted response from Claude, including a weather summary and source attribution.
- Save the response to the phone's memory card or add a calendar entry directly from the response.
- Switch between chats, pin important ones, and search past conversations.
Code Health & Issues
Measured Findings
- High Severity (4 issues):
- Deep nesting in
ClaudeS40MIDlet.java,Pairing.java, andSetup.java(max indentation depth 8). - Oversized files:
ChatCanvas.java(1,339 lines),ChatSession.java, andClaudeS40MIDlet.java. - Medium Severity (26 issues):
- File opened without context manager in
check.pyandpromo.py. - Duplicated code blocks across 6 files (6-line blocks repeated 6 times).
- High branching density in
Cal.java,ChatList.java, andText.java. - Low Severity (1 issue):
- 3 unresolved
TODOmarkers inCal.java.
Other Observations
- Dependency Management: Uses Go modules (
server/go.mod) and J2ME stubs (app/stubs/). - Testing: Limited to 2 test files (
server/server_test.go). - Documentation: Comprehensive in
docs/(13 files) but lacks inline documentation for key functions.
The Bottom Line
claude-s40 is a well-structured, functional solution for bringing modern AI to legacy devices. The codebase is clean but has some maintenance debts (e.g., oversized files, deep nesting). The server is lightweight and deployable via Docker, while the client handles the constraints of J2ME well. Suitable for hobbyists or those with a nostalgia for Nokia phones.