Skip to main content

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.

Monorepos e workspaces com vários pacotes exigem cuidado extra em blueprints, porque diferentes subdiretórios podem usar linguagens, gerenciadores de pacotes ou conjuntos de dependências distintos. Devin oferece suporte a duas abordagens:

Workspaces nativos (recomendado)

Crie um blueprint separado para cada subdiretório. Cada workspace recebe suas próprias seções initialize, maintenance e knowledge, com o diretório de trabalho definido automaticamente para o subdiretório.

Subshells

Execute comandos em subdiretórios dentro de um único blueprint usando (cd dir && command). Mais simples para monorepos pequenos com apenas alguns pacotes.

Workspaces nativos

Recomendado para a maioria dos monorepos. Workspaces nativos dão a cada subdiretório seu próprio blueprint, com configuração, Knowledge e diretório de trabalho isolados. Isso é mais organizado e mais fácil de manter do que usar subshells à medida que o número de pacotes cresce.
Com workspaces nativos, cada subdiretório recebe um blueprint dedicado. Os comandos nesse blueprint são executados com o diretório de trabalho já definido para o subdiretório — não é necessário usar cd nem subshells.

O blueprint raiz

Todo repositório que usa workspaces nativos deve ter um blueprint raiz. O blueprint raiz é executado a partir da raiz do repositório e antes de qualquer blueprint com escopo de workspace. Use-o para configurações compartilhadas que se aplicam a todo o repositório — como instalar runtimes, ferramentas globais ou executar instalações de dependências na raiz.
# Blueprint raiz — executado primeiro, a partir da raiz do repositório
initialize: |
  npm install -g pnpm

maintenance: |
  pnpm install
Os blueprints de workspace então cuidam da configuração específica do pacote e são executados depois que o blueprint raiz é concluído.

Como criar um workspace

  1. Vá para Configurações > Ambiente > Blueprints
  2. Clique no repositório
  3. Clique em Add workspace
  4. Insira o caminho do subdiretório (por exemplo, packages/frontend)
  5. Defina o blueprint para esse workspace
O caminho do workspace deve corresponder a um diretório real dentro do repositório. Se o caminho não existir quando o build for executado, o build falhará. Verifique se o caminho corresponde exatamente à estrutura do seu repositório (por exemplo, packages/frontend, não pkg/frontend).

Exemplo

Um monorepo com frontend em React e backend em Python. O blueprint raiz instala ferramentas compartilhadas, e cada workspace gerencia as próprias dependências:
# Blueprint raiz — configuração compartilhada para todo o repo
initialize: |
  npm install -g pnpm
  curl -LsSf https://astral.sh/uv/install.sh | sh

knowledge:
  - name: structure
    contents: |
      Monorepo com dois packages:
      - packages/frontend — app React (TypeScript, pnpm)
      - packages/backend — API Python (FastAPI, uv)
As entradas de knowledge de cada workspace são limitadas a esse subdiretório. Quando Devin trabalha em packages/frontend, ele vê os comandos de lint/test/dev do frontend — não os do backend.

Quando usar workspaces nativos

  • Os subdiretórios têm linguagens ou gerenciadores de pacotes diferentes
  • Cada pacote precisa de suas próprias entradas do Knowledge (comandos de lint, teste e build)
  • Você quer uma configuração isolada — um blueprint com problema em um workspace não bloqueia os demais
  • O número de pacotes está crescendo, e um único blueprint está ficando difícil de manter

Subshells

Para monorepos mais simples, você pode gerenciar tudo em um único blueprint usando subshells. Coloque os comandos entre parênteses para executá-los em um subdiretório sem afetar as etapas seguintes:
maintenance:
  - name: Frontend deps
    run: (cd packages/frontend && pnpm install)
  - name: Backend deps
    run: (cd packages/backend && uv sync)
Os parênteses (cd ... && ...) criam uma subshell. Quando a subshell é encerrada, o diretório de trabalho volta para a raiz do repositório na próxima etapa.
Sem parênteses, cd altera o diretório de trabalho de todas as etapas subsequentes. Sempre use subshells ao alternar diretórios em etapas de blueprint.

Por que os subshells são importantes

Compare estas duas abordagens:
maintenance:
  - name: Frontend deps
    run: (cd packages/frontend && pnpm install)
  - name: Backend deps
    run: (cd packages/backend && uv sync)
Cada etapa é executada a partir da raiz do repositório. Ambos os comandos encontram o subdiretório packages/ correto.

Quando usar subshells

  • O monorepo tem alguns pacotes com configuração simples
  • Todos os pacotes usam a mesma linguagem e o mesmo gerenciador de pacotes
  • Você não precisa de entradas de Knowledge para cada pacote

Entradas de Knowledge para monorepos

Se você usa workspaces nativos ou subshells, entradas de Knowledge bem estruturadas ajudam Devin a navegar pela base de código:
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
Uma entrada structure do Knowledge que mapeia cada diretório para sua linguagem e toolchain ajuda o Devin a navegar pelo repo rapidamente. Com workspaces nativos, cada workspace tem suas próprias entradas do Knowledge, então a entrada structure é mais útil no blueprint raiz ou em configurações baseadas em subshell.

Exemplos

Turborepo / Nx workspace

Para workspaces gerenciados por uma ferramenta de build de monorepo, como Turborepo ou Nx, instale as dependências na raiz e deixe a ferramenta cuidar da orquestração de cada pacote:
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

Múltiplas versões do JDK

Um monorepo Java em que diferentes serviços exigem diferentes versões do JDK:
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)

Blueprint da organização para ferramentas compartilhadas

Quando vários pacotes em um monorepo compartilham as mesmas ferramentas, instale-as uma única vez no blueprint de nível da organização:
# Blueprint nível da organização (Configurações > 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
Então, cada blueprint do repositório só precisa de comandos específicos do projeto:
# Repo blueprint (usa pnpm e uv do org blueprint)
maintenance:
  - name: Install all workspace deps
    run: pnpm install
  - name: Install Python service deps
    run: (cd services/ml-pipeline && uv sync)

Boas práticas

Quando cada subdiretório tem sua própria linguagem, gerenciador de pacotes ou processo de build, workspaces nativos mantêm cada blueprint focado e independente. Reserve subshells para casos simples com poucos pacotes.
Ao usar a abordagem com subshell, coloque os comandos cd entre parênteses: (cd dir && command). Isso evita que a troca de diretório de uma etapa afete a próxima.
Runtimes de linguagem e gerenciadores de pacotes usados em vários repositórios devem ficar no blueprint de nível da organização. Isso evita duplicação e mantém os blueprints do repositório focados na configuração específica do projeto.
Se o pacote A depende de que o pacote B tenha o build concluído primeiro, liste a etapa de build de B antes da etapa de instalação de A em maintenance. As etapas do blueprint são executadas sequencialmente na ordem em que aparecem.
Uma entrada de Knowledge chamada structure, que mapeia diretórios para suas linguagens e ferramentas, ajuda Devin a navegar pela base de código. Inclua qual gerenciador de pacotes cada subdiretório usa e quaisquer dependências entre pacotes.
Em vez de criar uma única entrada de Knowledge grande, crie entradas separadas para cada pacote (por exemplo, frontend, backend, ml-pipeline). Com workspaces nativos, cada workspace já inclui sua própria seção de conhecimento.
Use pnpm install (não pnpm install --force) e uv sync (não rm -rf .venv && uv sync). Comandos incrementais são mais rápidos durante rebuilds periódicos.