commit 41e2c110ba1d7cfc7e5470df2e5f60d07ed3fd32 Author: Amolith Date: Wed Jul 16 09:07:06 2025 -0600 feat: add initial llm-fragments-repomix plugin Add plugin that loads repository contents using Repomix: - Clone git repositories to temporary directories - Run repomix to generate AI-friendly repository summaries - Return repomix output as a single fragment - Clean up temporary directories automatically diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..d68201d156d15ddef78679c013bc46df45bdd0f8 --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +# llm-fragments-repomix + +A plugin for [LLM](https://llm.datasette.io/) that loads repository contents as fragments using [Repomix](https://github.com/yamadashy/repomix). + +## Installation + +First, install the plugin: + +```bash +pip install llm-fragments-repomix +``` + +Make sure you have `repomix` installed: + +```bash +npm install -g repomix +``` + +## Usage + +Use the `repomix:` prefix with a full git repository URL: + +```bash +llm -f repomix:https://git.sr.ht/~amolith/willow "Tell me about this project" +``` + +```bash +llm -f repomix:ssh://git.sr.ht:~amolith/willow "Analyze the code structure" +``` + +The plugin will: +1. Clone the repository to a temporary directory +2. Run repomix on the cloned repository +3. Return the repomix output as a single fragment +4. Clean up the temporary directory + +## Requirements + +- Python 3.9+ +- `git` command available in PATH +- `repomix` command available in PATH + +## Future Work + +Future versions may support: +- Passing repomix arguments (e.g., `--compress`, `--ignore`) +- Integration with other fragment loaders for repository shortcuts +- Configuration options for repomix behavior \ No newline at end of file diff --git a/llm_fragments_repomix.py b/llm_fragments_repomix.py new file mode 100644 index 0000000000000000000000000000000000000000..b7694de6a70eb8500d365705e4d16f18ba05a038 --- /dev/null +++ b/llm_fragments_repomix.py @@ -0,0 +1,85 @@ +from typing import List +import llm +import os +import pathlib +import subprocess +import tempfile +import shutil + + +@llm.hookimpl +def register_fragment_loaders(register): + register("repomix", repomix_loader) + + +def repomix_loader(argument: str) -> List[llm.Fragment]: + """ + Load repository contents as fragments using Repomix + + Argument is a git repository URL (https:// or ssh://) + Examples: + repomix:https://git.sr.ht/~amolith/willow + repomix:ssh://git.sr.ht:~amolith/willow + """ + if not argument.startswith(("https://", "ssh://", "git@")): + raise ValueError( + f"Repository URL must start with https://, ssh://, or git@ - got: {argument}" + ) + + # Check if repomix is available + if not shutil.which("repomix"): + raise ValueError( + "repomix command not found. Please install repomix first: " + "https://github.com/yamadashy/repomix" + ) + + # Create a temporary directory for the cloned repository + with tempfile.TemporaryDirectory() as temp_dir: + repo_path = pathlib.Path(temp_dir) / "repo" + + try: + # Clone the repository + subprocess.run( + ["git", "clone", "--depth=1", argument, str(repo_path)], + check=True, + capture_output=True, + text=True, + ) + + # Run repomix on the cloned repository + result = subprocess.run( + ["repomix", "--stdout", str(repo_path)], + check=True, + capture_output=True, + text=True, + ) + + # Create a single fragment with the repomix output + fragments = [ + llm.Fragment( + content=result.stdout, + source=f"repomix:{argument}" + ) + ] + + return fragments + + except subprocess.CalledProcessError as e: + # Handle Git or repomix errors + if "git" in str(e.cmd): + raise ValueError( + f"Failed to clone repository {argument}: {e.stderr}" + ) + elif "repomix" in str(e.cmd): + raise ValueError( + f"Failed to run repomix on {argument}: {e.stderr}" + ) + else: + raise ValueError( + f"Command failed: {e.stderr}" + ) + except Exception as e: + # Handle other errors + raise ValueError( + f"Error processing repository {argument}: {str(e)}" + ) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000000000000000000000000000000000..d07b1d52af475d7e29166fa124830c3d2c91eabf --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,26 @@ +[project] +name = "llm-fragments-repomix" +version = "0.1.0" +description = "Load repository contents as LLM fragments using Repomix" +readme = "README.md" +authors = [{name = "Amolith"}] +license = "Apache-2.0" +requires-python = ">=3.9" +dependencies = [ + "llm" +] + +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project.urls] +Homepage = "https://git.sr.ht/~amolith/llm-fragments-repomix" +Changelog = "https://git.sr.ht/~amolith/llm-fragments-repomix/refs" +Issues = "https://todo.sr.ht/~amolith/public-tracker" + +[project.entry-points.llm] +fragments_repomix = "llm_fragments_repomix" + +[project.optional-dependencies] +test = ["pytest"] \ No newline at end of file