npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@andrewhopper/fd

v0.1.6

Published

Flight Director — visualize and monitor AI agent state machines

Readme

Flight Director

A sidecar supervisor for coding agents — it doesn't run the agent, it watches and constrains one that's already running.

Define DAG workflows in YAML that constrain AI agent behavior with tool gates, budgets, and transition rules. Unlike agent frameworks that orchestrate execution, Flight Director sits alongside an autonomous agent and enforces what it's allowed to do at each phase.

Prerequisites

  • Rust 1.70+ — install via rustup.rs
  • Node.js 18+
  • jq
  • git
◉ diagnose  ──[found_it]──→  ○ fix  ──[fix_applied]──→  ○ verify  ──[tests_pass]──→  ◎ done
   Read,Grep,Glob only          no WebSearch/WebFetch       Read,Bash,Grep only
   500 tokens / 20 calls        500 tokens / 20 calls       300 tokens / 10 calls

How it works

Flight Director Data Flow

Every tool call flows through the gate engine. On allow, a hint is injected back into the agent's context with the current state, instructions, available transitions, budget status, and criteria progress. On block, the agent gets a rich error explaining why and what to do instead.

Complex Bugfix Machine

UI Page Generation Machine

What it does

  1. Define workflows as YAML state machines — states, transitions, tool gates, budgets, exit criteria
  2. Enforce constraints — each state restricts which tools the agent can use, what files it can touch, and how many tokens/calls it can spend
  3. Track progress — session state persists to disk, transitions are recorded, budgets are monitored

Two ways to use it:

| | Rust CLI (recommended) | Viewer (full-stack) | |---|---|---| | What | Compiled binary with Claude Code hook integration | React + Express app with interactive graph visualization | | For | Claude Code — enforces constraints via PreToolUse/PostToolUse hooks | Local dev — watch agents traverse the DAG in real-time | | Run | fd-cli init --machine machine.yaml | cd viewer && npm run dev |

Quick Start

./bin/fd-cli

That's it. On first run, Flight Director walks you through setup — checks prerequisites, builds the Rust CLI, configures hooks for your AI tools, and lets you pick a workflow machine. On subsequent runs it prints session status and starts the viewer.

./bin/fd-cli --setup              # Force re-run the config flow
./bin/fd-cli --no-viewer          # Print status only
./bin/fd-cli --machine tdd        # Skip the picker, init with a specific machine

To build from source directly:

cargo build --release

Which path?

| Goal | Section | |------|---------| | Just trying it? | Quick Start | | Building from source? | Rust CLI | | Web viewer? | Viewer Setup | | Embedding in a project? | Subtree |

Rust CLI (manual setup)

# Build and configure hooks for your AI tools
bash scripts/setup-hooks.sh

# Initialize a session
./target/release/fd-cli init --machine docs/scenarios/simple-bugfix.yaml

# Check status
./target/release/fd-cli status

# Transition
./target/release/fd-cli transition found_it

# View log
./target/release/fd-cli log

setup-hooks.sh builds the binary and auto-detects which AI tools you have installed (Claude Code, Gemini CLI, Kiro). See Hook Setup for details.

Viewer (full-stack)

# First-time setup
bash scripts/bootstrap.sh

# Start dev server
cd viewer
npm run dev

Opens at localhost:5199 (client) with API at localhost:3199 (server).

Hook Setup

scripts/setup-hooks.sh auto-detects installed AI tools and configures each to call fd-cli via hooks. It builds the Rust binary, runs bootstrap if needed, and writes the appropriate settings file for each tool.

# Configure all detected tools
bash scripts/setup-hooks.sh

# Configure a specific tool only
bash scripts/setup-hooks.sh --tool claude-code
bash scripts/setup-hooks.sh --tool gemini-cli

# Remove Flight Director hooks from all tools
bash scripts/setup-hooks.sh --uninstall

# Skip the cargo build (binary must already exist)
bash scripts/setup-hooks.sh --skip-build

Supported tools

| Tool | Status | Settings file | Hook events | |------|--------|---------------|-------------| | Claude Code | Native | .claude/settings.json | PreToolUse, PostToolUse | | Gemini CLI | Adapter | .gemini/settings.json | BeforeTool, AfterTool | | Kiro | Template | .kiro/settings.json | PreToolUse, PostToolUse | | Codex | Stub | — | Hooks not yet upstream |

Claude Code calls fd-cli directly (native protocol). Gemini CLI and Kiro go through a universal shim (scripts/hooks/fd-shim.sh) that translates between each tool's stdin/stdout format and fd-cli's HookInput/HookOutput protocol.

The script is idempotent — re-running it replaces existing Flight Director hooks without duplicating them, and preserves any non-Flight Director hooks in the settings file.

Adding a new tool

Create a single file in scripts/hooks/adapters/ implementing the adapter interface:

adapter_name()           # "my-tool"
adapter_label()          # "My Tool" (human-readable)
adapter_detect()         # exit 0 if tool is installed
adapter_ready()          # exit 0 if hooks are supported
adapter_settings_path()  # path to settings file
adapter_hooks_json()     # JSON fragment with hook entries
adapter_uninstall_filter()  # jq filter to remove Flight Director hooks

For tools that need stdin/stdout translation (not native), also implement:

adapter_event_to_fd()            # map tool event → fd-cli subcommand
adapter_translate_input()        # jq filter: tool stdin → HookInput
adapter_translate_output_allow() # jq filter: fd-cli allow → tool allow
adapter_translate_output_block() # jq filter: fd-cli block → tool block

No changes to setup-hooks.sh or fd-shim.sh are needed. See docs/hooks.md for the fd-cli hook protocol.

Writing Machines

Machines are YAML files. Here's the simplest possible one:

id: yolo
name: "YOLO"
description: "No guardrails."

override_policy:
  allow_override: true
  allow_waiver: true
  require_reason: false
  hard_criteria_bypass: true

states:
  - id: code
    description: "Write code."
    initial: true
    transitions:
      - name: ship_it
        target:
          state: ship

  - id: ship
    description: "Deploy."
    transitions:
      - name: done
        target:
          state: done

  - id: done
    description: "In production."
    terminal: true

Tool Gates

Constrain which tools the agent can use in a state:

# Only allow these tools
tool_gates:
  - gate_type: tool_allowlist
    params:
      tools: [Read, Grep, Glob]
    message: "Read-only — no edits allowed"
    hard: true

# Block specific tools
  - gate_type: tool_denylist
    params:
      tools: [WebSearch, WebFetch]
    message: "No web access"
    hard: false

# Restrict bash commands
  - gate_type: bash_policy
    params:
      allow_commands: ["npm test", "npm run lint"]
      deny_commands: ["rm -rf", "git push --force"]
    message: "Safe commands only"
    hard: true

# Restrict file paths for Write/Edit
  - gate_type: path_pattern
    params:
      tools: [Write, Edit]
      allow_patterns: ["tests/**", "**/*.test.*"]
      deny_patterns: ["src/**"]
    message: "Only test files may be edited"
    hard: true

Gate types: tool_allowlist, tool_denylist, bash_policy, path_pattern, input_pattern

When hard: true, the constraint is absolute. When hard: false, it's a soft warning.

Criteria

Conditions evaluated during transitions. Eight built-in types: min_tool_calls, max_tool_calls, min_tokens, max_tokens, min_duration, max_duration, command, file_exists. See docs/criteria.md for full reference.

Budgets

Limit resource consumption per state:

budget:
  max_tokens: 5000
  max_tool_calls: 30
  max_wall_time_ms: 300000
  thresholds:
    - percent: 70
      action: Notify
    - percent: 90
      action: Block

Exit Criteria

Conditions that must be met before leaving a state:

exit_criteria:
  - criterion_type: command
    params:
      command: "npm test"
      expect_exit_code: 0
    message: "Tests must pass"
    hard: true

Auto-transitions

Transitions that fire automatically when a condition is met:

transitions:
  - name: tests_pass
    target:
      state: refactor
    auto:
      criterion_type: command
      params:
        command: "npm test"
        expect_exit_code: 0
      message: "Auto-advance when tests pass"

Fork/Join (Concurrency)

transitions:
  - name: parallelize
    target:
      type: Fork
      targets: [lint, test, typecheck]
      join: merge-results

Data Flow

Pass named data between states — upstream states declare outputs, downstream states declare inputs:

states:
  - id: triage
    data_flow:
      outputs:
        - key: bug_classification
          description: "Severity, component, symptoms"

  - id: reproduce
    data_flow:
      inputs:
        - key: bug_classification
          from_state: triage
      outputs:
        - key: error_trace
          description: "Stack trace and repro steps"

Partitions

Split work across keys (e.g., test files). On re-entry, only failed partitions re-run:

partitions:
  keys: ["tests/**/*.test.ts"]
  redo_failed_only: true

Retry Policy

Auto-retry a state on failure with configurable backoff (None, Linear, Exponential):

retry:
  max_retries: 3
  backoff: Exponential
  base_delay_ms: 2000
  max_delay_ms: 30000
  retryable: [CriterionNotMet, Timeout]

Timeout

Time-limit a state with heartbeat monitoring:

timeout:
  state_timeout_ms: 600000
  on_timeout: ForceTransition    # Notify | ForceTransition | Abort | Retry
  timeout_transition: next-state
  heartbeat_interval_ms: 30000
  on_heartbeat_missed: Notify

Spawn (Multi-Agent)

Launch concurrent agents with convergence strategies:

# State-level spawn
spawn:
  strategy: Race         # Explore | Race | Vote
  max_agents: 2
  convergence:
    min_agree: 1
    timeout_ms: 600000
    on_timeout: AbortSlowest
  on_limit: NotifyCoordinator

# Machine-level spawn with parameter matrix
spawn:
  spawn_point: explore
  count: 3
  strategy: Explore
  params_matrix:
    - { approach: "top-down" }
    - { approach: "bottom-up" }
    - { approach: "lateral" }
  convergence:
    max_wall_time_ms: 600000
    on_limit: Abort

See docs/advanced-features.md for full reference on all advanced features.

Example Machines

| Machine | States | Description | |---------|--------|-------------| | yolo | 3 | No constraints, manual transitions | | simple-bugfix | 4 | diagnose → fix → verify → done | | tdd | 7 | Red-green-refactor cycle with loops | | complex-bugfix | 8 | Retry, heartbeat, bash policy, data flow | | bdd | — | Behavior-driven development | | greenfield-landing-page | — | Landing page from scratch | | greenfield-mobile-app | — | Mobile app from scratch |

All live in docs/scenarios/.

Documentation

| Doc | What it covers | |-----|----------------| | docs/rust-cli.md | Rust CLI command reference | | docs/criteria.md | Criteria system — all 8 types, hard/soft, waivers | | docs/advanced-features.md | Data flow, partitions, retry, timeout, spawn, join | | docs/hooks.md | Hook protocol (PreToolUse/PostToolUse) and fd-cli integration | | docs/override-policy.md | Override policy, waivers, rollback, trigger types | | docs/architecture.md | Rust crate architecture, data flow, dependencies | | docs/diagrams/ | PlantUML sequence and component diagrams | | docs/types/ | HTML type reference pages |

Architecture (Viewer)

viewer/src/
├── shared/          # Types + YAML parser (used by both)
│   ├── types/       # Branded IDs, MachineDef, gates, budget, runtime
│   └── yaml-parser  # YAML → MachineDef
├── server/          # Express + WebSocket
│   ├── routes/      # /api/machines, /api/sessions, /api/health
│   ├── data-source/ # FileReader + ZMQ + HybridSource
│   └── ws/          # WebSocket bridge
└── client/          # React 19 + Vite
    ├── components/  # atoms/ molecules/ organisms/ graph/
    ├── stores/      # Zustand (machine, session, ui, graph, ws)
    ├── hooks/       # useWebSocket, useSessionData, useBreadcrumbNav
    └── lib/         # graph-builder, layout (Dagre), colors, format

Data flow: files on disk → Express reads → ZMQ triggers re-reads → WebSocket pushes to React → Zustand stores → graph re-renders.

Environment Variables

| Variable | Default | Purpose | |----------|---------|---------| | ASM_PORT | 3199 | Express server port | | ASM_HOST | 127.0.0.1 | Express server host | | ASM_DIR | $CWD/.claude/asm/ | Data directory | | ZMQ_ENDPOINT | ipc:///tmp/asm.sock | ZMQ socket for live updates |

Project Structure

flight-director/
├── Cargo.toml          # Rust workspace root
├── crates/
│   ├── fd-core/        # Library — types, engine, storage, display
│   └── fd-cli/         # Binary — CLI commands
├── docs/
│   ├── scenarios/      # Example YAML machines
│   ├── diagrams/       # PlantUML architecture diagrams
│   ├── types/          # HTML type reference pages
│   ├── rust-cli.md     # CLI command reference
│   ├── criteria.md     # Criteria system reference
│   ├── hooks.md        # Claude Code hook integration
│   ├── override-policy.md # Override & waiver system
│   ├── architecture.md # Rust crate architecture
│   └── advanced-features.md # Data flow, partitions, retry, timeout, spawn
├── scripts/
│   ├── bootstrap.sh    # First-time setup
│   ├── setup-hooks.sh  # Configure AI tool hooks
│   └── hooks/
│       ├── fd-shim.sh  # Universal shim for non-native tools
│       └── adapters/   # One file per tool (claude-code, gemini-cli, kiro, codex)
├── viewer/             # Full-stack viewer app (React + Express)
└── machines/           # Runtime machine instances

License

MIT