Skip to content

Feature: Daemon mode to avoid model reload on every suggestion #95

@noahgift

Description

@noahgift

Feature Request

Add a daemon/server mode to keep the model in memory, avoiding the ~11ms startup overhead per suggestion.

Current Architecture

Every suggestion spawns a new process:

keystroke → zsh widget → fork+exec aprender-shell → load model → suggest → exit

This causes:

Proposed Architecture

# Start daemon once
aprender-shell daemon &

# Widget uses Unix socket
suggestion=$(echo "$BUFFER" | nc -U /tmp/aprender.sock)

Or use stdin/stdout streaming:

# Daemon mode - stays running, reads prefixes from stdin
aprender-shell daemon --socket /tmp/aprender.sock

# Or simpler - shell coprocess
coproc aprender-shell stream
echo "git " >&${COPROC[1]}
read suggestion <&${COPROC[0]}

Benefits

  • Model loaded once, kept in memory
  • Sub-millisecond suggestion latency
  • Zero disk I/O after startup
  • Reduced memory churn

Implementation Options

Option 1: Unix Socket Server

fn cmd_daemon(socket_path: &Path) {
    let model = Model::load_default()?;
    let listener = UnixListener::bind(socket_path)?;
    
    for stream in listener.incoming() {
        let prefix = read_line(&stream)?;
        let suggestions = model.suggest(&prefix, 5);
        write_response(&stream, &suggestions)?;
    }
}

Option 2: Stdin/Stdout Streaming

fn cmd_stream() {
    let model = Model::load_default()?;
    
    for line in stdin().lines() {
        let suggestions = model.suggest(&line?, 5);
        println!("{}", format_suggestions(&suggestions));
    }
}

Option 3: Named Pipe (FIFO)

mkfifo /tmp/aprender-in /tmp/aprender-out
aprender-shell pipe /tmp/aprender-in /tmp/aprender-out &

ZSH Widget Update

# Start daemon if not running
if [[ ! -S /tmp/aprender.sock ]]; then
    aprender-shell daemon --socket /tmp/aprender.sock &
fi

_aprender_suggest() {
    suggestion=$(echo "$BUFFER" | nc -U /tmp/aprender.sock 2>/dev/null | head -1)
    # ...
}

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions