Developer Documentation

Build on Neuraglass

Neuraglass runs on Stack OS. Use standard Android APIs to access hardware: keys, camera, microphone, and speaker. If you've built for Android, you already know how to build for this.

Platform
Android (AOSP)
Language
Java / Kotlin
Build
Gradle
Camera
CameraX API
Getting Started
API Reference
Resources

Introduction

Neuraglass is a pair of glasses with a see-through Micro OLED display, 16MP camera, dual speakers, a microphone, and five physical input keys. It runs Stack OS, a custom operating system built on Android.

If you know how to build an Android app, you can build for Neuraglass. The main differences are:

1
No touchscreen
Input comes from 5 hardware keys and voice. Design for scroll, confirm, and return.
2
See-through display
The user sees the real world through the lenses. Keep UIs minimal, high-contrast, and non-blocking.
3
16MP camera
Capture photos and video from the user's perspective. Access it via CameraX.
4
Dual speakers
Built-in speakers, no earbuds needed. Route audio with AudioManager.

System Overview

Here's how the pieces fit together.

Your App
Java / Kotlin · Android Views or Compose
Stack OS
Voice engine · AI runtime · Display compositor · Key dispatcher
Android (AOSP)
Activity lifecycle · CameraX · MediaRecorder · AudioManager · ADB
Hardware
Micro OLED · 16MP camera · Dual speakers · Mic · 5 keys · WiFi + BT
Deploying apps

Connect via ADB over USB or WiFi. Install APKs with adb install just like any Android device.

Debugging

Standard Android debugging works. adb logcat, Android Studio debugger, and layout inspector all connect normally.

Build Your First App

Let's build a minimal app that responds to Neuraglass hardware keys. This is the "hello world" of Neuraglass development.

1

Create a new Android project

In Android Studio (or your editor of choice), create a new project with an Empty Activity. Set the minimum SDK to 21.

build.gradleGradleCopy
plugins {
    id 'com.android.application'
}
android {
    compileSdk 33
    defaultConfig {
        applicationId "com.example.helloneuraglass"
        minSdk 21
        targetSdk 33
        versionCode 1
        versionName "1.0"
    }
}
dependencies {
    implementation "androidx.appcompat:appcompat:1.6.1"
}
2

Set up the manifest

AndroidManifest.xmlXMLCopy
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.helloneuraglass">
    <uses-permission android:name="android.permission.CAMERA" />
    <application
        android:label="Hello Neuraglass"
        android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
        <activity android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category
                    android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
3

Handle hardware keys

Override dispatchKeyEvent() to respond to the physical buttons on Neuraglass.

MainActivity.javaJavaCopy
package com.example.helloneuraglass;
import android.os.Bundle;
import android.view.KeyEvent;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
    // Neuraglass key codes
    public static final int KEY_OK   = 352;
    public static final int KEY_BACK = 158;
    private TextView statusText;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        statusText = new TextView(this);
        statusText.setText("Hello from Neuraglass!\n\n"
            + "Press CONFIRM to continue.\n"
            + "Press RETURN to go back.");
        statusText.setTextSize(18f);
        statusText.setPadding(48, 48, 48, 48);
        setContentView(statusText);
    }
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            switch (event.getKeyCode()) {
                case KEY_OK:
                    Toast.makeText(this,
                        "Confirm pressed!", Toast.LENGTH_SHORT)
                        .show();
                    return true;
                case KEY_BACK:
                    finish();
                    return true;
            }
        }
        return super.dispatchKeyEvent(event);
    }
}
4

Deploy to Neuraglass

$adb connect <neuraglass-ip>:5555
$./gradlew installDebug
$adb shell am start -n com.example.helloneuraglass/.MainActivity

Event Key Listening

Neuraglass has five physical inputs: scroll forward, scroll backward, confirm, return, and power. These map to standard Android key events.

Physical InputEvent NameHexCode
Scroll forwardKEY_RIGHT0x6a106
Scroll backwardKEY_LEFT0x69105
ConfirmKEY_OK0x160352
ReturnKEY_BACK0x9e158
PowerPOWER0x74164
MainActivity.javaJavaCopy
package com.example.keyeventdemo;
import android.os.Bundle;
import android.view.KeyEvent;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
    // Neuraglass hardware key codes
    public static final int KEY_RIGHT = 106;  // Scroll forward
    public static final int KEY_LEFT  = 105;  // Scroll backward
    public static final int KEY_OK    = 352;  // Confirm
    public static final int KEY_BACK  = 158;  // Return
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        int keyCode = event.getKeyCode();
        int action  = event.getAction();
        if (action == KeyEvent.ACTION_DOWN) {
            switch (keyCode) {
                case KEY_LEFT:
                    showToast("Scroll backward");
                    return true;
                case KEY_RIGHT:
                    showToast("Scroll forward");
                    return true;
                case KEY_OK:
                    showToast("Confirm pressed");
                    return true;
                case KEY_BACK:
                    showToast("Return pressed");
                    super.onBackPressed();
                    return true;
            }
        }
        return super.dispatchKeyEvent(event);
    }
    private void showToast(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }
}

Camera APIs

Access the Neuraglass camera using Android's CameraX API. The 16MP camera supports preview, image capture, and video recording.

Dependencies

build.gradleGradleCopy
// build.gradle dependencies
dependencies {
    def camerax_version = "1.3.0"
    implementation "androidx.camera:camera-core:$camerax_version"
    implementation "androidx.camera:camera-camera2:$camerax_version"
    implementation "androidx.camera:camera-lifecycle:$camerax_version"
    implementation "androidx.camera:camera-view:$camerax_version"
}

Camera preview with CameraX

MainActivity.ktKotlinCopy
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    private var cameraProvider: ProcessCameraProvider? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        if (allPermissionsGranted()) {
            startCamera()
        } else {
            ActivityCompat.requestPermissions(
                this, arrayOf(Manifest.permission.CAMERA), 10
            )
        }
    }
    private fun startCamera() {
        val cameraProviderFuture =
            ProcessCameraProvider.getInstance(this)
        cameraProviderFuture.addListener({
            cameraProvider = cameraProviderFuture.get()
            val preview = Preview.Builder().build().also {
                it.setSurfaceProvider(
                    binding.previewView.surfaceProvider
                )
            }
            val cameraSelector =
                CameraSelector.DEFAULT_BACK_CAMERA
            cameraProvider?.unbindAll()
            cameraProvider?.bindToLifecycle(
                this, cameraSelector, preview
            )
        }, ContextCompat.getMainExecutor(this))
    }
    private fun allPermissionsGranted(): Boolean =
        ContextCompat.checkSelfPermission(
            this, Manifest.permission.CAMERA
        ) == PackageManager.PERMISSION_GRANTED
}
Required permissions
<uses-permission android:name="android.permission.CAMERA" />

Microphone APIs

Record audio from the on-device microphone using Android's MediaRecorder API. Supports recording to 3GP format with AMR encoding, and playback via MediaPlayer.

MainActivity.javaJavaCopy
public class MainActivity extends AppCompatActivity {
    private MediaRecorder recorder = null;
    private MediaPlayer   player   = null;
    private String fileName;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        fileName = getExternalCacheDir().getAbsolutePath()
                   + "/audiorecordtest.3gp";
        ActivityCompat.requestPermissions(this,
            new String[]{
                Manifest.permission.RECORD_AUDIO,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            }, 200);
    }
    private void startRecording() {
        recorder = new MediaRecorder();
        recorder.setAudioSource(
            MediaRecorder.AudioSource.MIC);
        recorder.setOutputFormat(
            MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setOutputFile(fileName);
        recorder.setAudioEncoder(
            MediaRecorder.AudioEncoder.AMR_NB);
        try { recorder.prepare(); }
        catch (IOException e) { e.printStackTrace(); }
        recorder.start();
    }
    private void stopRecording() {
        if (recorder != null) {
            recorder.stop();
            recorder.release();
            recorder = null;
        }
    }
    private void startPlaying() {
        player = new MediaPlayer();
        try {
            player.setDataSource(fileName);
            player.prepare();
            player.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Required permissions
<uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Speaker APIs

Output audio through the Neuraglass dual speakers using Android's TextToSpeech engine and AudioManager. Supports text-to-speech with language, pitch, and rate controls.

MainActivity.javaJavaCopy
public class MainActivity extends AppCompatActivity {
    private AudioManager audioManager;
    private TextToSpeech  textToSpeech;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        audioManager = (AudioManager)
            getSystemService(Context.AUDIO_SERVICE);
        textToSpeech = new TextToSpeech(this, status -> {
            if (status == TextToSpeech.SUCCESS) {
                textToSpeech.setLanguage(Locale.US);
                textToSpeech.setPitch(1.0f);
                textToSpeech.setSpeechRate(1.0f);
            }
        });
    }
    private void startSpeaking(String text) {
        audioManager.setMode(AudioManager.MODE_NORMAL);
        audioManager.setSpeakerphoneOn(true);
        textToSpeech.speak(
            text,
            TextToSpeech.QUEUE_FLUSH,
            null,
            "tts1"
        );
    }
    private void stopSpeaking() {
        if (textToSpeech != null) {
            textToSpeech.stop();
        }
        audioManager.setSpeakerphoneOn(false);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (textToSpeech != null) {
            textToSpeech.stop();
            textToSpeech.shutdown();
        }
    }
}
Audio routing

Use AudioManager.setSpeakerphoneOn(true) to route audio to the dual speakers.

Eliza AI Voice

Eliza is the built-in AI voice assistant on Neuraglass. It can see what you see, answer questions about the real world, and take actions on your behalf, all through natural conversation.

API documentation coming soon

The Eliza AI voice API is functional on current dev kits but the interface is still being structured for third-party developers. Full documentation, including intent registration, context passing, and custom voice commands, will be published here once the API surface is finalized.

In the meantime, join the Discord to get early access and discuss integration patterns with the team.

Voice commands

Register custom voice intents that Eliza routes to your app.

Visual context

Eliza shares what the camera sees. Your app can tap into that context.

Conversational

Multi-turn dialogue with memory, so users can refine requests naturally.

Dev Tools

Drop a native instruction file in the project root so Claude Code, Codex, or Cursor already know the Dev Kit: no touchscreen, five keys, CameraX, ADB. Then ask it to build.

Claude Code
CLAUDE.md

Put this in the project root. Claude Code loads it on every session.

$ claude > "Build a camera app for the Dev Kit"
Download CLAUDE.md
Codex · Cursor
AGENTS.md

Same hardware rules for OpenAI Codex and Cursor Agent. Drop it in the project root.

$ codex > "Handle KEY_OK and KEY_BACK"
Download AGENTS.md

Quick paste

Copy

Shorter version if you just want to paste into a chat. The downloaded files are the ones to keep in the repo.

prompt.txtSystem PromptCopy
You are helping me build an Android app for the Neuraglass Dev Kit running Stack OS (AOSP).
This is glasses software, not a phone app. No touchscreen. See-through Micro OLED. Keep UIs small, high-contrast, and short.
Input is five physical keys + voice:
  - Scroll forward (KEY_RIGHT, 106)
  - Scroll backward (KEY_LEFT, 105)
  - Confirm (KEY_OK, 352)
  - Return (KEY_BACK, 158)
  - Power (164)
Hardware: CameraX (16MP), MediaRecorder / AudioRecord, TextToSpeech + AudioManager.setSpeakerphoneOn(true).
Gradle, Java or Kotlin. compileSdk 33, minSdk 21, targetSdk 33. Install with adb install -r.
Always implement dispatchKeyEvent() and consume ACTION_DOWN for those key codes.
Do not invent Helix or Eliza APIs. Those are not public yet.
Do not use TypeScript, REST, Swift, or Python as the glasses runtime.
When asked to build a Neuraglass app, produce a Gradle Android app and show ADB install steps.

Android Studio

The Dev Kit is a normal Android device. Connect via ADB (USB or Wi-Fi) and use the debugger, layout inspector, and profiler. No extra plugin. Install APKs with adb install -r.

Ready to build?

Join the Discord to get Dev Kit access, ask questions, and connect with other developers building on Neuraglass.

Join the Discord