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:

  1. 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 with Makefile and assets in app/, using stubs for JSR-75 PIM APIs in app/stubs/.
  1. 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.java initializes 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.java and Cal.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.go starts the HTTP server and sets up routes.
  • Key Components:
  • claude.go: Interfaces with the Claude API via protocol.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.java and ChatCanvas.java.
  • Calendar/to-do items are parsed from Claude's responses and exposed via Cal.java and Pim.java.

How To Use It

Setup

  1. Build the Client: ``sh cd app make ` Outputs a .jar file (e.g., claude-s40.jar`) for deployment to the phone.
  1. 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

  1. Install the .jar on the Nokia phone.
  2. Run the server and ensure it's reachable from the phone (via local network or internet).
  3. 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, and Setup.java (max indentation depth 8).
  • Oversized files: ChatCanvas.java (1,339 lines), ChatSession.java, and ClaudeS40MIDlet.java.
  • Medium Severity (26 issues):
  • File opened without context manager in check.py and promo.py.
  • Duplicated code blocks across 6 files (6-line blocks repeated 6 times).
  • High branching density in Cal.java, ChatList.java, and Text.java.
  • Low Severity (1 issue):
  • 3 unresolved TODO markers in Cal.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.