logo

Comparte tu código fácilmente con Claude Projects y ChatGPT

Integra tu repositorio completo en tu asistente de IA favorito con un solo paso

23 de enero de 2025

Si has usado herramientas como Claude o ChatGPT al desarrollar o analizar código, probablemente te hayas encontrado con un problema común: subir tu repositorio. Con uno o dos archivos es sencillo, pero a menudo quieres dar al LLM una vista global de todo tu repositorio para poder hacer preguntas, corregir errores e incluso desarrollar nuevas funcionalidades.

Para subir un repositorio completo a un asistente de IA, hay dos grandes obstáculos:

Sin una solución sencilla a estas cuestiones, trabajar con LLMs en proyectos complejos se vuelve tedioso y lento. Tener que subir cada archivo individualmente y luego explicar la estructura del proyecto es demasiado ineficiente. Tiene que haber una mejor manera...

La inspiración para resolver esto la encontré en la reciente entrevista de Greg Kamradt con Nicole Hedley de Headstart (si no conoces el canal de YouTube de Greg, échale un vistazo: tiene un contenido y entrevistas muy interesantes sobre IA). Durante la entrevista, Nicole explica cómo utiliza Claude Projects en su trabajo diario como desarrolladora y menciona el uso de un script que simplifica la subida de repositorios al LLM.

Es una solución muy simple e inteligente. Un script que toma tu repositorio y crea una versión "plana" con todos los archivos en un único directorio, pero con sus rutas originales incluidas en los nombres de los archivos. Por ejemplo, tomemos esta estructura de un proyecto React:

my-app/
├── src/
│ ├── components/
│ │ └── Button.jsx
│ └── utils/
│ └── validation.js
└── package.json

El script lo transforma en:

my-app_flat/
├── src__components__Button.jsx
├── src__utils__validation.js
├── tests__Button.test.js
└── package.json

Y ahora solo tienes que arrastrar y soltar estos archivos en Claude Projects o ChatGPT (o cualquier otra herramienta LLM que estés usando). En cuestión de segundos, puedes empezar a analizar y explorar tu repositorio completo con el LLM, que mantiene el contexto completo de la estructura de tu proyecto.

Por supuesto, ya existen herramientas más avanzadas como Cursor y GitHub Copilot con integración directa de LLMs en tu editor de código. Pero a veces es preferible un enfoque más simple que te permita analizar tu código directamente en Claude o ChatGPT, con control total y transparencia sobre tus prompts y los archivos que incluyes en el contexto. Aquí es donde esta solución resulta realmente útil.

Inspirado por la idea de Nicole, he creado una versión del script en Python, que puedes encontrar en este repositorio de GitHub. En la siguiente sección, explicaré cómo funciona el código y te mostraré cómo usarlo en tus propios proyectos.

#Cómo funciona el script

Veamos los detalles de implementación del script. El código es bastante simple, son menos de 150 líneas de código en total. Y puedes adaptarlo fácilmente a tus necesidades concretas.

El script comienza con un conjunto de variables de configuración que permiten personalizarlo. Estas variables indican qué se debe incluir o excluir al crear la versión "plana" del repositorio:

EXCLUDED_DIRS = {
'node_modules', '.git', '.venv', 'venv', '__pycache__', 'dist', 'build', 'data'
}

EXCLUDED_FILES = {
'.gitignore', '.DS_Store', 'package-lock.json', 'yarn.lock', 'uv.lock', '__init__.py',
'.env', '.env.local', '.env.development', '.env.production', '.env.test', '.env.staging'
}

EXCLUDED_EXTENSIONS = {
'.pyc', '.pyo', '.lock', '.log', '.map', '.pdf', '.jpg', '.jpeg', '.png',
'.gif', '.ico', '.svg',
}

# Default included extensions for Python/JavaScript projects
DEFAULT_INCLUDED_EXTENSIONS = {
'.py', '.js', '.jsx', '.ts', '.tsx', # Source code
'.json', '.yaml', '.yml', '.toml', # Config files
'.md', '.txt', '.rst' # Documentation
}

Lo normal es que no quieras incluir directorios y archivos como node_modules/, .git/, .venv/, package-lock.json, imágenes, variables de entorno, archivos binarios, etc. Van a ocupar mucho espacio de la ventana de contexto del LLM y no son relevantes para el código. El script los excluye automáticamente.

Como generalmente trabajo con Python y JavaScript, he ajustado las variables de configuración para estos entornos. Pero si usas otros lenguajes y tecnologías, puedes ajustarlas según tus necesidades.

La función principal del script es flatten_repository. Toma un directorio de origen y crea una nueva versión "plana" con el sufijo _flat. Así, si lo ejecutas sobre my-project, obtendrás un nuevo directorio my-project_flat justo al lado, que contiene todos los archivos relevantes en una estructura plana.

Dentro de esta función, hay un simple bucle que procesa tu repositorio:

for file_path in source_dir.rglob('*'):
if file_path.is_dir():
continue

if not should_include_file(file_path, include_all_extensions):
continue

# Create new filename using original path
rel_path = str(file_path.relative_to(source_dir))
flat_filename = encode_path_as_filename(rel_path)

# Check for collisions
if flat_filename in processed_files:
print(f"Warning: Duplicate file name detected: {rel_path}", file=sys.stderr)
continue

processed_files.add(flat_filename)

# Copy file to output directory
try:
shutil.copy2(file_path, output_dir / flat_filename)
print(f"Copied: {rel_path}")
except Exception as e:
print(f"Error copying {rel_path}: {e}", file=sys.stderr)

Este bucle hace varias cosas. Primero, omite los directorios ya que solo queremos procesar archivos. Luego, usa las reglas de inclusión/exclusión para validar cada archivo. Para los archivos que las cumplan, crea un nuevo nombre de archivo que preserva la estructura de ruta original, verifica si hay conflictos de nombres y finalmente copia el archivo a la versión "plana" del repositorio.

La lógica que decide qué archivos incluir está en la función should_include_file, que aplica nuestras reglas de configuración:

def should_include_file(path: Path, include_all_extensions: bool) -> bool:
"""Determine if a file should be included in the flattened output."""
# Check if path contains excluded directories
if any(part in EXCLUDED_DIRS for part in path.parts):
return False

# Check if filename is in excluded files
if path.name in EXCLUDED_FILES:
return False

# Check if extension is excluded
if path.suffix.lower() in EXCLUDED_EXTENSIONS:
return False

# If include_all_extensions is True, include all non-excluded files
# Otherwise, check if extension is in DEFAULT_INCLUDED_EXTENSIONS
return include_all_extensions or path.suffix.lower() in DEFAULT_INCLUDED_EXTENSIONS

¿Y cómo codificamos la ruta de cada archivo en su nombre? Con esta sencilla línea:

def encode_path_as_filename(path: str) -> str:
"""Convert a file path into a filename that preserves the path structure."""
return path.replace('/', FILENAME_PATH_SEPARATOR)

El script utiliza dobles guiones bajos (__) como separador de ruta en los nombres de archivo, porque el carácter / no suele ser válido en muchos sistemas operativos. Cuando el script ve un archivo como src/components/Button.jsx, lo convierte en src__components__Button.jsx. Puedes personalizar este separador modificando la variable de configuración FILENAME_PATH_SEPARATOR.

#Cómo usar el script

Para usarlo, navega al directorio que contiene flatten_repo.py y ejecuta:

python flatten_repo.py /path/to/your/project

El script acepta dos argumentos:

Pero hay una manera mucho más cómoda de usar el script: configurarlo como un comando global. Así es como lo he configurado en macOS:

  1. Haz el script ejecutable:

    chmod +x flatten_repo.py
  2. Crea un enlace simbólico (o una copia) en el directorio "bin" de tu sistema:

    ln -s /path/to/flatten_repo.py /usr/local/bin/flatten-repo

¡Ahora ya puedes ejecutar el comando flatten-repo directamente desde cualquier repositorio!

Nota: En Linux, el proceso es esencialmente el mismo. En Windows, necesitas añadir la carpeta del script a tu PATH o crear un archivo batch que llame al script.

Veamos el script en acción en un repositorio de una aplicación full-stack que contiene un backend en Python y un frontend en React:

Resultado del script en acción

Resultado del script en acción

Con esta herramienta, puedes preparar fácilmente cualquier repositorio para analizarlo con IA y simplemente arrastrarlo a tu asistente de IA favorito.

Y como mencioné antes, puedes encontrar el script en este repositorio de GitHub. ¡Espero que te resulte útil!