npm package: @northflare/runner
Description: Distributed conversation runner for Northflare
Latest version: 0.0.37

# Northflare Runner

Distributed conversation runner for Northflare that executes Claude conversations on behalf of remote workspaces.

## Overview

The Runner App is an npm module that:

- Receives messages from the orchestrator via Server-Sent Events (SSE)
- Sends responses to the orchestrator via HTTP POST with JSONRPC format
- Manages GitHub repository checkouts per workspace
- Executes Claude conversations using the official Anthropic claude-code SDK

## Installation

```bash
npm install -g @northflare/runner
# or
npx @northflare/runner start
```

## Quick Start

### Required Environment Variables

```bash
# Authentication token from the server
export NORTHFLARE_RUNNER_TOKEN="your-auth-token"
```

### Optional Environment Variables

```bash
# Root directory for Git checkouts (optional, defaults to /workspace)
export NORTHFLARE_WORKSPACE_PATH="/path/to/workspace/root"

# Orchestrator API endpoint, for use when self-hosting
export NORTHFLARE_ORCHESTRATOR_URL="https://your-orchestrator-url"
```

### Starting the Runner

```bash
# Start with default configuration
npx @northflare/runner start

# Start with custom config file
npx @northflare/runner start --config runner-config.json

# Enable debug logging
npx @northflare/runner start --debug

# Override workspace directory
npx @northflare/runner start --workspace-path /custom/workspace

```

### CLI Options

```bash
npx @northflare/runner --help

Options:
  -V, --version                          output the version number
  -c, --config <path>                    path to configuration file
  --retry-strategy <strategy>            registration retry strategy (none, interval, exponential) (default: "exponential")
  --retry-interval-secs <seconds>        retry interval in seconds for interval strategy (default: "60")
  --retry-duration-secs <seconds>        max retry duration in seconds for exponential strategy (default: "900")
  --data-dir <path>                      data directory path (default: env-paths app data dir)
  --heartbeat-interval <ms>              heartbeat interval in milliseconds (default: "120000")
  -h, --help                             display help for command
```

## Configuration

### Configuration File (optional)

Create a `runner-config.json` file (optional). By default data is stored in
the OS-specific application data directory provided by [`env-paths`](https://www.npmjs.com/package/env-paths)
under the `northflare-runner` app name. Override it only if you need the data
somewhere else:

```json
{
  "dataDir": "/custom/path/to/northflare-runner-data"
}
```

### Environment Variables

| Variable                      | Required | Description                                            |
| ----------------------------- | -------- | ------------------------------------------------------ |
| `NORTHFLARE_RUNNER_TOKEN`     | Yes      | Authentication token from server                       |
| `NORTHFLARE_WORKSPACE_PATH`   | No       | Root directory for Git checkouts |
| `NORTHFLARE_ORCHESTRATOR_URL` | Yes      | Orchestrator API endpoint                              |
| `NORTHFLARE_DATA_DIR`         | No       | Override data directory (default: env-paths app data dir) |
| `DEBUG`                       | No       | Enable debug logging                                   |

### Programmatic

```typescript
import { RunnerApp, ConfigManager } from "@northflare/runner";

// Load configuration
const config = await ConfigManager.loadConfig();

// Create and start runner
const runner = new RunnerApp(config);
await runner.start();

// Graceful shutdown
process.on("SIGTERM", async () => {
  await runner.stop();
  process.exit(0);
});
```

## Features

- **Real-time Communication**: Receives messages via SSE, sends via HTTP
- **Repository Isolation**: Separate Git checkouts per workspace
- **Automatic Recovery**: Retry logic with exponential backoff
- **Comprehensive Logging**: Winston-based logging with file rotation
- **Graceful Shutdown**: Handles signals properly
- **Resource Management**: Automatic cleanup and limits
- **Server-Generated IDs**: Runner IDs are generated by the server during registration
- **Configurable Retry Strategies**: Choose from none, interval, or exponential backoff for registration

## Registration and Retry Strategies

The runner must register with the orchestrator before it can start processing tasks. The registration process:

1. **Initial Registration**: The runner sends a registration request to the orchestrator
2. **Server Response**: The orchestrator generates a unique runner ID and returns it
3. **Heartbeat**: After successful registration, the runner sends periodic heartbeats

### Retry Strategies

If registration fails, the runner can retry using one of three strategies:

#### None (`--retry-strategy none`)

- Single registration attempt
- Fails immediately if registration fails
- Use for testing or when you want immediate failure feedback

#### Interval (`--retry-strategy interval`)

- Retries at fixed intervals
- Configure interval with `--retry-interval-secs` (default: 60 seconds)
- Continues retrying indefinitely until successful
- Use for predictable retry patterns

#### Exponential (`--retry-strategy exponential`) [Default]

- Starts with 8-second delay, doubles each time (8s, 16s, 32s, 64s, etc.)
- Maximum retry duration configured with `--retry-duration-secs` (default: 900 seconds / 15 minutes)
- Final retry attempt at the max duration before giving up
- Use for production to avoid overwhelming the server while still retrying aggressively at first

### Examples

```bash
# Use exponential backoff (default)
npx @northflare/runner start

# Retry every 30 seconds indefinitely
npx @northflare/runner start --retry-strategy interval --retry-interval-secs 30

# Fail immediately if registration fails
npx @northflare/runner start --retry-strategy none

# Use exponential backoff but give up after 5 minutes
npx @northflare/runner start --retry-strategy exponential --retry-duration-secs 300
```

## Logging

Logs are written to:

- Console (colored output)
- `{dataDir}/logs/combined.log` - All logs
- `{dataDir}/logs/error.log` - Errors only
- `{dataDir}/logs/debug.log` - Debug logs (when debug enabled)

## Architecture

The runner consists of several key components:

1. **RunnerApp** - Main entry point and lifecycle manager
2. **MessageHandler** - Processes incoming JSONRPC messages via SSE
3. **ClaudeManager** - Manages Claude conversations using the official Anthropic claude-code SDK
4. **RepositoryManager** - Manages Git repository checkouts and workspace isolation

The runner operates as a standalone process that:

- Receives messages from orchestrator via Server-Sent Events (SSE)
- Sends responses to orchestrator via HTTP POST
- Manages GitHub repository checkouts per workspace
- Executes Claude conversations using the official Anthropic claude-code SDK

## Development

```bash
# Install dependencies
npm install

# Build the project
npm run build

# Run in development mode
npm run dev

# Run tests
npm test

# Lint code
npm run lint
```

## License

MIT