Skip to content

yazinsai/exec

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

171 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Exec

Voice-to-action system. Record a voice command on your phone or Mac, and a persistent Claude agent executes it with full Mac access.

Architecture

Phone (Expo) → InstantDB ← Agent (Bun + Claude Agent SDK) ← Desktop (Electron hotkey)

Three components:

  • Mobile app — Expo/React Native. Record voice, view task status + results
  • Agent process — Bun. Polls InstantDB for tasks, executes via Claude Agent SDK
  • Desktop hotkey — Electron. Cmd+Option+Space push-to-talk overlay

Prerequisites

  • Node.js 18+
  • Bun (agent process)
  • pnpm (mobile app)
  • EAS CLI (npm install -g eas-cli)
  • ffmpeg (desktop audio recording) — brew install ffmpeg
  • Xcode (iOS builds) / Android Studio (Android builds)

Environment Variables

Copy .env.example to .env and fill in:

EXPO_PUBLIC_INSTANT_APP_ID=       # InstantDB app ID
EXPO_PUBLIC_GROQ_API_KEY=         # Groq API key (Whisper transcription)
INSTANT_APP_ADMIN_TOKEN=          # InstantDB admin token (for agent)

The desktop app reads from desktop/.env:

INSTANT_APP_ID=
INSTANT_ADMIN_TOKEN=
GROQ_API_KEY=

Development

Mobile App

pnpm install
pnpm start          # Expo dev server
pnpm ios            # Run on iOS simulator
pnpm android        # Run on Android emulator

Agent Process

cd agent
bun install
bun run dev         # Start with --watch (auto-restart on changes)

The agent polls InstantDB for pending tasks and executes them via the Claude Agent SDK with bypassPermissions. It processes tasks FIFO, one at a time.

Desktop Hotkey App

cd desktop
npm install
npm start           # Launch Electron app

Press Cmd+Option+Space to record. Press again to stop, transcribe, and send to the agent. Runs as a menubar tray app.

Building & Deploying

EAS Build (Mobile)

Three build profiles in eas.json:

# Development build (includes dev tools, internal distribution)
eas build --profile development --platform ios

# Preview build (internal distribution, "preview" update channel)
eas build --profile preview --platform ios

# Production build (auto-increment version, "production" update channel)
eas build --profile production --platform ios

Replace ios with android for Android builds.

OTA Updates (Mobile)

Push over-the-air updates without rebuilding:

pnpm update:preview      # Push to preview channel
pnpm update:production   # Push to production channel

InstantDB Schema

After modifying instant.schema.ts or instant.perms.ts:

npx instant-cli push schema --app $EXPO_PUBLIC_INSTANT_APP_ID --token $INSTANT_APP_ADMIN_TOKEN --yes
npx instant-cli push perms --app $EXPO_PUBLIC_INSTANT_APP_ID --token $INSTANT_APP_ADMIN_TOKEN --yes

Auto-Start on Login (macOS)

launchd plists are included in the repo. Symlink them to ~/Library/LaunchAgents/ so macOS picks them up:

# Symlink the plists (one-time setup)
ln -s ~/ai/projects/exec/agent/com.exec.agent.plist ~/Library/LaunchAgents/
ln -s ~/ai/projects/exec/desktop/com.exec.desktop.plist ~/Library/LaunchAgents/

# Start them
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.exec.agent.plist
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.exec.desktop.plist

To stop:

launchctl bootout gui/$(id -u)/com.exec.agent
launchctl bootout gui/$(id -u)/com.exec.desktop

To restart:

launchctl kickstart -k gui/$(id -u)/com.exec.agent
launchctl kickstart -k gui/$(id -u)/com.exec.desktop

Logs: /tmp/exec-agent.stdout.log, /tmp/exec-desktop.stdout.log

Data Model

Two InstantDB entities:

tasks — voice commands and their results

Field Type Notes
input string Transcribed voice text
status string pending / running / done / failed / cancelled
result string? Agent's output (markdown)
source string phone / mac
sessionId string? Claude session ID (for follow-ups)
liveOutput string? Streaming output while running
cancelRequested boolean? Cancel flag
createdAt number Timestamp (indexed, FIFO order)

messages — conversation thread per task

Field Type Notes
role string user / assistant
content string Message text
createdAt number Timestamp

Link: each message belongs to one task (cascade delete).

Project Structure

exec/
├── agent/                  # Claude Agent SDK process
│   ├── index.ts            # Main loop (FIFO queue, polling, execution)
│   ├── system-prompt.md    # Agent system prompt
│   └── package.json
├── desktop/                # Electron hotkey app
│   ├── main.js             # Main process (global shortcut, recording, transcription)
│   ├── overlay.html        # Floating recording overlay
│   ├── preload.js          # Context bridge
│   └── package.json
├── app/
│   ├── index.tsx           # Home screen (recorder + task list + detail modal)
│   └── _layout.tsx         # Root layout
├── components/
│   ├── RecordingOverlay.tsx # Full-screen recording UI
│   └── Waveform.tsx        # Audio waveform visualization
├── lib/
│   ├── db.ts               # InstantDB client init
│   ├── audio.ts            # Audio file operations
│   └── transcription.ts    # Groq Whisper API
├── hooks/
│   ├── useThemeColors.tsx   # Dark/light theme
│   └── usePushNotifications.tsx
├── constants/Colors.ts     # Design tokens
├── instant.schema.ts       # InstantDB schema (2 entities)
├── instant.perms.ts        # InstantDB permissions
├── eas.json                # EAS build profiles
├── app.config.ts           # Expo config
└── .env                    # Credentials

About

Voice → Done. Your AI executive that handles whatever you throw at it.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors