Skip to main content

Autonomous dependency upgrader powered by LangGraph and LLMs

Project description

loopgrade

Autonomous dependency upgrader powered by LangGraph and LLMs. Upgrades your dependencies one at a time, runs your tests, commits what works, reverts what breaks — without you touching anything.

Python 3.10+ LangGraph


The Problem

You have a project with 20 dependencies. Half of them are outdated. Running ncu -u or pip install --upgrade upgrades all of them at once — and when something breaks, you have no idea which package caused it.

So you don't upgrade. The deps rot. Security patches pile up.

loopgrade fixes this.

It upgrades one dependency at a time, runs your test suite after each upgrade, commits if it passes, reverts if it fails, and moves on to the next one. When it's done, it gives you a full report of what was upgraded, what failed, and why.


How It Works

loopgrade is built on Loop Engineering — the practice of designing autonomous systems that work toward a goal without human prompts. Instead of you babysitting an AI agent turn by turn, loopgrade designs the loop once and lets it run.

The core loop is a LangGraph StateGraph — a stateful, cyclical graph that carries a shared state object through every node. Each node reads what it needs from state, does one job, and writes back only what changed.

See docs/agent.md for the full agent architecture diagram, node descriptions, tool definitions, and LLM prompts.


Conflict Resolution

Version conflicts are detected before any file is touched — not discovered after tests fail.

How conflicts are detected

For npm, loopgrade runs:

npm install axios@1.7.2 --dry-run

For pip:

pip install numpy==2.0.0 --dry-run

Both commands hit the resolver without touching anything on disk.

Three outcomes

none — no conflicts, proceed to upgrade normally.

resolvable — a constraint exists but a safe version is available. Example: you want numpy 2.0.0 but scipy 1.11.0 requires numpy < 2.0. loopgrade finds numpy==1.26.4 (the highest version satisfying all constraints) and uses that instead of the absolute latest. The result is logged as "upgraded with adjustment."

hard — no version of the package can satisfy all constraints simultaneously. loopgrade skips it immediately — zero test attempts wasted — and logs the exact reason plus a suggestion for what the developer should do manually.

What a hard conflict looks like in the report

## Failed / Skipped
- webpack: 4.46.0 → 5.91.0
  reason: hard conflict — html-webpack-plugin 4.x requires webpack<5
  suggestion: upgrade html-webpack-plugin to 5.x first, then retry webpack

Retry Policy

Each dependency gets up to 3 attempts. The retry logic is intelligent — not just "try the same thing again."

Attempt 1 → try absolute latest version
              ↓ fail
Attempt 2 → try safe_version from resolver (if available)
              ↓ fail
Attempt 3 → try one minor version below latest
              ↓ fail
→ skip + flag for manual review

Early exit conditions — these skip the dep immediately, no attempts wasted:

  • same_error_streak >= 3 — identical error across retries means retrying is pointless
  • conflict_info.type == "hard" — mathematically impossible, skip before any attempt
  • retry_count >= max_retries_per_dep — out of attempts

Global hard capmax_iterations in config (default: 20). When hit, the run ends regardless of how many deps remain. This is your cost guardrail — no surprise LLM bills from infinite loops.


The State Report

loopgrade writes loopgrade-state.md to your project root after every single dependency — win, lose, or skip. You can open it any time during a run and see live progress:

# loopgrade run — 2026-07-07 14:32

## Progress: 3/8 deps processed

## Upgraded 
- lodash: 4.17.19 → 4.17.21
- express: 4.17.1 → 4.18.2

## Upgraded with adjustment 
- numpy: 1.24.0 → 1.26.4 (wanted 2.0.0, constrained by scipy==1.11.0)
## Failed / Skipped 
- webpack: 4.46.0 → 5.91.0
  reason: hard conflict — html-webpack-plugin 4.x requires webpack<5
  suggestion: upgrade html-webpack-plugin to 5.x first, then retry webpack
- axios: 0.27.0 → 1.7.2
  reason: 3 attempts failed — response structure migration needed in code
  suggestion: update all axios call sites to use new response format before upgrading

## Remaining
- dotenv, jest, eslint, prettier, typescript

Installation

Prerequisites

  • Python 3.10+
  • Git initialized in your project (git init)
  • Your test suite must pass before running loopgrade (npm test or pytest exits 0)
  • For npm projects: npm-check-updates installed globally (npm install -g npm-check-updates)
  • A Groq or Gemini API key (both have free tiers)

Install loopgrade

pip install loopgrade

Or install from source:

git clone https://github.com/yourusername/loopgrade
cd loopgrade
pip install -e .

Quick Start

# 1. go to your project
cd my-project

# 2. initialize loopgrade (creates config + .env)
loopgrade init

# 3. add your API key to .env
echo "GROQ_API_KEY=your_key_here" >> .env

# 4. run it
loopgrade run

Note: The default configuration assumes a Node.js project (npm test). If you are using Python, be sure to edit loopgrade.config.json and change "package_manager": "pip" and "test_command": "pytest" (or whatever you use for testing) before running loopgrade run.

That's it. loopgrade will scan your deps, upgrade them one at a time, and report back.


CLI Reference

loopgrade init

Creates loopgrade.config.json and .env in your current directory with sensible defaults.

loopgrade init

loopgrade run

Runs the full autonomous upgrade loop.

loopgrade run                          # standard run
loopgrade run --dry-run                # show what would be upgraded, no changes
loopgrade run --only axios             # upgrade one specific package
loopgrade run --config path/to/config  # use a different config file

Before starting, loopgrade validates:

  • A git repo exists in the current directory
  • Your test suite currently passes (if tests are already failing, loopgrade won't run — fix them first)

loopgrade status

Pretty-prints the current loopgrade-state.md with rich formatting.

loopgrade status

Configuration Reference

loopgrade.config.json — place this in your project root.

{
  "llm_provider": "groq",
  "model": "llama-3.3-70b-versatile",
  "max_iterations": 20,
  "max_retries_per_dep": 3,
  "package_manager": "npm",
  "test_command": "npm test",
  "skip_major_versions": false,
  "skip": []
}
Field Type Default Description
llm_provider string "groq" LLM provider to use. Options: "groq", "gemini"
model string "llama-3.3-70b-versatile" Model name. See provider docs for options
max_iterations int 20 Hard cap on total iterations across all deps. Your cost guardrail
max_retries_per_dep int 3 Max attempts per dependency before skipping
package_manager string "npm" Package manager. Options: "npm", "pip"
test_command string "npm test" Command loopgrade runs to verify each upgrade
skip_major_versions bool false If true, skip any dep with a major version bump
skip array [] List of package names to skip entirely e.g. ["react", "typescript"]

Environment Variables

Create a .env file in your project root (loopgrade reads it automatically):

# use one of these depending on your configured provider
GROQ_API_KEY=your_groq_key_here
GEMINI_API_KEY=your_gemini_key_here

Getting API keys:


Supported Package Managers

Package manager Dep file Install command Test discovery
npm package.json npm install configured via test_command
pip requirements.txt pip install -r requirements.txt configured via test_command

More package managers (yarn, pnpm, poetry, cargo) are planned — contributions welcome.


Why loopgrade over just running ncu -u?

ncu -u loopgrade
Upgrades all deps at once Yes
Tests after each upgrade Yes
Reverts on failure Yes
Attributes which dep broke things Yes
Detects version conflicts before trying Yes
Finds safe version ceiling for conflicts Yes
Explains why something failed Yes
Suggests manual steps for hard failures Yes
Your codebase always left in working state Yes

Project Structure

loopgrade/
├── loopgrade/
│   ├── cli.py                  # typer CLI — run / init / status
│   ├── config.py               # load + validate loopgrade.config.json
│   ├── agents/
│   │   ├── __init__.py
│   │   ├── graph.py            # LangGraph graph assembly + routing
│   │   ├── state.py            # LoopgradeState TypedDict
│   │   └── nodes/
│   │       ├── __init__.py
│   │       ├── scan.py         # scan_deps node
│   │       ├── pick.py         # pick_next node
│   │       ├── upgrade_node.py # upgrade_node — pre-upgrade LLM call
│   │       ├── upgrade.py      # run_upgrade node
│   │       ├── test.py         # run_tests node
│   │       ├── verifier_node.py# verifier_node — post-test LLM call
│   │       ├── commit.py       # commit_success node
│   │       ├── revert.py       # revert_dep node
│   │       ├── skip.py         # skip_dep node
│   │       ├── state_writer.py # write_state node
│   │       ├── conflict_check.py
│   │       └── conflict_resolve.py
│   │
│   ├── tools/
│   │   ├── registry.py         # get latest versions from npm / PyPI
│   │   ├── files.py            # edit package.json / requirements.txt
│   │   ├── runner.py           # run install + test commands
│   │   ├── git.py              # commit / revert
│   │   └── conflicts.py        # dry-run conflict detection + safe version finder
│   │
│   └── providers/
│       ├── base.py             # abstract LLM interface
│       ├── groq.py             # Groq implementation
│       └── gemini.py           # Gemini implementation
│
└── test-fixtures/
    ├── node-app/               # intentionally outdated Node app for testing loopgrade
    │   ├── package.json
    │   ├── index.js
    │   └── index.test.js
    └── python-app/             # intentionally outdated Python app for testing loopgrade
        ├── requirements.txt
        ├── main.py
        └── test_main.py

Further Reading


Contributing

Contributions are welcome — especially:

  • Additional package manager support (yarn, pnpm, poetry, cargo)
  • Additional LLM providers (OpenAI, Ollama for local models)
  • Better conflict resolution strategies
  • CI/CD integration (GitHub Actions support)

To get started:

git clone https://github.com/yourusername/loopgrade
cd loopgrade
pip install -e ".[dev]"

# run tests against the fixtures
cd test-fixtures/node-app && npm install && npm test
cd test-fixtures/python-app && pip install -r requirements.txt && pytest

Please open an issue before starting work on a large feature so we can align on the approach.


Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

loopgrade-0.1.0.tar.gz (27.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

loopgrade-0.1.0-py3-none-any.whl (30.8 kB view details)

Uploaded Python 3

File details

Details for the file loopgrade-0.1.0.tar.gz.

File metadata

  • Download URL: loopgrade-0.1.0.tar.gz
  • Upload date:
  • Size: 27.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for loopgrade-0.1.0.tar.gz
Algorithm Hash digest
SHA256 df7eb45c36211d0c6362ec26da7e9a26472c7a3706deb1ffaa3573d5985f2bd3
MD5 e3e68183893c355a5b8b6036df876412
BLAKE2b-256 e300b1d5428b97c4fb7e563b5863be5a434c9ca0f791e0afe58dd1e2baf54338

See more details on using hashes here.

File details

Details for the file loopgrade-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: loopgrade-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 30.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for loopgrade-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4fc48accfd0831941c44f7262b90d6f9bac565fcf2e4d649157fc1694975446f
MD5 86bdc952dc08dd95ebe115bf889c230f
BLAKE2b-256 b3a74de4eb991ed308bfd9ad808635fd2071e50ac51bcdba3b62cfd2898533eb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page