> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Espacios de trabajo y monorepos

> Configura el Environment de Devin para monorepos, espacios de trabajo con varios paquetes y proyectos con subdirectorios independientes.

Los monorepos y los espacios de trabajo con varios paquetes requieren atención adicional en los blueprints, ya que distintos subdirectorios pueden usar diferentes lenguajes, gestores de paquetes o conjuntos de dependencias. Devin admite dos enfoques:

<CardGroup cols={2}>
  <Card title="Espacios de trabajo nativos (recomendado)" icon="cubes" href="#native-workspaces">
    Crea un blueprint independiente para cada subdirectorio. Cada espacio de trabajo tiene sus propias secciones de initialize, maintenance y Knowledge, con el directorio de trabajo configurado automáticamente en ese subdirectorio.
  </Card>

  <Card title="Subshells" icon="terminal" href="#subshells">
    Ejecuta comandos en subdirectorios dentro de un solo blueprint usando `(cd dir && command)`. Es una opción más sencilla para monorepos pequeños con solo unos pocos paquetes.
  </Card>
</CardGroup>

***

<div id="native-workspaces">
  ## Espacios de trabajo nativos
</div>

<Info>
  **Recomendado para la mayoría de los monorepos.** Los espacios de trabajo nativos asignan a cada subdirectorio su propio blueprint, con una configuración, Knowledge y un directorio de trabajo aislados. Esto es más limpio y más fácil de mantener que usar subshells a medida que aumenta la cantidad de packages.
</Info>

Con los espacios de trabajo nativos, cada subdirectorio tiene un blueprint dedicado. Los comandos de ese blueprint se ejecutan con el directorio de trabajo ya establecido en el subdirectorio, sin necesidad de `cd` ni de subshells.

<div id="the-root-blueprint">
  ### El blueprint raíz
</div>

Se espera que todo repo que use espacios de trabajo nativos tenga un **blueprint raíz**. El blueprint raíz se ejecuta desde la raíz del repositorio y lo hace **antes** que cualquier blueprint específico de un espacio de trabajo. Úsalo para la configuración compartida que se aplica a todo el repo: instalar entornos de ejecución, herramientas globales o realizar instalaciones de dependencias en la raíz.

```yaml theme={null}
# Plantilla raíz — se ejecuta primero, desde la raíz del repositorio
initialize: |
  npm install -g pnpm

maintenance: |
  pnpm install
```

Los blueprints del espacio de trabajo se encargan luego de la configuración específica de cada paquete y se ejecutan una vez que se completa el blueprint raíz.

<div id="creating-a-workspace">
  ### Crear un workspace
</div>

1. Ve a **Settings > Environment > Blueprints**
2. Haz clic en el repositorio
3. Haz clic en **Agregar workspace**
4. Ingresa la ruta del subdirectorio (p. ej., `packages/frontend`)
5. Escribe el blueprint para ese workspace

<Warning>
  La ruta del workspace debe corresponder a un directorio real dentro del repositorio. Si la ruta no existe cuando se ejecute la compilación, la compilación fallará. Verifica que la ruta coincida exactamente con la estructura de tu repo (p. ej., `packages/frontend`, no `pkg/frontend`).
</Warning>

<div id="example">
  ### Ejemplo
</div>

Un monorepo con un frontend en React y un backend en Python. El blueprint raíz instala herramientas compartidas, y luego cada workspace gestiona sus propias dependencias:

<Tabs>
  <Tab title="Raíz">
    ```yaml theme={null}
    # Blueprint raíz: configuración compartida para todo el repo
    initialize: |
      npm install -g pnpm
      curl -LsSf https://astral.sh/uv/install.sh | sh

    knowledge:
      - name: structure
        contents: |
          Monorepo con dos packages:
          - packages/frontend — aplicación React (TypeScript, pnpm)
          - packages/backend — API de Python (FastAPI, uv)
    ```
  </Tab>

  <Tab title="packages/frontend">
    ```yaml theme={null}
    # Workspace con ámbito en packages/frontend
    maintenance: |
      pnpm install

    knowledge:
      - name: lint
        contents: pnpm lint
      - name: test
        contents: pnpm test
      - name: dev
        contents: pnpm dev
    ```
  </Tab>

  <Tab title="packages/backend">
    ```yaml theme={null}
    # Workspace con ámbito en packages/backend
    maintenance: |
      uv sync

    knowledge:
      - name: lint
        contents: uv run ruff check .
      - name: test
        contents: uv run pytest
      - name: dev
        contents: uv run uvicorn app.main:app --reload
    ```
  </Tab>
</Tabs>

Las entradas de `knowledge` de cada workspace se limitan a ese subdirectorio. Cuando Devin trabaja en `packages/frontend`, ve los comandos de lint/test/dev del frontend, no los del backend.

<div id="when-to-use-native-workspaces">
  ### Cuándo usar workspaces nativos
</div>

* Los subdirectorios tienen **lenguajes o gestores de paquetes diferentes**
* Cada paquete necesita sus propias **entradas de Knowledge** (comandos de lint, test y compilación)
* Quieres una **configuración aislada** — si un blueprint falla en un workspace, no bloquea a los demás
* El número de paquetes está creciendo y un solo blueprint se está volviendo difícil de gestionar

***

<div id="subshells">
  ## Subshells
</div>

Para monorepos más sencillos, puedes gestionar todo en un único blueprint usando subshells. Encierra los comandos entre paréntesis para ejecutarlos en un subdirectorio sin afectar a los pasos posteriores:

```yaml theme={null}
maintenance:
  - name: Frontend deps
    run: (cd packages/frontend && pnpm install)
  - name: Backend deps
    run: (cd packages/backend && uv sync)
```

Los paréntesis `(cd ... && ...)` crean un subshell. Cuando el subshell termina, el directorio de trabajo vuelve a la raíz del repositorio para el siguiente paso.

<Warning>
  Sin paréntesis, `cd` cambia el directorio de trabajo en todos los pasos posteriores. Usa siempre subshells al cambiar de directorio en los pasos de blueprint.
</Warning>

<div id="why-subshells-matter">
  ### Por qué importan los subshells
</div>

Compara estos dos enfoques:

<Tabs>
  <Tab title="Correcto (con subshells)">
    ```yaml theme={null}
    maintenance:
      - name: Frontend deps
        run: (cd packages/frontend && pnpm install)
      - name: Backend deps
        run: (cd packages/backend && uv sync)
    ```

    Cada paso se ejecuta desde la raíz del repositorio. Ambos comandos encuentran el subdirectorio correcto dentro de `packages/`.
  </Tab>

  <Tab title="Incorrecto (sin subshells)">
    ```yaml theme={null}
    maintenance:
      - name: Frontend deps
        run: cd packages/frontend && pnpm install
      - name: Backend deps
        run: cd packages/backend && uv sync
    ```

    El primer paso cambia el directorio de trabajo a `packages/frontend`. Luego, el segundo paso intenta ejecutar `cd packages/backend` relativo a `packages/frontend`, lo que falla.
  </Tab>
</Tabs>

<div id="when-to-use-subshells">
  ### Cuándo usar subshells
</div>

* El monorepo tiene **unos pocos paquetes** con una configuración sencilla
* Todos los paquetes comparten el **mismo lenguaje y gestor de paquetes**
* No necesitas entradas de Knowledge específicas para cada paquete

***

<div id="knowledge-entries-for-monorepos">
  ## Entradas de Knowledge para monorepos
</div>

Tanto si usas workspaces nativos como subshells, unas entradas de Knowledge bien estructuradas ayudan a Devin a orientarse en la base de código:

```yaml theme={null}
knowledge:
  - name: structure
    contents: |
      This is a monorepo with three packages:
      - `packages/frontend` — React app (TypeScript, pnpm)
      - `packages/backend` — Python API (FastAPI, uv)
      - `packages/shared` — Shared TypeScript utilities
  - name: frontend
    contents: |
      cd packages/frontend
      Dev server: pnpm dev
      Lint: pnpm lint
      Test: pnpm test
  - name: backend
    contents: |
      cd packages/backend
      Dev server: uv run uvicorn app.main:app --reload
      Lint: uv run ruff check .
      Test: uv run pytest
```

<Tip>
  Una entrada de conocimiento `structure` que asigne a cada directorio su lenguaje de programación y toolchain ayuda a Devin a navegar por el repo rápidamente. Con los workspaces nativos, cada workspace tiene sus propias entradas de conocimiento, por lo que la entrada `structure` resulta más útil en el blueprint raíz o en configuraciones basadas en subshells.
</Tip>

<div id="examples">
  ## Ejemplos
</div>

<div id="turborepo-nx-workspace">
  ### workspace de Turborepo / Nx
</div>

Para workspaces gestionados con una herramienta de compilación para monorepos como Turborepo o Nx, instala las dependencias en la raíz y deja que la herramienta se encargue de la orquestación de cada paquete:

```yaml theme={null}
initialize: |
  npm install -g pnpm turbo

maintenance: |
  pnpm install

knowledge:
  - name: structure
    contents: |
      Turborepo monorepo. Use `turbo` for building and testing:
      - `apps/web` — Next.js app
      - `apps/api` — Express API
      - `packages/ui` — Shared component library
      - `packages/config` — Shared configuration
  - name: build
    contents: turbo run build
  - name: test
    contents: turbo run test
  - name: lint
    contents: turbo run lint
  - name: dev
    contents: turbo run dev
```

<div id="multiple-jdk-versions">
  ### Múltiples versiones de JDK
</div>

Un monorepo de Java en el que distintos servicios requieren distintas versiones de JDK:

```yaml theme={null}
initialize:
  - name: Install JDK 17 (primary)
    run: |
      sudo apt-get update -qq
      sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openjdk-17-jdk-headless
      echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' \
        | sudo tee /etc/profile.d/java.sh > /dev/null

  - name: Install JDK 11 (legacy service)
    run: |
      sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openjdk-11-jdk-headless

maintenance:
  - name: Warm dependency caches
    run: |
      export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
      (cd services/api && ./gradlew dependencies --refresh-dependencies)

      export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
      (cd services/legacy && ./gradlew dependencies --refresh-dependencies)

knowledge:
  - name: build_api
    contents: |
      Build the API service (JDK 17):
        JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 \
        cd services/api && ./gradlew clean build
  - name: build_legacy
    contents: |
      Build the legacy service (JDK 11):
        JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 \
        cd services/legacy && ./gradlew clean build
  - name: test_all
    contents: |
      Run tests for all services:
        JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 \
        (cd services/api && ./gradlew test)

        JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 \
        (cd services/legacy && ./gradlew test)
```

<div id="org-blueprint-for-shared-tools">
  ### Blueprint de org para herramientas compartidas
</div>

Si múltiples paquetes de un monorepo comparten las mismas herramientas, instálalas una sola vez en el blueprint de toda la organización:

```yaml theme={null}
# Blueprint de organización (Settings > Environment > Blueprints > configuración de la organización)
initialize:
  - name: Install pnpm
    run: npm install -g pnpm
  - name: Install uv
    run: curl -LsSf https://astral.sh/uv/install.sh | sh
  - name: Install shared build tools
    run: npm install -g turbo typescript
```

Así, cada blueprint del repo solo necesita comandos específicos del proyecto:

```yaml theme={null}
# Blueprint del repo (usa pnpm y uv del blueprint de org)
maintenance:
  - name: Install all workspace deps
    run: pnpm install
  - name: Install Python service deps
    run: (cd services/ml-pipeline && uv sync)
```

<div id="best-practices">
  ## Prácticas recomendadas
</div>

<AccordionGroup>
  <Accordion title="Prefiere workspaces nativos para monorepos complejos">
    Cuando cada subdirectorio tiene su propio lenguaje, gestor de paquetes o proceso de compilación, los workspaces nativos mantienen cada blueprint centrado e independiente. Reserva los subshells para casos sencillos con pocos paquetes.
  </Accordion>

  <Accordion title="Usa siempre subshells para los cambios de directorio">
    Cuando uses el enfoque de subshells, encierra los comandos `cd` entre paréntesis: `(cd dir && command)`. Esto evita que el cambio de directorio de un paso afecte al paso siguiente.
  </Accordion>

  <Accordion title="Pon las herramientas compartidas en el blueprint de org">
    Los entornos de ejecución y los gestores de paquetes que se usan en múltiples repos deben ir en el blueprint de toda la organización. Esto evita duplicaciones y mantiene los blueprints del repo centrados en la configuración específica del proyecto.
  </Accordion>

  <Accordion title="Ordena los pasos de maintenance según las dependencias">
    Si el paquete A depende de que el paquete B se compile primero, coloca el paso de compilación de B antes del paso de instalación de A en `maintenance`. Los pasos del blueprint se ejecutan secuencialmente en el orden en que aparecen.
  </Accordion>

  <Accordion title="Agrega una entrada de Knowledge sobre la estructura">
    Una entrada de Knowledge llamada `structure` que asigne directorios a sus lenguajes y herramientas ayuda a Devin a navegar por la base de código. Incluye qué gestor de paquetes usa cada subdirectorio y cualquier dependencia entre paquetes.
  </Accordion>

  <Accordion title="Usa entradas de Knowledge por paquete">
    En lugar de una sola entrada de Knowledge grande, crea entradas separadas para cada paquete (p. ej., `frontend`, `backend`, `ml-pipeline`). Con workspaces nativos, cada workspace ya incluye su propia sección de Knowledge.
  </Accordion>

  <Accordion title="Mantén maintenance incremental">
    Usa `pnpm install` (no `pnpm install --force`) y `uv sync` (no `rm -rf .venv && uv sync`). Los comandos incrementales son más rápidos durante las reconstrucciones periódicas.
  </Accordion>
</AccordionGroup>

<div id="related-pages">
  ## Páginas relacionadas
</div>

* [Configuración declarativa de Environment](/es/onboard-devin/environment/blueprints)
* [Referencia de blueprint](/es/onboard-devin/environment/blueprint-reference)
* [Biblioteca de plantillas](/es/onboard-devin/environment/templates) — incluye plantillas de monorepo listas para usar
