JARVIS AI Assistant

repository·main·Indexed 20 days ago

https://github.com/ethanplusai/jarvis

A voice-first AI assistant for macOS that integrates with Apple system apps (Calendar, Mail, Notes) using Claude and Fish Audio. It features a state-driven frontend with a Three.js particle orb visualization, Web Speech API integration, and a WebSocket-based communication system. JARVIS can execute system-level tasks via action tags, including browsing the web and building software using the Claude Code CLI.

Tokens
8.2K
Snippets
29
Records
41
Agent score
71%

What's inside JARVIS

  1. Understand the JARVIS Action System

    main

    JARVIS triggers system-level tasks using specific action tags. These tags allow the AI to move beyond conversation into executing real work on your Mac.

    Action TagDescription
    [ACTION:BUILD]Spawns Claude Code to build a software project.
    [ACTION:BROWSE]Opens Google Chrome to a specific URL or search query.
    [ACTION:RESEARCH]Performs deep research using Claude Opus and outputs an HTML report.
    [ACTION:PROMPT_PROJECT]Connects to an existing project via Claude Code.
    [ACTION:ADD_TASK]Creates a tracked task with a priority and due date.
    [ACTION:REMEMBER]Stores a fact in the SQLite memory system for future context.
  2. Install and set up JARVIS manually

    main

    To run JARVIS on macOS, follow these steps to set up the backend, frontend, and environment:

    1. Clone the repository:

      git clone https://github.com/yourusername/jarvis.git
      cd jarvis
    2. Configure environment variables: Copy the example env file and populate it with your API keys:

      cp .env.example .env

      See the Configuration section for required keys.

    3. Install Python dependencies:

      pip install -r requirements.txt
    4. Install frontend dependencies:

      cd frontend && npm install && cd ..
    5. Generate SSL certificates (Required for secure WebSockets):

      openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost'
    6. Run the application:

      • Terminal 1 (Backend):
        python server.py
      • Terminal 2 (Frontend):
        cd frontend && npm run dev
    7. Access the UI: Open http://localhost:5173 in Google Chrome. Click the page once to enable audio before speaking.

    # 1. Clone the repo
    git clone https://github.com/yourusername/jarvis.git
    cd jarvis
    
    # 2. Set up environment
    cp .env.example .env
    
    # 3. Install Python dependencies
    pip install -r requirements.txt
    
    # 4. Install frontend dependencies
    cd frontend && npm install && cd ..
    
    # 5. Generate SSL certificates
    openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost'
    
    # 6. Start the backend
    python server.py
    
    # 7. Start the frontend
    cd frontend && npm run dev
    
    # 8. Open Chrome
    open http://localhost:5173
  3. How action detection works in JARVIS

    main

    JARVIS uses two methods to identify user intent:

    1. Fast Action Detection: For short, obvious commands (under 12 words), the detect_action_fast function performs keyword-based matching without calling the LLM. This handles requests like "what's on my screen", "check my email", or "show me what you built".
    2. LLM-based Action Extraction: For complex or conversational requests, the text is sent to the LLM. The LLM is expected to respond with [ACTION:X] tags, which are then parsed by extract_action to trigger system-level operations (like building a project or opening a browser).
  4. Configure JARVIS environment variables

    main

    JARVIS requires specific API keys in a .env file to function. You can also configure personal preferences like your name and specific calendar accounts.

    Required Keys

    • ANTHROPIC_API_KEY: Powers the AI brain (Claude).
    • FISH_API_KEY: Powers the voice (Fish Audio TTS).

    Optional Keys

    • USER_NAME: The name JARVIS will use to address you (e.g., Tony).
    • CALENDAR_ACCOUNTS: A comma-separated list of specific email addresses to use. If left empty, JARVIS will attempt to auto-discover all available calendars via AppleScript.
    # Required
    ANTHROPIC_API_KEY=your-anthropic-api-key-here
    FISH_API_KEY=your-fish-audio-api-key-here
    
    # Optional
    USER_NAME=Tony
    CALENDAR_ACCOUNTS=you@gmail.com,work@company.com
  5. How JARVIS frontend components work together

    main

    The JARVIS frontend is a state-driven application that orchestrates several core modules to provide a voice-interactive experience:

    • Orb Visualization: Uses createOrb to render a visual representation on a canvas. Its visual state is synchronized with the application's lifecycle via orb.setState(state).
    • Voice Input: Managed by createVoiceInput. It captures speech and provides callbacks for successful transcriptions and errors. It can be start()ed, pause()ed, or resume()ed.
    • Audio Playback: Managed by createAudioPlayer. It handles queuing audio data and provides an onFinished callback to signal when speech has ended. It also provides an Analyser used to drive the Orb's animations.
    • WebSocket Communication: Managed by createSocket. It facilitates real-time bidirectional communication with the backend, handling message types like transcript, audio, status, and task_spawned.
    • State Machine: The application transitions between four primary states: idle, listening, thinking, and speaking. Transitions trigger corresponding UI updates, orb animations, and voice input controls (e.g., pausing voice input while the system is thinking or speaking).
    // Conceptual flow of the state machine and component interaction
    transition("listening"); // Resumes voice input
    transition("thinking");  // Pauses voice input
    transition("speaking"); // Pauses voice input and plays audio
    transition("idle");     // Resumes voice input
  6. Manage JARVIS Work Mode and Project Building

    main

    JARVIS features a specialized "Work Mode" for software development tasks.

    Modes of Operation:

    • Chat Mode: Standard conversational interaction using fast keyword detection and Haiku-based responses.
    • Work Mode: Activated via specific commands or when a work_session is started. It uses claude -p (Claude Code) for high-power coding tasks.
    • Planning Mode: A state where JARVIS asks clarifying questions to build a project plan. Once confirmed, it generates a CLAUDE.md instruction file and begins building.

    Key Features in Work Mode:

    • Stall Detection: If Claude Code asks too many clarifying questions instead of coding, JARVIS automatically pushes it to "start building now".
    • Auto-open Localhost: If a response mentions a localhost URL, JARVIS automatically opens it in the browser.
    • Project Scaffolding: When building, JARVIS creates a directory on the Desktop, writes a detailed CLAUDE.md with specific instructions (e.g., using React + Vite + Tailwind), and expects the final output to include a RUNNING_AT=http://localhost:PORT line.
  7. Handle browser autoplay policies for JARVIS audio

    main

    To ensure audio playback works correctly, the AudioContext must be resumed following a user interaction (click, touch, or keydown) due to browser autoplay restrictions. The application implements an ensureAudioContext pattern that should be called on these events to prevent the audio from remaining in a suspended state.

    function ensureAudioContext() {
      const ctx = audioPlayer.getAnalyser().context as AudioContext;
      if (ctx.state === "suspended") {
        ctx.resume().then(() => console.log("[audio] context resumed"));
      }
    }
    
    // Attach to user interaction events
    document.addEventListener("click", ensureAudioContext);
    document.addEventListener("touchstart", ensureAudioContext);
    document.addEventListener("keydown", ensureAudioContext, { once: true });
  8. Requirements for running JARVIS

    main

    Before installing, ensure your system meets the following requirements:

    • OS: macOS (Required for AppleScript integration with Calendar, Mail, and Notes).
    • Python: 3.11+
    • Node.js: 18+
    • Browser: Google Chrome (Required for the Web Speech API).
    • API Keys:
      • Anthropic API key
      • Fish Audio API key
    • CLI Tools:
      • Claude Code CLI (for software building tasks).
  9. Manage Claude Code tasks with ClaudeTaskManager

    main

    The ClaudeTaskManager class manages background claude -p subprocesses. It handles task spawning, status tracking, and provides real-time updates to connected WebSocket clients.

    Key features:

    • Concurrency Control: Limits the number of simultaneous tasks (default is 3).
    • Automatic Project Creation: If no working directory is provided, it generates a kebab-case folder name on the Desktop.
    • Visual Execution: Uses AppleScript to open a new Terminal window and run the command visibly.
    • Auto-QA: Automatically runs a QA verification process upon task completion.
    • WebSocket Notifications: Pushes task_spawned, task_complete, and qa_result events to clients.
    manager = ClaudeTaskManager(max_concurrent=3)
    # Spawns a task and returns a unique task_id
    task_id = await manager.spawn("Build a React todo app", working_dir="./my-project")
    
    # Retrieve task details
    task = await manager.get_status(task_id)
    print(f"Status: {task.status}")
    
    # List all tasks
    all_tasks = await manager.list_tasks()
  10. Scan for local projects with scan_projects

    main

    The scan_projects() function performs a shallow scan of the user's ~/Desktop directory to identify Git repositories. It returns a list of dictionaries containing project metadata, which can be used to provide context to the LLM.

    Returned Dictionary Structure:

    • name: The name of the directory.
    • path: The absolute path to the project.
    • branch: The current Git branch (or unknown).
    projects = await scan_projects()
    # Example output:
    # [{
    #   "name": "my-awesome-app",
    #   "path": "/Users/user/Desktop/my-awesome-app",
    #   "branch": "main"
    # }]
  11. Create voice input with createVoiceInput()

    main

    Use createVoiceInput to initialize speech recognition using the Web Speech API. It requires two callback functions: onTranscript to handle successfully recognized text and onError to handle errors (such as microphone access denial).

    The returned VoiceInput object allows you to control the lifecycle of the microphone listener.

    const voiceInput = createVoiceInput(
      (text) => console.log("Recognized:", text),
      (err) => console.error("Voice Error:", err)
    );
    
    // Control the listener
    voiceInput.start();
    voiceInput.pause();
    voiceInput.resume();
    voiceInput.stop();
  12. Trigger JARVIS self-improvement mode

    main

    Enters 'work mode' by opening the JARVIS repository in a new Terminal window using claude. This is intended for allowing the agent to perform self-fixes or improvements on its own codebase.

    POST /api/fix-self