Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

minifactory

A tiny, pluggable software factory. You describe what you need, a workflow does the work, and every step an AI agent takes is fenced in by deterministic checks, budgets and a human-reviewable result.

  • Declarative workflows: YAML made of plugin steps, validated before anything runs.
  • Agents on a leash: the LLM is a step, never the boss. Its output is untrusted, bounded by budgets and followed by real gates (a compiler, a test run, a diff-size limit).
  • Everything environment-specific sits behind ports (git host, LLM, secrets, job source, executor), so swapping GitHub for another host or Bedrock for another model is a one-line change.
  • Ask in plain language: minifactory ask "..." picks the right workflow, drafts its input, and asks before it runs.

Status: alpha. The engine, the CLI and three example workflows work and are tested; see Limitations for what has and has not been verified.

┌──────────────── core (src/minifactory/core) ────────────────┐
│ engine · workflow validation · registry · events · expr │   knows nothing about
└───────────────────────────┬─────────────────────────────┘   languages, git hosts or LLMs
   ports: scm · llm · secrets · source · executor · router · intake
                            │
┌───────────── plugins (src/minifactory/plugins/builtin) ─────┐
│ github · local-git · bedrock · openai · jev router      │
│ shell.run · agent.edit · flutter.* · scm.open_pr · ...  │
└─────────────────────────────────────────────────────────┘

The rule that keeps it from becoming spaghetti: the core never imports a plugin; plugins register themselves.

Install

Pre-release. 0.0.2a1 is an alpha: pip and uv skip pre-releases unless you ask, so a plain install still gets 0.0.1. To try the alpha: uv tool install --prerelease allow minifactory or pip install --pre minifactory.

The easiest way to get the minifactory command is a tool installer, which keeps it isolated and on your PATH:

uv tool install minifactory            # or: pipx install minifactory
uv tool install "minifactory[aws]"     # + boto3, for the Amazon Bedrock LLM

Or with plain pip, ideally inside a virtual environment:

pip install minifactory
pip install "minifactory[aws]"

minifactory: command not found after pip install? pip puts console scripts next to the Python it installed into, and that folder is often not on your PATH (typical with the python.org macOS installer, where it is /Library/Frameworks/Python.framework/Versions/3.X/bin). Use uv tool install / pipx, add that folder to PATH, or run python3 -m minifactory .... Beware of zsh's AUTO_CD: if a folder called minifactory exists where you are, typing the bare word changes into it instead of reporting the missing command.

From source, for development:

git clone https://github.com/juan-campuzano/minifactory && cd minifactory
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,aws]"

Python 3.11+. Workflows live in a workspace, not in the package (see below).

Quick start (offline, no keys, no SDK)

minifactory init my-factory && cd my-factory       # a workspace: minifactory.yaml + workflows/
minifactory workflows list                         # templates that ship with the package
minifactory workflows copy flutter-app-factory     # copies the workflow and its sample inputs
minifactory validate flutter-app-factory           # fail-fast checks, runs nothing
minifactory run flutter-app-factory                # runs 4 sample jobs with canned LLM replies

This example factory turns an app spec into a project: plan, implement, build/test gates, an automatic repair loop, a non-blocking coverage check, then delivery. The offline run uses a simulated flutter and canned LLM replies, so what it produces is not a real project. It exists to show every path the engine can take:

sample job what it exercises
todo_app happy path
counter_needs_repair the first attempt breaks the build; the repair loop fixes it
notes_low_coverage coverage below the threshold never blocks delivery, it annotates it
bad_spec the plan is not valid JSON, so the job fails early and nothing is built

Each job leaves state.json, result.json and its working copy in .minifactory/runs/<workflow>/<job>/; events.jsonl records every step and LLM call (tokens and cost when the provider reports them). minifactory run ... --resume restarts from the first step that did not finish ok.

Workspaces

Code ships in the package; your content lives in a workspace, found like git (nearest minifactory.yaml going up from the current directory, else ~/.config/minifactory):

my-factory/
  minifactory.yaml      optional settings: runs_dir, output_dir, router, threshold, plugins
  workflows/        your workflows, the ones `minifactory ask` can choose from
  ...               anything your workflows reference (specs/, fixtures/...), relative to this folder

Relative paths inside a workflow resolve from the workspace root, wherever you run minifactory inside it. Command-line flags override minifactory.yaml, which overrides the defaults.

Example workflows (templates)

Copy one into your workspace with minifactory workflows copy NAME; only copied workflows are routable by ask.

template what it does needs
flutter-app-factory the offline demo above nothing
app-factory creates a new project (an app, a CLI, a library) from a one-line request, in Python, Node, Java or Flutter, sized to the request AWS credentials (Bedrock) and the stack's tools
fix-bug fixes a bug in an existing GitHub repo (Python, Node or Flutter, detected from its files): reproduces it with a failing test, fixes it minimally, opens a PR gh auth login, AWS credentials, the stack's tools
create-workflow drafts a new workflow from a plain-language goal, using only the steps and plugins that exist (see below) AWS credentials (Bedrock)
java-migration-demo a batch transform over toy repos: deterministic branch vs LLM branch, baseline gate, repair loop nothing

Describe what you need: minifactory ask

export TYPESAFE_API_KEY=...       # for the default router (Jev); `--router keyword` works offline
minifactory ask "a simple app to track my expenses" --dry-run   # picks a workflow, drafts its input, runs nothing
minifactory ask "a simple app to track my expenses"             # same, then asks before running
  1. A router plugin chooses among the workflows that declare a route: block, and says how confident it is.
  2. Policy lives in code, not in the model: with --yes it only acts when the router is confident, the request is actionable and a workflow fits; otherwise it exits without doing anything.
  3. The workflow's intake plugin drafts its input from your text (the text is treated as data, the result is validated), and you confirm before anything runs.
  4. Where results go is your choice for new projects: --output local (a plain git folder) or --output github (a new private repo plus a pull request; --public to change that).

Languages: stack profiles

Everything language-specific is data: a stack profile says how to recognise a stack, how to scaffold it, which commands analyse and test it, where code and tests live, and what an LLM should know about its idioms. Packaged: python, node, java (JDK only: no Maven, Gradle or JUnit) and flutter. ask picks the stack from your request, and when it matches none of them it says so instead of building the wrong thing:

$ minifactory ask "a cobol program that prints hello"
error: no supported stack matches this request (got 'unsupported'; available: flutter, java, node, python). Add one as stacks/<name>.yaml

Add a language by dropping a YAML file in your workspace's stacks/ folder (field reference in docs/stacks.md): no code needed.

Fix a bug in an existing repo

minifactory workflows copy fix-bug
minifactory ask "the counter goes up by 2 instead of 1 in acme/todo_app" --dry-run

fix-bug clones the repo with gh, requires the repo to analyse cleanly, selects the relevant files, writes a test that reproduces the bug (and stops without changing anything if that test does not fail), fixes it with an exact-match patch, re-runs the checks, enforces a size limit on the change, and opens a pull request. It never touches the default branch.

Let the factory write workflows

minifactory workflows copy create-workflow
minifactory ask "create a workflow that clones a GitHub repo, runs dart format and opens a pull request"
minifactory workflows list                    # the result is listed under "drafts"
minifactory workflows enable dart-format-pr   # shows what it would do, asks, then activates it

The agent reads a catalog generated from the plugins installed right now (minifactory plugins --schema prints the same text), writes draft.yaml, and must pass the same validator as any workflow; errors go back to it through the usual repair loop. If the goal needs something that does not exist it declines with MISSING: <what> instead of inventing a step. The result is only ever a draft: it is not routable by ask and never runs until you enable it, and enable first lists every shell command, repository write and paid LLM call it contains.

Design principles

  • Untrusted agent output. Edits are parsed strictly: a PATCH must match exactly once or nothing is written; paths cannot escape the repo; plans are validated with pydantic; the Bedrock provider rejects a reply cut off by the token limit.
  • Bounded loops. Repair attempts, unproductive attempts, features per plan and context size all have budgets.
  • Deterministic gates after every agent step. on_fail: discard stops a job without changing anything; blocking: false lets enrichment steps annotate a result without stopping it.
  • Generated workflows are drafts. A person reviews and enables them; nothing an LLM wrote runs on its own.
  • Proposals, not pushes. Changes to existing repos arrive as a pull request on a new branch.
  • No silent fakes. The simulated flutter is opt-in (tool: fake or FACTORY_FLUTTER=fake); by default the real SDK is required and a missing one is an error.

The workflow format

Deliberately small: sequence, when, on_fail: fail|discard|continue, blocking: false, and ${...} templating over job, steps, vars and env. No loops, no calls, no arithmetic: if you need that, write a step in Python. Everything checkable is checked at load time: unknown plugins, typos in parameters, missing providers, bad when syntax, references to steps that run later.

Write a plugin

No core changes needed. A step is a class with typed parameters:

# my_plugin.py
from minifactory.core.context import Step, StrictParams
from minifactory.core.models import StepResult
from minifactory.core.registry import register

class Params(StrictParams):          # unknown keys in the YAML are errors
    message: str

@register("step", "demo.hello")
class Hello(Step):
    Params = Params
    def run(self, ctx, p):
        return StepResult.ok(f"hello {ctx.job.name}: {p.message}")
minifactory run my-workflow --plugin my_plugin

Installed packages can instead expose the minifactory.plugins entry point and are discovered automatically. Plugin kinds: step, source, executor, scm, llm, secrets, router, intake. Built in:

kind built in
scm github (via the gh CLI), local-git, local-dir
llm bedrock, openai (any OpenAI-compatible endpoint), fixture, scripted
router jev (TypeSafe), keyword
intake app-spec, repo-task
source app-specs, repo-tasks, catalog, static
executor local, threads
secrets env

See docs/plugins.md for each kind's interface, and AGENTS.md if you are an AI coding agent (or work with one) on this repo.

Limitations

  • Alpha. Only Python 3.11 and 3.13 are tested in CI.
  • Stack profiles ship for Python, Node, Java (JDK only) and Flutter. A Maven/Gradle project needs your own profile.
  • The gates check that generated code is consistent (it builds and its own tests pass), not that it does what you meant: a generated Java "first twenty primes" program printed the primes up to a limit, and passed its own tests.
  • The real-model runs were small: a one-line app, and a seeded one-line bug in a small repo. Larger apps, where features must agree with each other, are not solved: expect failures there.
  • The github provider has been exercised against a fake gh in tests and has created repos in manual runs; the existing-repo flow has only been run against a local git remote, not against a real GitHub repository.
  • No built-in retry or timeout policy at the engine level, and no persistent state store beyond local JSON files.

Development

pip install -e ".[dev]"
ruff check src tests examples
pytest -q            # no network, credentials or Flutter SDK needed

License

MIT, see LICENSE.

Metadata

Release files for minifactory 0.0.2a1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for minifactory 0.0.2a1
File Size Uploaded Provenance
minifactory-0.0.2a1.tar.gz 99.1 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for minifactory 0.0.2a1
File Interpreter ABI Platform
minifactory-0.0.2a1-py3-none-any.whl Python 3 none any Details

Total release size: 191.2 kB

Release files / minifactory-0.0.2a1.tar.gz

Download URL minifactory-0.0.2a1.tar.gz
Size 99.1 kB
Tags Source
SHA-256 checksum
How to use checksums
84905a52d3624e3b834a33684a5ef2a12754b651fa01a3091ec88aeb0d0791fe
BLAKE2b-256 checksum
How to use checksums
c80fd4963cb0cee2a2029e768f7c24d16865177dc7100ddd58f3e580508e959c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.

Transparency log

Release files / minifactory-0.0.2a1-py3-none-any.whl

Download URL minifactory-0.0.2a1-py3-none-any.whl
Size 92.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
76b9067c913394be3596f77fb1c9a68dbdc0efbfc7b26f856ce47ceac85bd51a
BLAKE2b-256 checksum
How to use checksums
a4bcd0202581b87b027dc7de1906ccafcaf8d913e0b7901e77087f3c66e21ecc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.

Transparency log

Security for minifactory 0.0.2a1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for minifactory-0.0.2a1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page