> ## 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.

# Workspace e monorepo

> Configura l'ambiente di Devin per monorepo, workspace multi-package e progetti con sottodirectory indipendenti.

I monorepo e i workspace multi-package richiedono particolare attenzione nei blueprint, perché sottodirectory diverse possono usare linguaggi, gestori di pacchetti o set di dipendenze differenti. Devin supporta due approcci:

<CardGroup cols={2}>
  <Card title="Workspace nativi (consigliato)" icon="cubes" href="#native-workspaces">
    Crea un blueprint separato per ogni sottodirectory. Ogni workspace ha le proprie sezioni initialize, maintenance e Knowledge, con la directory di lavoro impostata automaticamente sulla sottodirectory corrispondente.
  </Card>

  <Card title="Subshells" icon="terminal" href="#subshells">
    Esegui i comandi nelle sottodirectory all'interno di un singolo blueprint usando `(cd dir && command)`. È più semplice per monorepo di piccole dimensioni con pochi package.
  </Card>
</CardGroup>

***

<div id="native-workspaces">
  ## Workspace nativi
</div>

<Info>
  **Consigliati per la maggior parte dei monorepo.** I workspace nativi forniscono a ogni sottodirectory il proprio blueprint, con setup, Knowledge e directory di lavoro isolati. Questa soluzione è più ordinata e più facile da mantenere rispetto ai subshells, man mano che aumenta il numero di package.
</Info>

Con i workspace nativi, ogni sottodirectory ha un blueprint dedicato. I comandi in quel blueprint vengono eseguiti con la directory di lavoro già impostata sulla sottodirectory, senza bisogno di `cd` o di subshells.

<div id="the-root-blueprint">
  ### Il blueprint radice
</div>

Ogni repo che usa workspace native deve avere un **blueprint radice**. Il blueprint radice viene eseguito dalla radice del repository **prima** di qualsiasi blueprint con ambito workspace. Usalo per la configurazione condivisa valida per l'intero repo — ad esempio per installare runtime, strumenti globali o le dipendenze a livello della radice.

```yaml theme={null}
# blueprint radice — viene eseguito per primo, dalla root del repo
initialize: |
  npm install -g pnpm

maintenance: |
  pnpm install
```

I blueprint del workspace gestiscono quindi la configurazione specifica del package e vengono eseguiti una volta completato il blueprint radice.

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

1. Vai a **Settings > Environment > Blueprints**
2. Fai clic sul repository
3. Fai clic su **Add workspace**
4. Inserisci il percorso della sottodirectory (ad es. `packages/frontend`)
5. Scrivi il blueprint per quel workspace

<Warning>
  Il percorso del workspace deve corrispondere a una directory reale all'interno del repository. Se il percorso non esiste quando viene eseguita la build, la build fallirà. Verifica attentamente che il percorso corrisponda esattamente alla struttura del tuo repo (ad es. `packages/frontend`, non `pkg/frontend`).
</Warning>

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

Un monorepo con un frontend React e un backend Python. Il blueprint radice installa gli strumenti condivisi, poi ogni workspace gestisce le proprie dipendenze:

<Tabs>
  <Tab title="Root">
    ```yaml theme={null}
    # blueprint radice — configurazione condivisa per l'intera repo
    initialize: |
      npm install -g pnpm
      curl -LsSf https://astral.sh/uv/install.sh | sh

    knowledge:
      - name: structure
        contents: |
          Monorepo con due package:
          - packages/frontend — app React (TypeScript, pnpm)
          - packages/backend — API Python (FastAPI, uv)
    ```
  </Tab>

  <Tab title="packages/frontend">
    ```yaml theme={null}
    # Workspace nell'ambito di 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 nell'ambito di 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>

Le voci `knowledge` di ciascun workspace sono limitate a quella sottodirectory. Quando Devin lavora in `packages/frontend`, vede i comandi lint/test/dev del frontend, non quelli del backend.

<div id="when-to-use-native-workspaces">
  ### Quando usare i workspace nativi
</div>

* Le sottodirectory usano **linguaggi o gestori di pacchetti diversi**
* Ogni package ha bisogno di proprie **voci di Knowledge** (comandi di lint, test, build)
* Vuoi una **configurazione isolata** — un blueprint non funzionante in un workspace non blocca gli altri
* Il numero di package è in crescita e un singolo blueprint sta diventando difficile da gestire

***

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

Per i monorepo più semplici, puoi gestire tutto all'interno di un unico blueprint tramite subshell. Racchiudi i comandi tra parentesi per eseguirli in una sottodirectory senza influire sui passaggi successivi:

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

Le parentesi `(cd ... && ...)` creano una subshell. Quando la subshell termina, la directory di lavoro torna alla radice della repo per il passaggio successivo.

<Warning>
  Senza parentesi, `cd` cambia la directory di lavoro per tutti i passaggi successivi. Usa sempre le subshell quando cambi directory nei passaggi di Blueprint.
</Warning>

<div id="why-subshells-matter">
  ### Perché le subshell sono importanti
</div>

Confronta questi due approcci:

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

    Ogni passaggio viene eseguito dalla radice della repo. Entrambi i comandi trovano la sottodirectory `packages/` corretta.
  </Tab>

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

    Il primo passaggio cambia la directory di lavoro in `packages/frontend`. Il secondo passaggio cerca quindi di eseguire `cd packages/backend` partendo da `packages/frontend`, quindi fallisce.
  </Tab>
</Tabs>

<div id="when-to-use-subshells">
  ### Quando usare le subshell
</div>

* Il monorepo ha **pochi pacchetti** con una configurazione semplice
* Tutti i pacchetti condividono **lo stesso linguaggio di programmazione e lo stesso gestore di pacchetti**
* Non sono necessarie voci di Knowledge per singolo pacchetto

***

<div id="knowledge-entries-for-monorepos">
  ## Voci di Knowledge per i monorepo
</div>

Che tu usi workspace nativi o subshell, delle voci di Knowledge ben strutturate aiutano Devin a orientarsi nel codebase:

```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 voce di Knowledge `structure` che associa ogni directory al relativo linguaggio e alla relativa toolchain aiuta Devin a orientarsi rapidamente nel repo. Con i workspace nativi, ogni workspace ha le proprie voci di Knowledge, quindi la voce `structure` è particolarmente utile nel blueprint di root o per configurazioni basate su subshell.
</Tip>

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

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

Per i workspace gestiti da uno strumento di build monorepo come Turborepo o Nx, installa le dipendenze alla radice e lascia che lo strumento gestisca l'orchestrazione dei singoli pacchetti:

```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">
  ### Più versioni del JDK
</div>

Un monorepo Java in cui servizi diversi richiedono versioni diverse del 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 dell'org per gli strumenti condivisi
</div>

Quando più package di un monorepo condividono gli stessi strumenti, installali una sola volta nel blueprint per tutta l'org:

```yaml theme={null}
# Blueprint per tutta l'org (Settings > Environment > Blueprints > Org-wide setup)
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
```

In questo modo, ogni blueprint del repo deve includere solo i comandi specifici del progetto:

```yaml theme={null}
# Repo blueprint (usa pnpm e uv dall'org blueprint)
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">
  ## Buone pratiche
</div>

<AccordionGroup>
  <Accordion title="Preferisci workspace nativi per i monorepo complessi">
    Quando ogni sottodirectory ha il proprio linguaggio, gestore di pacchetti o processo di build, i workspace nativi mantengono ogni blueprint focalizzato e indipendente. Riserva le subshell ai casi semplici con pochi pacchetti.
  </Accordion>

  <Accordion title="Usa sempre le subshell per i cambi di directory">
    Quando usi l'approccio basato su subshell, racchiudi i comandi `cd` tra parentesi: `(cd dir && command)`. Questo impedisce che il cambio di directory di un passaggio influisca su quello successivo.
  </Accordion>

  <Accordion title="Metti gli strumenti condivisi nel blueprint dell'org">
    I runtime dei linguaggi e i gestori di pacchetti usati in più repo appartengono al blueprint per tutta l'org. Questo evita duplicazioni e mantiene i blueprint delle repo focalizzati sulla configurazione specifica del progetto.
  </Accordion>

  <Accordion title="Ordina i passaggi di maintenance in base alle dipendenze">
    Se il pacchetto A dipende dal fatto che il pacchetto B venga compilato per primo, elenca il passaggio di build di B prima del passaggio di installazione di A in `maintenance`. I passaggi del blueprint vengono eseguiti in sequenza nell'ordine indicato.
  </Accordion>

  <Accordion title="Aggiungi una voce di Knowledge sulla struttura">
    Una voce di Knowledge chiamata `structure`, che associa le directory ai rispettivi linguaggi e strumenti, aiuta Devin a orientarsi nella codebase. Includi quale gestore di pacchetti usa ogni sottodirectory ed eventuali dipendenze tra pacchetti.
  </Accordion>

  <Accordion title="Usa voci di Knowledge per pacchetto">
    Invece di un'unica grande voce di Knowledge, crea voci separate per ogni pacchetto (ad es. `frontend`, `backend`, `ml-pipeline`). Con i workspace nativi, ogni workspace include già la propria sezione Knowledge.
  </Accordion>

  <Accordion title="Mantieni incrementale la sezione maintenance">
    Usa `pnpm install` (non `pnpm install --force`) e `uv sync` (non `rm -rf .venv && uv sync`). I comandi incrementali sono più veloci durante le ricostruzioni periodiche.
  </Accordion>
</AccordionGroup>

<div id="related-pages">
  ## Pagine correlate
</div>

* [Configurazione dichiarativa dell'ambiente](/it/onboard-devin/environment/blueprints)
* [Riferimento del blueprint](/it/onboard-devin/environment/blueprint-reference)
* [Libreria dei template](/it/onboard-devin/environment/templates) — con template monorepo pronti all'uso
