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

@athree/create-project

v1.2.1

Published

Create a new A3 automation project

Readme

A3 Project Template

Create and scaffold A3 automation workflows.

Note: This template requires the next branch of @athree/runner. Last updated: 2026-01-27. This will change as this branch changes or is merged.

Create a New Project

npx @athree/create-project a3-project-starter
cd a3-project-starter
npm i && npm run compile

Naming convention: Projects should be named a3-project-{name} (e.g., a3-project-hotel-rates).

Note: You must run npm run compile for the project to appear in your local athree runner.

Or clone manually:

cp -r a3-project-template a3-project-starter
cd a3-project-starter
npm i && npm run compile

Adding Project to Runner

Use the Add Project button in the A3 runner UI to add your project directory. The runner will automatically detect workflows in compiled projects.

Environment Setup

Configure your environment variables before running workflows:

cp .env.example .env
# Edit .env and add your API keys

Required variables:

  • At least one LLM API key: GOOGLEAI_API_KEY, OPENAI_API_KEY, or ANTHROPIC_API_KEY

Optional variables:

  • CHROME_HEADLESS — Run browser in headless mode (default: true)
  • CHROME_KEEP_OPEN — Keep browser open between runs (default: true)

Project Structure

├── datasets/                    # Input YAML files (one per service)
├── services/                    # Output directory (gitignored)
│   └── {service-id}/
│       ├── screenshot.png       # Page screenshot
│       └── result.json          # Workflow result
├── src/
│   ├── instructions/            # LLM instructions (markdown files)
│   ├── schema/                  # Zod schemas (Dataset, Result)
│   └── workflows/               # Workflow classes

Included Workflows

SimpleScreenshot

A minimal workflow demonstrating basic browser automation:

  1. Navigates to a URL
  2. Waits for page load
  3. Takes a full-page screenshot

Useful as a starting point or for testing browser connectivity.

SimpleGenericWebAgent

Demonstrates the GenericWebAgent pattern:

  1. Navigates to a URL
  2. Creates a GenericWebAgent via AgentsService
  3. Runs the agent with a simple text objective

This is the simplest way to use LLM-powered web automation - no stages, no schemas, just a one-shot LLM call with browser tools.

SimpleLearningAgentExtract

Demonstrates the learning agent pattern with stages:

  1. Loads instructions from a markdown file
  2. Sets up automation context with input/output schemas
  3. Uses AutomationRunner.learn() to execute with LLM guidance
  4. The LLM creates reusable stages to navigate and extract data

Use this pattern for complex, multi-step automations that benefit from reusable stages.

Getting Started

  1. Set up environment variables (see Environment Setup)
  2. Run npm run compile to build the project
  3. Update the dataset in the workflow (or load from datasets/)
  4. Define instructions in src/instructions/ for LLM-powered workflows
  5. Update schemas in src/schema/ to match your data

Key Services

  • ChatService — Send messages to the UI
  • BrowserService — Access the browser page for screenshots, navigation
  • AgentsService — Create LLM agents (createGenericWebAgent(), createPageExtractor())
  • AutomationRunner — Run automations with run() (existing stages) or learn() (LLM-guided)
  • AutomationContext — Manage automation state, inputs, outputs, and schemas

GenericWebAgent Pattern

For simple one-shot LLM tasks, use GenericWebAgent:

import { AgentsService, BrowserService, workflow } from '@athree/runner';
import { dep } from 'mesh-ioc';

@workflow({ title: 'My Workflow' })
export class MyWorkflow {
    @dep() private browserService!: BrowserService;
    @dep() private agentsService!: AgentsService;

    async run() {
        const page = await this.browserService.getPage();
        await page.goto('https://example.com');

        const agent = this.agentsService.createGenericWebAgent();
        agent.addUserContext({ currentUrl: page.url() });

        await agent.run('Extract the main heading and description from this page.');
    }
}

Learning Agent Pattern

For complex multi-step automations with reusable stages, use the learning agent:

import { AutomationRunner, AutomationContext, workflow } from '@athree/runner';
import { dep } from 'mesh-ioc';
import { z } from 'zod';

@workflow({ title: 'My Workflow' })
export class MyWorkflow {
    @dep() private automationRunner!: AutomationRunner;
    @dep() private automation!: AutomationContext;

    async run() {
        const result = await this.automationRunner.learn({
            automationId: 'my-automation',
            instructions,           // Loaded from .md file
            inputs: { url },        // Input data
            inputsSchema,           // Zod schema for inputs
            outputsSchema,          // Zod schema for expected outputs
            learningModel: 'gemini-2.5-flash',  // Optional: specify LLM model
        });

        const outputs = this.automation.outputs;
    }
}

Instructions Files

Instructions tell the LLM how to handle different page states. Place them in src/instructions/:

# Goal
Extract product details from the page.

# Output Fields
- `ctx.outputs.title` - Product title
- `ctx.outputs.price` - Product price
- `ctx.outputs.status` - "success" or "failure"

# Instructions
## Product page
1. Extract the title from h1
2. Extract the price
3. Set status to "success"

Tips

  • Define clear output fields in your instructions
  • Use Zod schemas to validate inputs and outputs
  • The LLM creates reusable stages that can be re-run without LLM
  • Save results to the services/ folder