# Billing Source: https://docs.devinenterprise.com/admin/billing Devin has two pricing models: * **Self-serve**: Free, Pro, Max, and Teams plans you can sign up for directly at [app.devin.ai](https://app.devin.ai). Self-serve usage is billed through a mix of included quota and on-demand credits. See [Self-serve plans](/admin/billing/self-serve) for full details. * **Enterprise**: Devin Enterprise customers are billed in Agent Compute Units (ACUs) at the rate set in their order form. See [Enterprise](/admin/billing/enterprise) for how ACU consumption is tracked, or [contact sales](https://cognition.com/contact) for pricing. For how Devin meters work in general (how usage accrues, idle/sleep behavior, and tips for keeping consumption under control), see [Usage](/admin/billing/usage). The tips on that page apply to both pricing models. # Enterprise Source: https://docs.devinenterprise.com/admin/billing/enterprise How Devin Enterprise contracts are billed and how admins track ACU consumption Devin Enterprise customers are billed in **Agent Compute Units (ACUs)** at the rate set in their order form. [Contact sales](https://cognition.com/contact) for pricing. For how Devin meters work in general (sleep behavior, what counts toward consumption, tips for keeping costs down), see [Usage](/admin/billing/usage). ## Tracking ACU consumption Enterprise customers can track ACU consumption at both the Enterprise and Organization level: * **Enterprise admins** view Enterprise ACU consumption at [Settings > Consumption](https://app.devin.ai/settings/consumption) in Enterprise Settings. * **Organization admins** view Organization ACU consumption at [Settings > Consumption Analytics](https://app.devin.ai/settings/analytics?tab=consumption) within Organization Settings. * **Any user** can see the ACU cost of a specific session from [Session Insights](/product-guides/session-insights). ## Setting Organization ACU limits Enterprise admins can set per-Organization ACU limits from [Settings > Organizations](https://app.devin.ai/settings/organizations) in Enterprise Settings. Devin Enterprise Org List
Devin Enterprise Org Management Once set, an Organization can only consume up to its limit. All Devin activity stops once the limit is reached, and users see a message indicating the Organization has hit its ACU limit and to contact the Enterprise admin to raise it. Devin Org ACU Limit Reached ## Frequently asked questions Enterprise customers are billed for ACUs as stated in their order form. Enterprise ACUs represent the work performed by Devin for customers on the Enterprise plan, which adheres more strictly to task planning and end-to-end testing. They are distinct from self-serve quota and on-demand credits, and are priced per the customer's Enterprise order form. Enterprise admins can break consumption down by Organization from the [Consumption](https://app.devin.ai/settings/consumption) page in Enterprise Settings. Org admins can break it down by user from [Consumption Analytics](https://app.devin.ai/settings/analytics?tab=consumption) inside Organization Settings. # Self-serve plans Source: https://docs.devinenterprise.com/admin/billing/self-serve Compare Devin's self-serve plans and understand usage quota and on-demand credits Devin has four self-serve plans you can sign up for directly at [app.devin.ai](https://app.devin.ai). For authoritative pricing, see the [Devin pricing page](https://devin.ai/pricing). This page explains how the plans relate to each other and how billing mechanics work. ## Plan overview | Plan | For | Price | Members | | --------- | --------------------------------- | ------------------ | --------- | | **Free** | Individuals trying Devin | Free | 1 | | **Pro** | Individual users | \$20/month | 1 | | **Max** | Power users who need more quota | \$200/month | 1 | | **Teams** | Teams working with Devin together | \$80/month minimum | Unlimited | The **Pro** and **Max** plans are individual plans. They cannot be shared across multiple users. If you want multiple people to use Devin under a single subscription, you need the **Teams** plan. ## Free The Free plan lets you try Devin with limited usage. It includes: * Limited Devin usage * Access to [Devin Review](/work-with-devin/devin-review) * Access to [DeepWiki](/work-with-devin/deepwiki) Free users can upgrade to any paid plan at any time from [Settings > Plans](https://app.devin.ai/settings/plans). ## Pro Pro is Devin's entry-level individual plan. It's designed for a single developer who uses Devin regularly. Pro includes: * A daily and weekly usage quota that covers Devin sessions, [Devin CLI](/cli), and [Devin Desktop](https://windsurf.com) * Pay-as-you-go [on-demand credits](#on-demand-credits) for usage past your quota * Slack, Linear, and [MCP](/work-with-devin/mcp) integrations Pro is a single-user plan. Pro subscribers cannot invite additional members to their organization. To work with teammates on a shared subscription, use the [Teams](#teams) plan. ## Max Max is for individual users who consistently exceed the Pro quota. It includes everything in Pro, plus a significantly larger weekly usage quota (with no daily cap), also shared between Devin sessions, [Devin CLI](/cli), and Devin Desktop. Like Pro, Max is a single-user plan and does not support multiple members. ## Teams The Teams plan is Devin's self-serve plan for teams of any size. Key properties: * **Unlimited members**: invite as many teammates as you want. * **\$80/month minimum**: every Teams account pays at least \$80/month. * Each member gets either a **full seat** or a **flex seat**. * **On-demand credits** are shared across the whole team. ### Full seats vs. flex seats Every member of a Teams account holds one of two seat types: **\$40/month per seat**, billed as a fixed recurring line item. Best for members who use Devin regularly. Each full seat includes: * A daily and weekly usage quota equivalent to the Pro plan * Access to Devin Desktop **Free**. Teams can have unlimited flex seats. Best for occasional users. Flex seats: * Draw entirely from the team's shared pool of on-demand credits * Do **not** include Devin Desktop access * Have no fixed monthly charge per seat Admins choose the seat type when [inviting a member](/product-guides/invite-team), and can convert a member between seat types later from **Settings > Members**. ### The \$80 Teams minimum Every Teams subscription costs **at least \$80/month**. You can hit this minimum in any combination of full seats (\$40 each) and on-demand credits: | Full seats | On-demand credits included | Monthly total | | ---------: | -------------------------: | ------------: | | 0 | \$80 | \$80 | | 1 | \$40 | \$80 | | 2 | \$0 | \$80 | | 3 | \$0 | \$120 | | *N* ≥ 2 | \$0 | *N* × \$40 | When you have fewer than two full seats, the remainder of the \$80 minimum is automatically charged as prepaid on-demand credits that the whole team can draw from. Once you have two or more full seats, you've cleared the minimum and no additional on-demand credits are included, but you can still [top up on-demand credits](#on-demand-credits) at any time. Give a full seat to anyone who uses Devin regularly. Full seats include their own Pro-equivalent quota and Devin Desktop access at a predictable fixed cost, making them the best fit for power users. Reserve flex seats for occasional or trial users who only need ad-hoc access through shared on-demand credits. ## How quotas work Each paid plan and full seat includes a usage allowance that refreshes automatically on a calendar basis: * **Pro** and **Teams full seats** have a **daily and weekly** allowance. The daily allowance is more than 1/7 of the weekly, so you can keep working through weekends without giving up overall capacity for the week. * **Max** has a **weekly** allowance only, with no daily cap. When you've used up your allowance, [on-demand credits](#on-demand-credits) keep you working without interruption. ## On-demand credits On-demand credits are prepaid usage credit that fund any work past your plan's included quota: * **Roll over** month-to-month. Purchased credits never expire. * Can be topped up at any time from [Settings > Plans](https://app.devin.ai/settings/plans), and optionally refilled automatically via auto-reload. * Admins can set auto-reload thresholds and default session spending limits from **Settings > Usage**. * On the **Teams** plan, credits are **shared across all members**, with no per-member balance. Any teammate can draw from the shared pool. * On the **Teams** plan, credits fund all usage on **flex seats** and any **full seat** usage past its included quota, and cover any portion of the [\$80/month minimum](#the-80-teams-minimum) not already covered by full seats.
## Devin Review and Automations Pricing
[Automations](/product-guides/automations) and [Devin Review](/work-with-devin/devin-review) are available on self-serve plans. * **Teams use shared on-demand credits.** On the Teams plan, Automations and Devin Review draw directly from the team's shared [on-demand credit](#on-demand-credits) pool and do not consume full-seat quota. * **What happens when you run out of credits.** If you run out of credits, Automations stop running and Devin Review switches to its smart diff viewer. Top up [on-demand credits](#on-demand-credits) to start Automations again and re-enable AI-powered review. * **Public PRs are free.** Anyone can review a public GitHub PR at [devinreview.com](https://devinreview.com) — or by replacing `github.com` with `devinreview.com` in any PR URL — without a Devin account, and no on-demand credits are consumed. Admins can keep usage predictable by tuning how often auto-review runs. Configure the trigger mode (every commit, only when a PR is first opened, or manual only) per repository or per user from [Settings > Review](https://app.devin.ai/settings/review). See [Trigger Modes](/work-with-devin/devin-review#trigger-modes) in the Devin Review docs for details. ## Migrating from legacy ACU-based plans If you were previously on a legacy ACU-based plan, here's what you need to know: * On-demand credits are the same dollar value as the ACUs you're used to. * **Legacy Core plan users** have been migrated to the Free plan and can continue using any remaining on-demand credits. To purchase additional credits, upgrade to the [Teams](#teams) plan. ## Managing your plan Admins can view and change the account's plan from [Settings > Plans](https://app.devin.ai/settings/plans). From there you can: * Upgrade or downgrade between Free, Pro, Max, and Teams * Add or cancel Teams full seats * Purchase on-demand credits or configure auto-reload to replenish them automatically * Download past invoices For tips on keeping consumption under control across all plans, see [Usage](/admin/billing/usage). # Usage Source: https://docs.devinenterprise.com/admin/billing/usage How Devin meters work, what counts toward consumption, and how to keep usage under control This page explains how Devin's work is metered. The mechanics are the same regardless of pricing model. The only difference is the unit: * **Enterprise** customers consume **Agent Compute Units (ACUs)** against the volume in their order form. * **Self-serve** customers consume their plan's included quota first, then draw from prepaid **on-demand credits**. Throughout this page, "usage" refers to whichever unit applies to your account. ## What counts toward usage Usage accrues based on the work Devin actually performs in a session, including: * Number and complexity of actions Devin takes (planning, context gathering, task execution, browser actions, code execution, and so on) * Virtual machine time and networking bandwidth (typically a small fraction of total usage) ### Windows sessions Windows sessions consume approximately **9% more** usage than equivalent Linux (Ubuntu) sessions. Aside from the few units required to keep the Devin VM running, Devin will not consume usage when: * Waiting for your response * Waiting for a test suite to run * Setting up and cloning repositories ## Sleep and idle behavior When a session is idle, Devin goes to sleep. While sleeping, Devin does not consume usage. You can wake the session up at any time by sending another message. Devin typically sleeps automatically after roughly 0.1 ACUs (or the equivalent quota / on-demand credit) of inactivity. ## Managing usage effectively A number of variables affect how much Devin consumes: * Task complexity * Prompt quality (or specificity) * Size of context or codebase * Number of files being touched or modified * Session runtime * Length of conversation * Frequency of back-and-forth messaging A few tips to keep usage under control: * Delegate clearly scoped tasks with a well-defined end goal * Keep prompts and sessions short * Avoid asking Devin to do a lot of different tasks in the same session * Split big projects into sub-tasks across sessions; there are no concurrent session limits, so take advantage of it These tips also tend to improve the quality of Devin's work, so it's a win-win. ## Frequently asked questions No, Devin does not consume any usage while sleeping. Devin typically sleeps automatically after roughly 0.1 ACUs (or the equivalent quota / on-demand credit) of inactivity, so awake-but-idle time generally adds up to very little. Any user can see per-session usage from [Session Insights](/product-guides/session-insights), regardless of pricing model. * **Self-serve**: Current month's usage, quota remaining, and on-demand credit balance live at [Settings > Plans](https://app.devin.ai/settings/plans). * **Enterprise**: Enterprise and per-Organization ACU consumption are available from the [Consumption](https://app.devin.ai/settings/consumption) and [Consumption Analytics](https://app.devin.ai/settings/analytics?tab=consumption) pages in Enterprise and Organization Settings respectively. Yes. If your enterprise enables [Personal Analytics](/enterprise/security-access/personal-analytics), users with the **View Personal Analytics** permission can see their own ACU consumption across every organization from the **My analytics** page in their settings. # Common Issues Source: https://docs.devinenterprise.com/admin/common-issues ## I'm unable to connect my GitHub.com organization If you're unable to set up your integration or seeing "Configure" next to the organization you want to connect, you or one of your teammates has likely already connected your GitHub organization to another Devin account. **You will need to disconnect the existing integration before you can connect to your Devin account.** GitHub error You can disconnect the existing integration by following these steps: 1. Navigate to the Devin Enterprise or Organization with the active integration 2. Navigate to the Integrations page * If you are on an Enterprise account, navigate to [https://app.devin.ai/settings/connected-accounts](https://app.devin.ai/settings/connected-accounts) in Enterprise Settings * If you are on a Teams account, navigate to [https://app.devin.ai/settings/integrations](https://app.devin.ai/settings/integrations) in Organization Settings 3. Click through on the GitHub integration card 4. Click "Disconnect" under the GitHub integration Alternatively, you can disconnect the integration via GitHub: 1. Go to the [GitHub Integration settings](https://github.com/settings/installations) 2. Navigate to Devin.ai Integration and click "Configure" 3. Scroll to the "Danger zone" section to uninstall the integration Devin ## I'm unable to connect my Slack organization If you're seeing an "Unable to proceed with request" error, it means that you or one of your teammates has already connected your Slack organization to another Devin organization. **You will need to disconnect the existing integration before you can connect your new organization.** Slack error You can disconnect the existing integration by following these steps: 1. Navigate to the Devin Enterprise or Organization with the active integration 2. Navigate to the Integrations page * If you are on an Enterprise account, navigate to [https://app.devin.ai/settings/connected-accounts](https://app.devin.ai/settings/connected-accounts) in Enterprise Settings * If you are on a Teams account, navigate to [https://app.devin.ai/settings/integrations](https://app.devin.ai/settings/integrations) in Organization Settings 3. Click through on the Slack integration card 4. Click "Disconnect" under the Slack integration If you're unable to disconnect or find the existing organization, please reach out to [support@cognition.ai](mailto:support@cognition.ai) ## IP Allowlisting If you need to allowlist Devin's services, please add the following IP addresses: * 100.20.50.251 * 44.238.19.62 * 52.10.84.81 * 52.183.72.253 * 20.172.46.235 * 52.159.232.99 * 4.204.199.103 * 140.232.64.0/26 (Please note: While we intend to keep this list static, it is possible these IPs may change in future updates.) ## Session Expiration Devin sessions can't be continued after 30 days. If you need to resume work after that window, start a new session and re-share any relevant context (for example: goals, requirements, key decisions, and any important files or links) so Devin can continue effectively. # Security at Cognition Source: https://docs.devinenterprise.com/admin/security We want Devin to be a core contributor in your organization, and have prioritized security, data privacy and compliance to make it possible ## Security All data transmission is encrypted in transit and at rest. Production software is also routinely monitored via logging, error handling and monitoring dashboards of live metrics. Unusual application states (i.e. unusually high error rates, slowness, failures) trigger alerts which are quickly investigated by our team. Access to our cloud environment in AWS is granted on an as-required basis based on business roles and only a small number of employees or contractors are granted direct access to production systems. All employees and contractors are required to use multi-factor authentication on all main work applications. All employees and contractors also receive annual training about security best practices, including good password management and how to identify social engineering and phishing scams. Cognition obtained SOC 2 Type II certification and conducted Security Training in March 2024 for all employees at Cognition. As part of the SOC 2 audit, Cognition's auditors reviewed all of Cognition's security policies, procedures, internal and third party controls related to data security, privacy, processing integrity, confidentiality and availability. For more details about our security please visit our [Trust Center](https://trust.cognition.ai/). If you have identified a potential security issue, we encourage you to share your findings with us. Please send your vulnerability reports to our security team at [security@cognition.ai](mailto:security@cognition.ai). ## Privacy & Intellectual Property Cognition processes data based on the application Customers use to interact with Devin. Devin can be accessed via web application, integration with GitHub, or integration with Slack. For the web application, Cognition only processes data actively provided by the authorized user prompting Devin; for the GitHub and Slack integrations, the administrator installing the integration can review and manage all permissions granted to Devin. Cognition uses Customer data to: * Deliver, maintain and update services provided to the Customer per their configuration and type of Devin access (e.g. web application, integration with GitHub, or integration with Slack) to make sure the software is up-to-date and operational. * Troubleshoot, prevent and resolve issues such as product-related issues, software bugs or security incidents to maintain service functionality and reliability. Cognition only retains data processed through Devin for the duration of the relationship with a given Customer, unless otherwise specified by the Customers. Any Feedback Data and User Interaction Data are retained as long as needed and as determined by Cognition. By default, we may use your data for model training purposes to improve and enhance the Services. If you're on a paid plan, you can opt out at any time on the Data Controls settings page. After you opt out, your data will not be used for training and Zero Data Retention will be enabled with our model providers. On the Teams plan, only an administrator can exercise the opt-out. Devin can still learn to fit into your unique workflow via the [Knowledge](/product-guides/knowledge) feature. When you share Knowledge, Devin can become more reliable at working on your specific projects over time. If you are an Enterprise customer, we will never train on your data without your express prior written consent. Please refer to the terms in your agreement with Cognition for details. The output — code, work product, or other — produced by Devin is considered the user’s intellectual property and can be used for the Customer’s commercial purposes, with the exception of using the output to train models that would attempt to reverse engineer and/or build a competing product to Devin. When setting up the GitHub integration, users can select which repositories Devin can access, with permissions adjustable through GitHub's App Settings during and post-installation. For more details on the requested permissions and security considerations go to [GitHub Integration Guide](/integrations/gh). In Slack, Devin doesn’t read, process or store any data in your Slack instance other than the information provided when @Devin is tagged, initially prompted and when any additional information is provided within the Slack thread while the session is ongoing. For more details on the requested permissions and security considerations go to [Integration with Slack Guide](/integrations/slack). ## User Best Practices While Devin’s performance is improving daily, it can still experience hallucinations, introduce bugs into code, or suggest insecure code or procedures. Like with any coding best practices, we recommend taking the appropriate precautions with the code written by Devin such as code reviews, enabling branch protections to ensure checks are enforced before Devin can merge any changes, and any practices currently adopted in your organization to review engineers’ work. You may need to provide Devin with credentials and keys such as passwords, API keys, cookies or other for authentication. In all cases we advise users to leverage our Secrets feature under the Settings page to share and store those credentials securely. We’re still learning and developing Devin to be a great AI software engineer, and our customers’ feedback is crucial for Devin’s development. We strongly encourage sharing feedback and feature requests directly with your Cognition account team or by emailing [support@cognition.ai](mailto:support@cognition.ai), and reporting incidents by emailing [security@cognition.ai](mailto:security@cognition.ai). # JetBrains Source: https://docs.devinenterprise.com/cli/acp/jetbrains Run Devin inside JetBrains IDEs from AI Chat using the Agent Client Protocol (ACP), including JetBrains Remote Development. JetBrains IDEs can run Devin as an agent inside **AI Chat** using the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/). The quickest way to add Devin is to install it from the **ACP Registry**; you can also configure it manually as a custom agent. Either way, you can drive Devin from the AI Chat panel in IntelliJ IDEA, PyCharm, GoLand, and other JetBrains IDEs — including over [JetBrains Remote Development](https://www.jetbrains.com/remote-development/). This integration uses JetBrains' built-in ACP support in AI Assistant. For the upstream reference, see the JetBrains docs on [adding a custom agent](https://www.jetbrains.com/help/ai-assistant/acp.html#add-custom-agent). ## Prerequisites * A JetBrains IDE with the **AI Assistant** plugin and AI Chat available. ## Setup Install Devin directly from the **ACP Registry** — no CLI installation or manual configuration required. Click the **AI Chat** icon in the right-hand tool window bar. AI Chat icon in the JetBrains tool window bar Click the agent selector in the AI Chat footer to see the list of available agents. Choose **Install From ACP Registry...**, search for **Devin**, and click **Install**. Devin is added to the list of available agents. Agent selector menu showing the Install From ACP Registry option The first time you connect, you may be prompted to authenticate. Follow the prompt to log in to your Devin account. Logging in to Devin from JetBrains AI Chat Select **Devin** in the agent selector and send a message to start a session. Devin selected as the agent in the AI Chat footer ## Manual setup (custom ACP) If you'd rather run Devin from your own installation of the Devin CLI, you can add it as a custom ACP agent instead of installing from the registry. ### Prerequisites * Devin CLI installed and authenticated. If you haven't installed it yet, follow the [Quickstart](/cli/index), then run `devin auth login`. * The absolute path to the `devin` binary. You can find it with: ```bash theme={null} which devin ``` This typically resolves to something like `~/.local/bin/devin`. For **JetBrains Remote Development**, Devin CLI must be installed on the **remote host** (where the backend runs), not on your local client. Run `which devin` in a terminal on the remote host and use that path in the configuration below. Click the **AI Chat** icon in the right-hand tool window bar. AI Chat icon in the JetBrains tool window bar Click the three-dots menu in the top-right of the AI Chat panel, then choose **Add Custom Agent**. This opens the `acp.json` configuration file. Add Custom Agent option in the AI Chat menu Add Devin to the `agent_servers` block in `acp.json`. Set `command` to the absolute path of your `devin` binary (from `which devin`) and pass `acp` as the only argument: ```json acp.json theme={null} { "default_mcp_settings": {}, "agent_servers": { "devin": { "command": "/home/you/.local/bin/devin", "args": ["acp"] } } } ``` Save the file. Devin now appears as a selectable agent in AI Chat. Select **devin** as the agent in AI Chat and send a message to start a session. The first time you connect, you may be prompted to authenticate; Devin uses the credentials from `devin auth login` (or `WINDSURF_API_KEY` if set). ## Managing the integration The three-dots menu in the AI Chat panel includes a few helpful actions for the Devin agent: * **Reset ACP Authentication** — clear stored ACP credentials and re-authenticate. * **Get ACP Logs** — open the ACP logs, useful for debugging connection issues or inspecting what the agent is doing under the hood. ## Notes and limitations * Devin's slash commands are advertised over ACP, so they appear in JetBrains AI Chat's own command palette — see [Slash commands in ACP hosts](/cli/reference/commands#slash-commands-in-acp-hosts). * Devin CLI's terminal/shell output is surfaced through JetBrains AI Chat's ACP rendering, which differs from the native Devin CLI terminal UI. Some richer interactions are only available in the standalone CLI. * The `devin acp` subcommand is intended to be launched by an ACP-aware client (like JetBrains AI Chat) as a subprocess — it speaks JSON-RPC over stdio and is not meant to be run interactively. See [`devin acp`](/cli/reference/commands#devin-acp) in the command reference. # Xcode Source: https://docs.devinenterprise.com/cli/acp/xcode Run Devin inside Xcode's coding assistant via the Agent Client Protocol (ACP), or give the Devin CLI access to your Xcode project through Xcode's MCP bridge. Xcode 26.6's [coding intelligence](https://developer.apple.com/documentation/xcode/setting-up-coding-intelligence) can run Devin as an agent inside the **coding assistant** using the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/). Devin isn't one of the agents listed in Xcode's Intelligence settings, so you add it manually as a custom ACP agent that runs from your local Devin CLI installation. This integration uses Xcode's built-in ACP support in the coding assistant. For the upstream reference, see Apple's docs on [setting up coding intelligence](https://developer.apple.com/documentation/xcode/setting-up-coding-intelligence). ## Prerequisites * **Xcode 26.6 or later** with the coding assistant available. * Devin CLI installed and authenticated. If you haven't installed it yet, follow the [Quickstart](/cli/index), then run `devin auth login`. * The **absolute** path to the `devin` binary. You can find it with: ```bash theme={null} which devin ``` This typically resolves to something like `/Users/you/.local/bin/devin`. Xcode requires an **absolute** path for the agent command — it does not expand `~` or use your shell's `PATH`. If `which devin` prints a `~`-prefixed path, expand it first (for example, run `echo "$(cd ~ && pwd)/.local/bin/devin"`) and use the full `/Users/...` result. ## Setup Add Devin as a custom agent from the Intelligence settings. Choose **Xcode > Settings**, then select **Intelligence** in the sidebar. Under **Agents**, click **Add an Agent**. Xcode's built-in ACP support lets you register any agent that speaks the Agent Client Protocol. In the sheet that appears, enter the agent's details: * **Name** — `Devin` (or any label you prefer). * **Command** — the **absolute** path to your `devin` binary (from `which devin`), for example `/Users/you/.local/bin/devin`. A relative path or a `~`-prefixed path won't work. * **Arguments** — `acp`. Add `--model ` (for example `acp --model opus`) to pick the model Devin uses; see [`devin acp`](/cli/reference/commands#devin-acp). Click **Add**. Devin now appears as a selectable agent under **Agents**. Select **Devin** in the coding assistant and send a message to start a session. The first time you connect, you may be prompted to authenticate; Devin uses the credentials from `devin auth login` (or `WINDSURF_API_KEY` if set). ## Give Devin CLI access to your Xcode project (MCP) Separately from running Devin *inside* Xcode, you can point the standalone Devin CLI at your Xcode project so it can build, run tests, read and edit files, render SwiftUI previews, and search Apple's documentation. Xcode ships an [MCP](/cli/extensibility/mcp/overview) server, `xcrun mcpbridge`, that exposes these Xcode tools to any external agent (the same mechanism [Cursor uses](https://cursor.com/docs/integrations/xcode)). Add it to Devin like any other MCP server. The Xcode MCP bridge requires **Xcode 26.3 or later**. Confirm the binary is available with `xcrun --find mcpbridge` (see [Troubleshooting](#troubleshooting) if it isn't). See Apple's docs on [giving external agents access to Xcode](https://developer.apple.com/documentation/xcode/giving-external-agents-access-to-xcode). Choose **Xcode > Settings**, select **Intelligence**, and under **Model Context Protocol** turn on **Allow external agents to use Xcode tools**. Register `xcrun mcpbridge` as a stdio MCP server: ```bash theme={null} devin mcp add xcode -- xcrun mcpbridge ``` Verify it was added with `devin mcp list`. See [`devin mcp`](/cli/reference/commands#devin-mcp) for scope and configuration options. Open your project or workspace in Xcode (the bridge needs a running Xcode session with a project open), then prompt Devin from the CLI. Xcode alerts you when the external agent connects and while it's active. ## Troubleshooting * **`xcrun: error: unable to find utility "mcpbridge"`** — your system is pointed at the Command Line Tools instead of the full Xcode install. Fix it with: ```bash theme={null} sudo xcode-select -s /Applications/Xcode.app/Contents/Developer sudo xcodebuild -runFirstLaunch ``` Then confirm with `xcrun --find mcpbridge`, which should print a path. * **Devin can't reach the Xcode tools** — make sure Xcode is running with a project (not an empty window) open, and that **Allow external agents to use Xcode tools** is enabled in Intelligence settings. ## Notes and limitations * The model can't be switched from Xcode's UI. To use something other than your team's default model, pass `--model ` in the agent's **Arguments** field (see [`devin acp`](/cli/reference/commands#devin-acp)), which sets the model for every session Xcode starts. * When you select an agent in Xcode's coding assistant, it automatically gets access to Xcode capabilities such as building and testing your app. You can review and restrict which commands and tools agents may use under **Agents > Permissions** in Intelligence settings — see Apple's docs on [extending and customizing agents](https://developer.apple.com/documentation/xcode/extending-and-customizing-agents). * Xcode's coding assistant does not surface Devin's slash commands. * Devin CLI's terminal/shell output is surfaced through Xcode's ACP rendering, which differs from the native Devin CLI terminal UI. Some richer interactions are only available in the standalone CLI. * The `devin acp` subcommand is intended to be launched by an ACP-aware client (like Xcode's coding assistant) as a subprocess — it speaks JSON-RPC over stdio and is not meant to be run interactively. See [`devin acp`](/cli/reference/commands#devin-acp) in the command reference. # Zed Source: https://docs.devinenterprise.com/cli/acp/zed Run Devin CLI inside the Zed editor as a custom ACP agent in the Agent Panel. [Zed](https://zed.dev/) has native support for the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/), so you can run Devin CLI as a custom external agent directly inside Zed's **Agent Panel** — with real-time editing, syntax highlighting, and agent following. This integration uses Zed's built-in support for external ACP agents. For the upstream reference, see the Zed docs on [external agents](https://zed.dev/docs/ai/external-agents). ## Setup Open the ACP registry with `zed: acp registry` from the command palette (Cmd+Shift+P on macOS and Ctrl+Shift+P on Windows). Search for "Devin" and install it. On the top left corner of the Threads Sidebar, click on the agent dropdown menu and select "Devin". In the new Devin thread, open the agent menu in the top right corner and select "Authenticate" (or "Reauthenticate"). Then on the bottom of the thread panel, click on "API Key". A browser window will open, where you can log into your Devin Cloud account and authenticate. If you don't have an account you can sign up for free! You can now start a conversation with Devin! By default, Devin will use Adaptive model selection, automatically choosing the best model for your task. You can also pick a specific model from the menu at the bottom of the thread panel. Devin in Zed ## Notes and limitations * Devin's slash commands are advertised over ACP, so they appear in Zed's own command palette — see [Slash commands in ACP hosts](/cli/reference/commands#slash-commands-in-acp-hosts). * Devin CLI's terminal/shell output is surfaced through Zed's ACP rendering, which differs from the native Devin CLI terminal UI. Some richer interactions are only available in the standalone CLI. * The `devin acp` subcommand is intended to be launched by an ACP-aware client (like Zed) as a subprocess — it speaks JSON-RPC over stdio and is not meant to be run interactively. See [`devin acp`](/cli/reference/commands#devin-acp) in the command reference. # Adaptive Source: https://docs.devinenterprise.com/cli/adaptive Adaptive is Cognition's intelligent model router that automatically selects the best AI model for each task. ## Selecting Adaptive To select Adaptive, run `/model adaptive` during a session, pass `--model adaptive` when launching, or set it as your default in `~/.config/devin/config.json` (on Windows, `%APPDATA%\devin\config.json`): ```json theme={null} { "agent": { "model": "adaptive" } } ``` You can switch away from Adaptive to a specific model at any time with `/model`. Adaptive is an intelligent model router that automatically selects the best AI model for each task. Instead of manually choosing between dozens of models, Adaptive analyzes your prompt and routes it to the model that will deliver the best result. ## How it works When you select **Adaptive**, Devin evaluates each request and dynamically chooses the right underlying model. Simple tasks get routed to fast, efficient models. Complex tasks get routed to more capable ones. This means you get the right level of intelligence for every prompt without overspending on premium models for routine work. Adaptive helps your usage allowance last longer by avoiding unnecessary use of expensive models. Adaptive is the best default for most users. ## Enterprise availability For enterprise organizations, Adaptive is disabled by default. An admin must enable the **Adaptive model router** setting from the enterprise settings page before team members can select Adaptive in the model picker. * **Devin Desktop**: Go to **Settings > Devin Desktop > Models** and toggle **Adaptive model router** on. * **Windsurf**: Go to **Team Settings > Models** and toggle **Adaptive model router** on. ## Pricing Adaptive pricing depends on your billing plan. Adaptive draws down your quota at a **fixed per-token rate**, regardless of which underlying model is selected for a given request. Currently, the Adaptive model consumes quota and overage at an introductory promotional rate (through July 7, 2026). | Token type | Cost per 1M tokens | | :---------------- | :----------------- | | Input tokens | \$0.50 | | Output tokens | \$2.00 | | Cache read tokens | \$0.10 | These rates also apply to extra usage beyond your included quota. Because Adaptive routes simpler tasks to lighter models, it typically consumes fewer tokens overall than manually selecting a frontier model for every request. This makes it the most cost-effective option for most users. For customers on the Cognition platform, Adaptive usage is metered in **ACUs** (Agent Compute Units). ACU consumption scales with the tokens used and the model selected by the router for each request. For enterprise customers on credit-based billing, Adaptive uses **variable-token credit pricing**. Each request consumes credits based on the actual tokens used and the model that Adaptive selects for that request according to your credit rate. This means cheaper models cost fewer credits per request, and Adaptive's routing naturally favors cost-efficient choices — so your credit pool lasts longer compared to always selecting a premium model. ## Tips for getting the most out of Adaptive * **Be specific with your prompts.** Clear, focused instructions help Adaptive route to the right model and reduce unnecessary token usage. * **Leverage prompt caching.** Staying on the same model across turns in a conversation enables caching, which significantly reduces input token costs. Adaptive takes this into account when routing. * **Use Adaptive as your default.** For most workflows, Adaptive is the best starting point. Switch to a specific model only when you have a particular reason to — for example, if you need a specific model's reasoning capabilities for a complex task. # Controls Source: https://docs.devinenterprise.com/cli/enterprise/controls Devin CLI is a local agent like Cascade, but does not yet implement all of the same features and controls. Devin CLI is a local agent that runs on your machine with access to your local files, tools, and environment — similar to Cascade in Devin Desktop. It shares the same agent harness as the [Devin Local agent](/desktop/devin-local). Because it is a newer agent, Devin CLI does not yet implement all of the same features and controls as Cascade. Many of Cascade's controls are replaced by more flexible mechanisms — for example, [permissions](/cli/reference/permissions), [hooks](/cli/extensibility/hooks/overview), and [team settings](/cli/enterprise/team-settings). ## Limitations The gap runs both ways: [plugins](/cli/extensibility/plugins/overview) and [subagents](/cli/subagents) have no Cascade equivalent at all, and recent releases brought [plan mode](/desktop/devin-local#plan-mode) and [merging worktree sessions](/desktop/devin-local#worktree-sessions) to parity with Cascade. The list below covers the Cascade features this agent does not have yet. The following features are not currently supported with the Devin Local agent: * **Memories** — The Devin Local agent does not persist memories between sessions. Migrate your critical memories to [skills](/desktop/cascade/skills) with the **Devin: Open Cascade Migration Wizard** command. * **Workflows** — Workflows are not available with the Devin Local agent. Migrate your workflows to [skills](/desktop/cascade/skills) with the **Devin: Open Cascade Migration Wizard** command. * **Code Lenses** - Currently [code lenses](/desktop/command/windsurf-related-features) do not yet trigger the Devin Local agent. * **App Deploys** - The Devin Local agent does not support app deploys. * **Conversation Sharing** - Conversation sharing is not yet available with the Devin Local agent. * **Arena Mode** - [Arena mode](/desktop/cascade/arena) is not available with the Devin Local agent. The Devin Local agent does support [rules and AGENTS.md files](https://cli.devin.ai/docs/extensibility/rules) as well as [skills](https://cli.devin.ai/docs/extensibility/skills/overview) for providing persistent context and reusable workflows. ### Analytics Devin Local activity is reported in the [`cascade_runs`](/desktop/accounts/api-reference/cascade-analytics) data source (model usage, messages sent, and credit consumption), the [`cascade_tool_usage`](/desktop/accounts/api-reference/cascade-analytics) data source (per-tool call counts such as Code Edit, Run Command, Search Web, and MCP Tool), the [`cascade_lines`](/desktop/accounts/api-reference/cascade-analytics) data source (daily lines of code written by the agent), and the [Cascade Data source](/desktop/accounts/analytics-api#cascade-data) of the Custom Analytics API. Unlike Cascade, Devin Local does not track specific suggested lines or "modes" when operating: an edit only runs after you approve it, so accepted lines equal suggested lines, and the `mode` field in `cascade_runs` is not populated. The Devin CLI does not report analytics for [hybrid deployments](https://devin.ai/blog/self-hosted-deployment-maintenance-mode). ### Enterprise controls Enterprise admins can configure the Devin Local agent through [team settings](https://windsurf.com/team/settings), including [new controls only available with the Devin Local agent](https://cli.devin.ai/docs/enterprise/team-settings): * **Sandbox enforcement** - Require sandbox mode for all users and configure organization-wide domain filtering rules * **Granular permissions** - Control which actions the agent can take with more fine-grained permissions * **Network enforcement** - Control network access with allowed and denied domains Additionally, the "Enable Cascade" control can be used to disable the legacy Cascade agent entirely to ensure your team follows the new controls available with Devin CLI. #### Unsupported enterprise controls The following legacy enterprise controls are not available with the Devin Local agent: * **Restrict Tool Calls to Workspace** - by default, the Devin Local agent can only read/edit files within the workspace. Custom [permissions](https://cli.devin.ai/docs/reference/permissions) are a more flexible replacement that can be used to replicate the same rules. * **App Deploys** - App deploys are not yet supported with the Devin Local agent. * **Conversation Sharing** - Conversation sharing is not yet supported with the Devin Local agent. * **Global tool calling disabled** - If you previously disabled tool calling entirely, write an equivalent [permission policy](https://cli.devin.ai/docs/reference/permissions) for Devin CLI instead. The following legacy controls will still be enforced as a fallback if you haven't yet implemented an enterprise CLI permission config: * **Auto Run Terminal Commands** - The Devin Local agent uses its own [permissions model](https://cli.devin.ai/docs/reference/permissions) instead of auto-execution levels; we recommend using this instead, but the old control will still be enforced as a fallback. * **Terminal allow lists** - Implement an equivalent [permission policy](https://cli.devin.ai/docs/reference/permissions) for Devin CLI to allow specific terminal commands. * **Terminal deny lists** - Implement an equivalent [permission policy](https://cli.devin.ai/docs/reference/permissions) for Devin CLI to deny specific terminal commands. ## Further reading * [Team settings](/cli/enterprise/team-settings) * [System configuration](/cli/enterprise/system-config) * [Permissions](/cli/reference/permissions) * [Hooks](/cli/extensibility/hooks/overview) * [Devin Local agent](/desktop/devin-local) # Devin Auth Source: https://docs.devinenterprise.com/cli/enterprise/devin-auth Authenticate to Devin CLI using your existing Devin account ## Overview You can authenticate to Devin CLI using your existing Devin account. This provides a seamless experience for organizations already using Devin, with billing handled through the standard **Devin billing model**. User management, team organization, SSO, RBAC, billing, and consumption are all inherited natively through the Devin dashboard. For most of your organizational needs, you should rely on the [Devin dashboard](https://app.devin.ai). Devin authentication for Devin CLI is available to **Devin Enterprise** customers. Contact your account executive if you have questions about authentication, billing, or access. ## Getting Started ### Prerequisites Before using Devin authentication, ensure that: 1. Your organization has a Devin enterprise account 2. Your administrator has configured Devin CLI access permissions (see [Configuring Access](#configuring-access) below) 3. You have been assigned a role with the **Use Devin CLI** permission ### Authenticating To authenticate with your Devin enterprise account: ```bash theme={null} devin auth login ``` Follow the prompts and be sure to select the **Log in with Devin for Enterprise** button to authenticate through your organization's identity provider. ### Credentials file location After `devin auth login`, Devin CLI stores your API token in `credentials.toml`. By default, this token is persistent and does not expire. You can copy the credentials file between your own machines to reuse the same authentication, but treat it as sensitive: anyone with this file can authenticate as you. Do not share it or commit it to source control. | Platform | Location | | ------------- | ---------------------------------------------------------------------------------------------------------------------- | | macOS / Linux | `$XDG_DATA_HOME/devin/credentials.toml` when `XDG_DATA_HOME` is set; otherwise `~/.local/share/devin/credentials.toml` | | Windows | `%APPDATA%\devin\credentials.toml` (typically `C:\Users\\AppData\Roaming\devin\credentials.toml`) | Run `devin auth logout` to remove stored credentials. On MDM-managed devices, administrators can pin login to a specific enterprise host or account — skipping the login prompts entirely and rejecting out-of-policy accounts — with the [system configuration file](/cli/enterprise/system-config). ## Configuring Access Devin CLI access is controlled through Devin's [custom roles and RBAC system](/enterprise/security-access/custom-roles). Administrators must create a custom role with the **Use Devin CLI** role permission and assign it to users who need access. ### Creating an Access Role 1. Navigate to **Enterprise Settings > Roles** 2. Click **Create a custom role** 3. Provide a descriptive name (e.g., "Devin CLI User") 4. Select the **Use Devin CLI** permission 5. Save the role ### Assigning the Role * **Enterprise admins** or users with the **Manage Account Membership** permission can assign account-level roles via the "Enterprise members" page * **Organization admins** or users with the **Manage Organization Membership** permission can assign organization-level roles via the "Organization members" page You can automatically assign roles based on SSO IdP groups. See the [custom roles documentation](/enterprise/security-access/custom-roles) for details. ## Billing Usage through Devin CLI is billed using the standard **Devin ACU (Agent Compute Unit) model**. All Devin CLI usage counts toward your organization's existing Devin enterprise allocation. Enterprise admins can view their users' Devin CLI usage by accessing the **Cost** dashboard under the **Enterprise Analytics** tab in the Devin web app. This dashboard contains helpful visualizations of ACU consumption across all of the Cognition products, including Devin CLI. For details about ACU billing and usage tracking, refer to your enterprise agreement or contact your account executive. ## Further Reading For more information about Devin enterprise features, see the [Devin Enterprise documentation](/enterprise/getting-started/get-started): * [Enterprise Setup](/enterprise/getting-started/get-started) — Initial configuration and onboarding * [SSO Configuration](/enterprise/security-access/sso/guide) — Single sign-on setup * [Custom Roles & RBAC](/enterprise/security-access/custom-roles) — Fine-grained access control * [Enterprise Security](/enterprise/security-access/security/enterprise-security) — Security policies and controls # System Configuration Source: https://docs.devinenterprise.com/cli/enterprise/system-config Pin Devin CLI login and proxy settings across managed devices with an MDM-distributed system.json policy ## Overview `system.json` is an optional, machine-wide policy file that administrators distribute to managed devices (typically via MDM). It lives in a system directory that only an administrator can write, so — unlike the user config at `~/.config/devin/config.json` — the settings it carries cannot be changed or removed by the user. Use it to: * **Pin authentication** to your enterprise Devin host and/or account, so `devin auth login` skips the login-method menu and rejects any account outside your organization. * **Force an outbound HTTP proxy** for the CLI and its updater. The enterprise setting takes precedence over the user config, and a user who also has a `proxy` section in their own config is asked to remove it before the CLI will start — see [proxy](#proxy) before rolling one out. The file is optional and additive: when it is absent, Devin CLI behaves exactly as it does on an unmanaged device. ## File location | Platform | Path | | -------- | ------------------------------------------------ | | macOS | `/Library/Application Support/Devin/system.json` | | Linux | `/etc/devin/system.json` | | Windows | `C:\ProgramData\Devin\system.json` | These are the same machine-wide, administrator-writable directories Devin Desktop uses for system-level [rules](/desktop/cascade/memories) and [hooks](/desktop/cascade/hooks). Deploy the file with root/Administrator ownership and read-only permissions for regular users — the CLI reads it wherever it finds it, so a user-writable location defeats the purpose of the policy. ## Example ```json theme={null} // /Library/Application Support/Devin/system.json { "enterprise_host": "acme.devinenterprise.com", "account_id": "acct-acme", "proxy": { "mode": "manual", "url": "http://proxy.corp.example.com:8080", "no_proxy": "localhost,127.0.0.1,.internal.corp" } } ``` `system.json` is parsed as strict JSON — comments and trailing commas are **not** supported here, unlike the user `config.json`, which is JSON-with-comments. The comment above is shown only to indicate the file path. ## Options reference | Option | Type | Default | Description | | ----------------- | ------ | ------- | -------------------------------------------------------------------------------------------------------------------------------- | | `enterprise_host` | string | unset | Devin enterprise host that users must authenticate against, e.g. `"acme.devinenterprise.com"`. Accepts a bare host or a full URL | | `account_id` | string | unset | Devin account identifier the authenticated account must belong to | | `proxy` | object | unset | Outbound HTTP proxy settings for the CLI and the updater (`mode`, `url`, `no_proxy`) | Every field is independent — set only the ones you need. Unknown fields are ignored, so a policy written for a newer CLI still applies its known settings on an older one. ### enterprise\_host When set, `devin auth login`: 1. Skips the login-method menu and the subdomain prompt, and drives authentication directly against the configured host. 2. Rejects any login whose resulting account belongs to a different host (or to no Devin enterprise at all) with a message pointing the user at the right host. 3. Refuses the legacy [Windsurf login](/cli/enterprise/windsurf-auth) path entirely. The value is compared case-insensitively and ignores the scheme, so `acme.devinenterprise.com`, `ACME.DevinEnterprise.com`, and `https://acme.devinenterprise.com/` are equivalent. An explicit `http://` scheme is preserved when driving the login (useful only for testing); otherwise `https://` is assumed. ### account\_id When set, the authenticated account must match this account identifier, even when the host already matches — use it to pin a specific tenant on a shared host. A login that resolves to another account, or to no account, is rejected after account verification. Contact your Cognition account team if you are unsure which account identifier to use. Setting `account_id` also refuses the legacy Windsurf login path, since a Windsurf account cannot satisfy a Devin account policy. ### proxy Configures how the CLI routes its own outbound HTTP/HTTPS traffic (API calls, updates, MCP servers). It uses the same shape as the `proxy` section of the [user config file](/cli/reference/configuration/config-file#proxy): | Option | Type | Default | Description | | ---------- | ----------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | `mode` | string | `"system"` | `"system"` (respect `HTTP_PROXY`/`HTTPS_PROXY`/`ALL_PROXY` and platform PAC), `"manual"` (route through `url`), or `"off"` (connect directly) | | `url` | string/null | `null` | Proxy URL. Required when `mode` is `"manual"`. Supports `http://`, `https://`, and `socks5://` | | `no_proxy` | string/null | `null` | Comma-separated bypass list, same syntax as the `NO_PROXY` environment variable. Applies in any mode | The `devin-updater` binary reads the same setting, so background updates go through the same proxy as the CLI itself. The enterprise proxy takes precedence over the user config, and it is an error for both files to configure one. If a user also has a `proxy` section in their `config.json`, the CLI exits at startup and asks them to remove it — rather than silently ignoring their setting. Tell your users to drop any local `proxy` section before you roll the policy out. ## Behavior and failure modes A broken or partially understood policy file never disables the CLI — it degrades to no enforcement — while a valid policy is always enforced: | Situation | Result | | ------------------------------------------ | ---------------------------------------------------------------------------------------- | | File absent | No enforcement; the CLI behaves as on an unmanaged device | | File unreadable or malformed JSON | Treated as absent, with a warning in the logs | | Unknown fields present | Ignored; the recognized fields still apply | | Malformed `proxy` section | The proxy section is ignored; `enterprise_host` / `account_id` enforcement still applies | | Malformed `enterprise_host` / `account_id` | Login enforcement is dropped; a valid `proxy` section still applies | | Blank or whitespace-only value | Treated as unset | Login enforcement runs during `devin auth login`. Credentials that are already stored on a device that signed in before the policy was deployed are not re-validated, so deploy `system.json` before rolling out the CLI — or have affected users run `devin auth logout` and sign in again. The path to `system.json` cannot be redirected by an environment variable on stable, next, or enterprise builds, so users cannot point the CLI at a policy of their own. ## Verifying the policy On a managed device: ```bash theme={null} devin auth logout devin auth login ``` With `enterprise_host` set, the login-method menu should not appear and the printed sign-in URL should be on your configured host. Then confirm the resulting session: ```bash theme={null} devin auth status ``` A login with an account outside the policy fails with an explicit message naming the host or account your organization requires. ## Related settings `system.json` covers device-level policy that must be in place before or during login. Most other organization-wide controls — models, MCP servers and registries, terminal permissions, sandbox enforcement, web search — are managed server-side in [Team Settings](/cli/enterprise/team-settings) and apply automatically once a user signs in. ## Further reading * [Devin Auth](/cli/enterprise/devin-auth) * [Team Settings](/cli/enterprise/team-settings) * [Configuration File](/cli/reference/configuration/config-file) * [Controls](/cli/enterprise/controls) * [Devin Desktop Enterprise Policies](/desktop/enterprise-policies) — the equivalent MDM-distributed policy surface for the editor # Team Settings Source: https://docs.devinenterprise.com/cli/enterprise/team-settings Configure team-wide settings to control your users' Devin CLI usage ## Overview Team-wide settings allow enterprise admins to control Devin CLI usage across their organization. * **Devin Enterprise admins** can manage these settings in the customer-facing Devin dashboard under **Settings → Enterprise → Windsurf** (`app.devin.ai/org/{orgName}/settings/windsurf`). This is self-service for admins with access to enterprise settings. * **Windsurf Enterprise admins** can manage these settings in the Windsurf dashboard at [https://windsurf.com/team/cli-settings](https://windsurf.com/team/cli-settings). Only the Devin CLI-specific settings on these pages apply to Devin CLI. General [Windsurf Team Settings](https://windsurf.com/team/settings) apply to Windsurf and do not necessarily apply to Devin CLI unless also listed on the Devin CLI settings page. ## Available Settings ### Models Control which models your users can access through Devin CLI. You can: * **Allowlist specific models** — Restrict users to a curated list of approved models * **Allow all models** — Give users access to all available models Click **Configure** to manage model access for each category. #### Default model You can also pin a **team-wide default model** that Devin CLI will use for new sessions. This is the same setting Windsurf uses for its default model, so configuring it once applies to both surfaces. * If no team default is set, Devin CLI uses its built-in default model. * If the pinned default is not present in the **allowed models** list above, Devin CLI falls back to the built-in default — the allowlist always takes precedence. * Individual users can still switch models during a session; this setting only controls the starting model for new sessions. Enterprise admins can configure the default model from the [Windsurf Team Settings](https://windsurf.com/team/settings) page, the [Devin CLI Settings](https://windsurf.com/team/cli-settings) page, or the customer-facing Devin Enterprise settings page at `app.devin.ai/org/{orgName}/settings/windsurf`. ### Enable Web Search Allow the Devin CLI agent to perform web searches on the open Internet. This does not affect the agent's ability to read specific URLs, which is performed locally on the user's machine. This tool is **disabled by default** for enterprise teams. ### MCP Servers Control whether your users can use MCP (Model Context Protocol) tools. * **Toggle on/off** — Enable or disable MCP server usage entirely * **Allowlisted MCP Servers** — Specify which MCP servers users are allowed to connect to. If no servers are added, all servers are allowlisted by default. Click **Add Server** to restrict access to specific servers. The recommended way to manage approved servers is through an [MCP registry](#mcp-registry) rather than the explicit allowlist. ### MCP Registry You can use the [official MCP registry](https://modelcontextprotocol.io/registry/about), a downstream registry built on it, or your own registry. Configure registries in team settings: * **MCP registry URLs** — Add one or more registry URLs. With multiple registries, a server is allowed if it appears in any of them (the union of all registries). * **MCP registry enforcement** (toggle) — Choose whether to strictly enforce your registries. When on, users can only connect to servers from your registries; when off, they can also connect to other servers, including custom ones. ### Terminal Permissions Configure team-enforced permission rules for Devin CLI usage. These rules have the **highest precedence** and cannot be overridden by individual users' local or project configurations. Click **Configure** to open the permissions editor. The configuration requires a JSON object with three fields: ```json theme={null} { "deny": [ "exec" ], "ask": [], "allow": [ "Read(~/my-repository/**)" ] } ``` * **`deny`** — Actions that are blocked entirely (takes highest priority) * **`ask`** — Actions that always prompt the user for approval * **`allow`** — Actions that are automatically approved without prompting Permissions can be **scope-based** or **tool-based**: | Type | Format | Example | | ----------------- | -------------- | ------------------------------- | | File read | `Read(/path)` | `Read(~/sensitive/**)` | | File write | `Write(/path)` | `Write(.env*)` | | Command execution | `Exec(cmd)` | `Exec(rm)`, `Exec(sudo)` | | HTTP fetch | `Fetch(url)` | `Fetch(https://internal.api/*)` | | Tool-based | Tool name | `read`, `edit`, `exec` | Use team-enforced deny rules to prevent actions across your entire organization, such as blocking access to sensitive directories or dangerous commands like `rm -rf` or `sudo`. For detailed information on permission syntax, glob patterns, and configuration examples, see the [Permissions documentation](/cli/reference/permissions). ### Sandbox Enforcement Control sandbox behavior for your organization: **Enforcement mode** (whether `--sandbox` is **Optional** or **Required** for all CLI sessions), **Domain allowlist** and **Domain denylist** (organization-wide network filtering), and **Excluded allow** / **Excluded ask** / **Excluded deny** (rules for commands that may — or must never — run outside the sandbox). See the [Sandbox documentation](/cli/sandbox) for how the sandbox works, how these settings interact with user-level configuration, and examples. Enforcement mode is re-read at the start of every prompt, not just at startup. If you switch it to **Required** while a user is in a session that was started without the sandbox, that session refuses further prompts and tells the user to restart — the sandbox is then enabled automatically at startup. Sessions already running with the sandbox are unaffected. ### Attribution Filtering When attribution filtering is enabled for your team, code generated by Devin CLI is checked against a corpus of publicly available code: file edits that match public code are automatically reverted, and matching code blocks in chat responses are flagged while the agent is instructed to rewrite them. The setting applies to all Devin CLI users on the team. This setting is available on **Enterprise plans** and has no self-serve toggle; to enable it, reach out to [support@cognition.ai](mailto:support@cognition.ai) or your Cognition account team. Attribution filtering is also available for Devin cloud sessions — see [Attribution Filtering](/enterprise/features/attribution-filtering). ### Show "Install Devin CLI" in the Devin Desktop Command Palette Devin CLI is bundled with Devin Desktop but requires explicit activation by an admin. Toggle this setting **on** to allow your users to install Devin CLI directly from the Devin Desktop Command Palette. Once enabled, users can open the Command Palette (Cmd+Shift+P on macOS or Ctrl+Shift+P on Windows/Linux) and run **Install Devin CLI** to add the `devin` binary to their PATH. This setting is available on **Legacy Windsurf Enterprise** and **Devin Enterprise** plans and is **off by default**. ## Further Reading To understand how to configure Devin CLI further, see the [Configuration documentation](/cli/reference/configuration/config-file). Settings on this page are applied server-side once a user signs in. To enforce device-level policy that applies before or during login — pinning the enterprise host or account, or forcing an outbound proxy — see the [system configuration file](/cli/enterprise/system-config). # Legacy Windsurf Auth Source: https://docs.devinenterprise.com/cli/enterprise/windsurf-auth Authenticate to Devin CLI using your existing legacy Windsurf enterprise account ## Overview Enterprise users can authenticate to Devin CLI using their existing legacy Windsurf enterprise accounts. This provides a seamless experience for organizations already using Windsurf, with billing handled through the standard **Windsurf legacy credit model**. User management, team organization, SSO, RBAC, billing, and consumption are all inherited natively through the Windsurf dashboard. For most of your organizational needs, you should rely on the [Windsurf dashboard](https://windsurf.com). Legacy Windsurf authentication for Devin CLI is available to **legacy Windsurf Enterprise** customers. Contact your account executive if you have questions about authentication, billing, or access. ## Getting Started ### Prerequisites Before using legacy Windsurf authentication, ensure that: 1. Your organization has a legacy Windsurf enterprise account 2. You have an active legacy Windsurf user account that can use the agentic tools No additional permissions are required to access Devin CLI. If your legacy Windsurf enterprise users can use Windsurf, they can use Devin CLI. ### Installation via Devin Desktop Devin CLI is bundled with Devin Desktop. An admin must first enable the option in [Devin CLI Team Settings](https://windsurf.com/team/cli-settings) — see [Team Settings](/cli/enterprise/team-settings#show-install-devin-cli-in-the-devin-desktop-command-palette) for details. Once enabled, open the Command Palette (Cmd+Shift+P / Ctrl+Shift+P) and run **Install Devin CLI**. Alternatively, you can install using the standalone installer — see the [Quickstart](/cli/) for instructions. ### Authenticating To authenticate with your legacy Windsurf enterprise account: ```bash theme={null} devin auth login ``` Follow the prompts and be sure to select the **Log in with Windsurf for Enterprise** option to authenticate through your organization's identity provider. ### Credentials file location After `devin auth login`, Devin CLI stores your API token in `credentials.toml`. By default, this token is persistent and does not expire. You can copy the credentials file between your own machines to reuse the same authentication, but treat it as sensitive: anyone with this file can authenticate as you. Do not share it or commit it to source control. | Platform | Location | | ------------- | ---------------------------------------------------------------------------------------------------------------------- | | macOS / Linux | `$XDG_DATA_HOME/devin/credentials.toml` when `XDG_DATA_HOME` is set; otherwise `~/.local/share/devin/credentials.toml` | | Windows | `%APPDATA%\devin\credentials.toml` (typically `C:\Users\\AppData\Roaming\devin\credentials.toml`) | Run `devin auth logout` to remove stored credentials. ## Billing & Analytics Usage through Devin CLI is billed using the standard **Windsurf legacy credit model**. All Devin CLI usage counts toward your organization's existing legacy Windsurf enterprise allocation. The analytics and billing systems are shared between Windsurf and Devin CLI. Use the [Team Members dashboard](https://windsurf.com/team/members) to manage team organization or view consumption metrics across both products. On prompt-based plans, each subagent consumes additional credits, just like a user message does. The number of credits depends on the model the subagent uses, so tasks that spawn multiple subagents (or [nest](/cli/subagents#nesting-depth) them) consume more credits. Enterprise admins can also access usage analytics programmatically through the [Analytics API](/desktop/accounts/api-reference/api-introduction) to monitor consumption across their organization. For details about credit billing and usage tracking, refer to your enterprise agreement or contact your account executive. ## Further Reading For more information about legacy Windsurf enterprise features, see the [Devin Desktop documentation](/desktop/getting-started): * [Guide for Admins](/desktop/guide-for-admins) — Administration and team management * [SSO & SCIM](/desktop/accounts/sso-scim) — Single sign-on and user provisioning * [API Reference](/desktop/accounts/api-reference/api-introduction) — Access analytics and usage data # Essential Commands Source: https://docs.devinenterprise.com/cli/essential-commands If you remember nothing else... ## Starting Devin CLI By default, sessions happen in a REPL, a graphical terminal interface where you can chat back and forth and observe Devin's actions. ```bash theme={null} devin # Start interactive REPL (no prompt) devin -- your prompt here # Start REPL with initial prompt devin -p "prompt" # Single-turn, no REPL: print response to stdout and exit devin -p -- prompt words here # Same, using -- separator (still works) ``` Use `--` before your prompt so it is interpreted as a prompt and not a subcommand. Single-turn mode (`-p`) is great for scripts and automations. Type `@` in the prompt input to open autocomplete for local files/directories. Selecting one adds it as context for your message. You can paste images from your clipboard with **Ctrl+V**. Attached images appear in the input area and can be managed with **Left/Right** to navigate and **Backspace** to remove. ## Running shell commands Devin may run shell commands while working. If a command is still running after the default wait period, Devin moves it to the background and shows how long it waited along with the background shell ID. Devin can then continue working and check the command's output later. *** ## Modes Devin CLI has 5 built-in permission modes: **Normal**, **Accept Edits**, **Smart**, **Bypass**, and **Autonomous**, and 3 agent-modes: **Normal**, **Plan**, and **Ask**. For plan and ask, use `/plan` and `/ask`. Auto-approves read-only tools within the current directory, and asks for permission for write/execute operations. ```bash theme={null} /normal # or /mode normal ``` This is the default mode. Auto-approves file edits within the workspace while still prompting for shell commands and other actions. We expect people to spend most of their time here. ```bash theme={null} /accept-edits # or /mode accept-edits ``` Auto-approves file edits within the workspace like Accept Edits, and for every other action — shell commands, web fetches, MCP tools — a fast model decides whether it is safe to run without asking. Anything it does not judge clearly safe still prompts, and high-risk categories (package installs, mutating `git`, `rm`, `sudo`, destructive cloud CLI operations, sensitive files) always prompt. ```bash theme={null} /smart # or /mode smart ``` You can also start in smart mode: ```bash theme={null} devin --permission-mode smart ``` Smart mode is rolling out gradually, so it may not be available on your account yet. See [Smart Mode](/cli/reference/permissions#smart-mode) for the full behavior. Auto-approves **all** tool calls, including writes and shell commands. ```bash theme={null} /bypass # or /mode bypass ``` You can also start in bypass mode: ```bash theme={null} devin --permission-mode bypass ``` Aliases: `/yolo`, `/dangerous` Bypass mode **never** overrides organization-level permissions configured by your admin via [Team Settings](/cli/enterprise/team-settings). Admin-enforced deny and ask rules **always** take priority. Roughly equivalent to Accept Edits in the current workspace, with the additional ability to run any shell command within an [OS-level sandbox](/cli/reference/configuration/config-file#sandbox) (to contain what those commands can actually touch). ```bash theme={null} devin --sandbox --permission-mode autonomous ``` Autonomous is the **only** permission mode available when running with `--sandbox`, and it is selected automatically — Normal, Accept Edits, Smart, and Bypass are hidden in sandbox sessions. In Autonomous mode... * You are prompted for **capabilities rather than commands**. * Commands respect `Write` scopes and `Read(...)` deny rules via a filesystem sandbox. * Commands prompt you when they try to connect to network resources. * Read-only operations within the current directory auto-approve. Autonomous relies on the sandbox for safety. Without `--sandbox`, the mode is unavailable — use Bypass if you want unattended execution without OS-level isolation. See [Bypass vs Autonomous](#bypass-vs-autonomous) below for a direct comparison. ### Bypass vs Autonomous Bypass and Autonomous both reduce approval prompts, but they rely on different safety mechanisms: | | Bypass | Autonomous | | ------------------------------------------------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------- | | Requires `--sandbox` | No | Yes (only available in sandbox sessions) | | Shell commands | Auto-approved, unrestricted | Auto-approved, contained by the sandbox | | File writes via `edit`/`write` tools | Auto-approved anywhere | Still prompt (granting a scope expands the sandbox) | | Network access | Unrestricted | Filtered by the sandbox's [domain allow/deny lists](/cli/reference/configuration/config-file#sandbox) | | Respects admin [Team Settings](/cli/enterprise/team-settings) | Yes | Yes | Pick Bypass when you trust the agent with your whole machine. Pick `--sandbox` (which selects Autonomous) when you want unattended execution with OS-enforced limits on what files and domains the agent can touch. If you like the feel of bypass but want the agent to have its own computer, try cloud Devin! ## Session History Your conversation history is saved so you can resume a session later. ```bash theme={null} devin -c # Continue the most recent session in the current directory devin --continue devin -r # Pick from recent sessions devin --resume devin -r brisk-otter # Resume a specific session by ID ``` *** ## Slash Commands You can use these commands while in an active session. ### Navigation & Control | Command | Description | | ------------------ | ---------------------------------------- | | `/help` | See all available commands | | `/exit` or `/quit` | Exit the application | | `/clear` or `/new` | Clear conversation history (start fresh) | You can also type `exit` or `quit` as plain text (without the `/` prefix) to exit. ### Mode Switching | Command | Description | | ----------------- | --------------------------------------------------------------------------------------------------- | | `/mode` | Show current mode | | `/mode ` | Switch mode (`normal`, `accept-edits`, `smart`, `plan`, `bypass`; `autonomous` in sandbox sessions) | | `/normal` | Switch to Normal mode (default) | | `/accept-edits` | Switch to Accept Edits mode | | `/smart` | Switch to Smart mode | | `/plan` | Switch to Plan mode | | `/ask ` | Ask a question without making code changes (oneshot) | | `/bypass` | Switch to Bypass mode (aliases: `/yolo`, `/dangerous`) | ### Model Switching | Command | Description | | -------- | ------------------- | | `/model` | Show model selector | ### Session Management | Command | Description | | ------------------ | ------------------------------------------------------------------- | | `/resume` | Open the interactive session picker | | `/resume ` | Resume session by ID | | `/ls` | List recent sessions in current directory (alias: `/list-sessions`) | | `/ls --all` | List all sessions across all directories | | `/continue` | Resume most recent session | | `/continue ` | Resume session by ID | | `/rm-session ` | Irreversibly delete a session by ID | ### Workspace | Command | Description | | ---------------------- | ------------------------------------------------- | | `/workspace` | List workspace directories (alias: `/workspaces`) | | `/add-dir ` | Add additional workspace directory | | `/undo-add-dir ` | Remove a workspace directory | ### Automation | Command | Description | | ---------------- | ------------------------------------------------------------------------------------ | | `/loop ` | Run a prompt then auto-review the diff in a loop (requires clean git state to start) | ### Extensibility | Command | Description | | -------- | ------------------------------------------------------------------- | | `/hooks` | List all loaded hooks with their IDs, event types, and source paths | ### Account & System | Command | Description | | ---------- | ---------------------------------------- | | `/login` | Authenticate with Devin | | `/logout` | Clear stored credentials and exit | | `/update` | Check for and install updates | | `/upgrade` | Upgrade your subscription plan | | `/bug` | Report a bug to the Devin CLI developers | | `/compact` | Force conversation compaction | If you installed Devin for Terminal via Homebrew, `/update` will direct you to use `brew upgrade devin` instead of performing a self-update. *** ## Keyboard Shortcuts Here are the most important keyboard shortcuts. See [Keyboard Shortcuts](/cli/reference/keyboard-shortcuts) for more shortcuts. | Shortcut | Description | | -------------------------- | --------------------------------------------------------------------- | | `Shift+Tab` | Cycle between modes (Normal, Accept Edits, Smart, Bypass, Autonomous) | | `Ctrl+C` | Clear input text, or cancel the running agent | | `Esc` | Cancel the running agent | | `Shift+Enter` | Insert a newline (multi-line input) | | `Ctrl+V` or `Shift+Insert` | Paste from clipboard | | `Ctrl+G` | Open external editor | | `Ctrl+O` | Open full-screen thinking trace viewer | | `@` | Mention files to add as context | # Configuration Source: https://docs.devinenterprise.com/cli/extensibility/configuration How to configure Devin CLI behavior with config files Devin CLI is configured through JSON files (with comment support) at the user and project level. These config files control the agent's model, permissions, MCP servers, and more. *** ## Config File Locations **Path:** `~/.config/devin/config.json` Your personal defaults that apply across all projects. This is where you set your preferred model, theme, and global permissions. You can also place an `AGENTS.md` file in this directory (`~/.config/devin/AGENTS.md`) to define [global rules](/cli/extensibility/rules#global-rules) that apply to every project. On Windows, this path is `%APPDATA%\devin\config.json` (typically `C:\Users\\AppData\Roaming\devin\config.json`). ```json theme={null} { "agent": { "model": "claude-sonnet-4.5" }, "permissions": { "allow": ["Read(**)", "Exec(git)"] } } ``` **Path:** `.devin/config.json` (at your project root) Shared team configuration committed to version control. Use this for permission policies and import settings. Project-specific MCP servers go in `.devin/mcp_config.json` alongside it. ```json theme={null} // .devin/config.json { "permissions": { "allow": ["Exec(npm run)", "Read(src/**)"], "deny": ["Exec(sudo)"] } } ``` ```json theme={null} // .devin/mcp_config.json { "mcpServers": { "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"] } } } ``` **Path:** `.devin/config.local.json` Personal overrides for this project that aren't committed to git (automatically gitignored). Use this for secrets, API keys, and personal preference overrides. Personal MCP servers go in `.devin/mcp_config.local.json`. ```json theme={null} // .devin/mcp_config.local.json { "mcpServers": { "github": { "env": { "GITHUB_TOKEN": "ghp_your_token" } } } } ``` *** ## What You Can Configure Choose which AI model powers the agent — from Claude Opus to GPT 5.2 to Gemini 3. Pre-approve safe actions, block dangerous ones, and control what the agent can do without asking. Connect external tool servers for GitHub, Linear, databases, and any custom APIs. Import rules, skills, and configuration from Cursor, Windsurf, and Claude Code. *** ## Quick Start The fastest way to get started is to create a `.devin/config.json` in your project root: ```json theme={null} { "permissions": { "allow": [ "Read(**)", "Exec(git)", "Exec(npm run)" ] } } ``` This pre-approves file reads and common commands so the agent doesn't prompt you for every action. You can also configure Devin CLI interactively: when the agent asks for permission, choose to save the decision to your project or user config for next time. *** ## Project vs User Settings Not all settings are available at every level. Project configs (`.devin/config.json` and `.devin/config.local.json`) support: * **`permissions`** — allow, deny, and ask rules * **`mcpServers`** — MCP server definitions (in the dedicated `.devin/mcp_config.json` / `.devin/mcp_config.local.json` files since v3000.3, the Local 3.6 release; in `config.json` in older versions) * **`read_config_from`** — import settings from Cursor, Windsurf, and Claude * **`hooks`** — lifecycle hooks ([see Hooks](/cli/extensibility/hooks/overview)) All other settings — including `agent` (model), `theme_mode`, `unicode_mode`, `show_path`, `sandbox`, and other display/behavior options — are **user-config only** and can only be set in the user config (`~/.config/devin/config.json`; `%APPDATA%\devin\config.json` on Windows). *** ## Configuration Precedence For settings that support multiple levels, higher-priority sources win: | Priority | Source | Shared? | | ----------- | ------------------------------------------------------------------------------ | ---------------- | | 1 (highest) | Organization / Team settings | Yes (enterprise) | | 2 | Session grants (interactive approvals) | No (in-memory) | | 3 | Project local (`.devin/config.local.json`) | No (gitignored) | | 4 | Project (`.devin/config.json`) | Yes (committed) | | 5 (lowest) | User (`~/.config/devin/config.json`; `%APPDATA%\devin\config.json` on Windows) | No (personal) | Permissions are merged across levels, while MCP servers are merged by name (higher-priority source wins for same-named servers). Organization-level (enterprise) settings can **never** be overridden by project or user config. See [Configuration Precedence](/cli/reference/configuration/global-vs-local) for full details on how merging works. *** ## Limitations When run standalone, Devin CLI only respects `.gitignore` by default — it does not enforce `.devinignore`, `.codeiumignore`, or `.windsurfignore` files. When Devin CLI runs inside Devin Desktop, all four ignore files are enforced. *** ## Learn More Complete list of every configuration option and its format. How global, project, and local settings interact and merge. # Lifecycle Hooks Source: https://docs.devinenterprise.com/cli/extensibility/hooks/lifecycle-hooks Understanding hook events and the data available at each stage Each hook event fires at a specific point in the agent's lifecycle. Use the **matcher** field (a regex matched against the hook event's `tool_name`) to filter which tool invocations trigger your hook. In addition to the event-specific fields below, every stdin payload includes a stable per-session `session_id` and a per-turn `prompt_id` (rotated on every user prompt; absent for events that fire before the first user prompt, e.g. `SessionStart`) — see [Command Hooks](/cli/extensibility/hooks/overview#command-hooks). *** ## PreToolUse Fires **before** a tool executes. Use this to block, modify, or add context to tool calls. **Stdin data:** | Field | Description | Example | | ------------ | ----------------------------- | ----------------------------------------------- | | `tool_name` | Name of the tool being called | `exec`, `edit`, `mcp__github__create_issue` | | `tool_input` | Arguments passed to the tool | `{ "command": "rm -rf /", "shell_id": "main" }` | **Example — Block destructive commands:** ```json theme={null} { "PreToolUse": [ { "matcher": "exec", "hooks": [ { "type": "command", "command": "python3 -c \"import sys, json; data = json.load(sys.stdin); cmd = data.get('tool_input', {}).get('command', ''); sys.exit(2 if 'rm -rf' in cmd else 0)\"" } ] } ] } ``` **Example — Require confirmation for writes outside src/:** Use a script that inspects the tool input and returns a decision: ```json theme={null} { "PreToolUse": [ { "matcher": "edit", "hooks": [ { "type": "command", "command": "./scripts/check-edit-path.sh", "timeout": 5 } ] } ] } ``` **Example — Rewrite commands before execution:** A hook can transparently rewrite the tool's input by printing `hookSpecificOutput.updatedInput` to stdout (see [Output format](/cli/extensibility/hooks/overview#output-format)). For example, a hook script that routes shell commands through a wrapper: ```json theme={null} { "hookSpecificOutput": { "hookEventName": "PreToolUse", "updatedInput": { "command": "rtk git status" } } } ``` The rewritten arguments are merged into the tool call before it runs — the agent executes the updated command instead of the original. *** ## PostToolUse Fires **after** a tool finishes executing. Use this for logging, validation, or triggering follow-up actions. **Stdin data:** | Field | Description | | --------------- | -------------------------------------------------------------------------------- | | `tool_name` | Name of the tool that ran | | `tool_input` | Arguments that were passed | | `tool_response` | Object with `success` (boolean), `output` (string), and `error` (string or null) | **Example — Log all shell commands:** ```json theme={null} { "PostToolUse": [ { "matcher": "exec", "hooks": [ { "type": "command", "command": "sh -c 'cat >> ~/.devin-command-log'" } ] } ] } ``` *** ## PermissionRequest Fires when the agent needs a permission decision. Use this to implement custom approval logic. **Stdin data:** | Field | Description | | ------------ | --------------------------- | | `tool_name` | Tool requesting permission | | `tool_input` | Arguments for the tool call | **Example — Auto-approve git commands:** ```json theme={null} { "PermissionRequest": [ { "matcher": "exec", "hooks": [ { "type": "command", "command": "python3 -c \"import sys, json; data = json.load(sys.stdin); cmd = data.get('tool_input', {}).get('command', ''); print(json.dumps({'decision': 'approve'})) if cmd.startswith('git ') else sys.exit(0)\"" } ] } ] } ``` *** ## UserPromptSubmit Fires when the user submits a message. Use this to add context or trigger workflows. **Stdin data:** | Field | Description | | -------- | ----------------------- | | `prompt` | The user's message text | **Example — Inject context on every prompt:** ```json theme={null} { "UserPromptSubmit": [ { "matcher": "", "hooks": [ { "type": "command", "command": "echo '{\"hookSpecificOutput\": {\"hookEventName\": \"UserPromptSubmit\", \"additionalContext\": \"Deploys require an approved change ticket.\"}}'" } ] } ] } ``` The command prints `additionalContext` inside a `hookSpecificOutput` object on stdout, tagged with the event name. That text is injected into the agent's context: ```json theme={null} { "hookSpecificOutput": { "hookEventName": "UserPromptSubmit", "additionalContext": "Deploys require an approved change ticket." } } ``` *** ## Stop Fires when the agent decides to stop (finish its turn). Use this to add follow-up instructions or prevent premature stopping. **Stdin data:** | Field | Description | | ------------------ | ------------------------------------- | | `stop_hook_active` | Whether a stop hook is already active | **Example — Remind agent to run tests:** ```json theme={null} { "Stop": [ { "matcher": "", "hooks": [ { "type": "command", "command": "echo '{\"decision\": \"block\", \"reason\": \"Please run the test suite before stopping.\"}'" } ] } ] } ``` Be careful with stop hooks that block — they can cause the agent to loop if the condition isn't eventually satisfied. *** ## PostCompaction Fires **after** context compaction completes successfully. Use this for logging, triggering follow-up actions, or re-injecting context that may have been lost during compaction. **Stdin data:** | Field | Description | | --------- | -------------------------------------------------------------------------------- | | `summary` | Summary text produced by the compactor (may be null if no summary was generated) | **Example — Log compaction events:** ```json theme={null} { "PostCompaction": [ { "matcher": "", "hooks": [ { "type": "command", "command": "sh -c 'cat >> ~/.devin-compaction-log'" } ] } ] } ``` *** ## SessionStart Fires when a new session begins. Use this for initialization, logging, or environment setup. **Stdin data:** | Field | Description | | -------- | --------------------------- | | `source` | How the session was started | **Example — Run setup script:** ```json theme={null} { "SessionStart": [ { "matcher": "", "hooks": [ { "type": "command", "command": "./scripts/dev-setup.sh", "timeout": 10 } ] } ] } ``` A SessionStart command can also inject context by printing `additionalContext` inside a `hookSpecificOutput` object on stdout: ```json theme={null} { "hookSpecificOutput": { "hookEventName": "SessionStart", "additionalContext": "Session started. Project uses ESM imports only." } } ``` *** ## SessionEnd Fires when a session ends. Use this for cleanup or final logging. **Stdin data:** | Field | Description | | -------- | --------------------- | | `reason` | Why the session ended | *** ## Matching Multiple Events A single hooks file can define hooks for multiple events: ```json theme={null} { "PreToolUse": [ { "matcher": "", "hooks": [ { "type": "command", "command": "./scripts/audit.sh" } ] } ], "PostToolUse": [ { "matcher": "", "hooks": [ { "type": "command", "command": "./scripts/audit.sh" } ] } ] } ``` ## Using the Matcher The `matcher` field is a **regex** matched against the hook event's `tool_name`. It is available for tool-related events: `PreToolUse`, `PostToolUse`, and `PermissionRequest`. For non-tool events (`UserPromptSubmit`, `Stop`, `PostCompaction`, `SessionStart`, and `SessionEnd`), there is no `tool_name`; use `""` or omit the matcher to run the hook for every event of that type. The matcher is not a permission glob. Patterns like `mcp__github__*` are useful in permissions, but hook matchers are regexes. Use `mcp__github__.*` in a hook matcher. | Matcher | Matches | | ------------------------------- | ---------------------------------------------------- | | `""` (empty) or omitted | All tool names for tool events | | `"exec"` | Tool names containing `exec` | | `"^exec$"` | Only the `exec` tool | | `"^(exec\|edit)$"` | Only `exec` or `edit` | | `"^mcp__.*"` | All MCP tools | | `"^mcp__github__.*"` | All tools from the `github` MCP server | | `"^mcp__github__create_issue$"` | The `create_issue` tool from the `github` MCP server | ### Tool names you can match Hook matchers run against the same externally-visible tool names that hook scripts receive in stdin as `tool_name`. The exact tool names available can vary by CLI mode, model, and enabled integrations. The core tool names, by category: | Category | Tool names | | ------------------ | -------------------------------------------------------------------------- | | File operations | `read`, `write`, `edit`, `apply_patch`, `notebook_read`, `notebook_edit` | | Search | `grep`, `glob` | | Shell | `exec`, `get_output`, `write_to_process`, `kill_shell` | | Web | `webfetch` | | Planning and tasks | `todo_write`, `exit_plan_mode` | | Skills | `skill` | | Subagents | `run_subagent`, `read_subagent` | | Permissions | `request_scope` | | MCP management | `mcp_list_servers`, `mcp_list_tools`, `mcp_call_tool`, `mcp_read_resource` | MCP server tools appear as `mcp____`. For example, a `github` MCP server tool named `create_issue` appears as `mcp__github__create_issue`. For other tools, match the exact `tool_name` shown in hook stdin. To confirm the complete set available in your current session, add a temporary `PostToolUse` hook with `matcher: ""` and log the stdin payload. # Hooks Source: https://docs.devinenterprise.com/cli/extensibility/hooks/overview Run custom logic when specific events occur during a session Hooks let you run custom logic in response to events in the agent's lifecycle. You can use hooks to enforce policies, add context, log actions, modify permissions, or integrate with external systems. Hooks are configured with a JSON format. Place them in your project's `.devin/` directory (or a user-level config) and Devin CLI runs them at the matching lifecycle events. Existing hooks in `.claude/` directories are also picked up automatically — see [Where Hooks Live](#where-hooks-live). *** ## What Can Hooks Do? Block dangerous commands, require confirmation for specific actions, or restrict file access. Inject additional instructions or information when specific tools are called. Execute scripts, send notifications, or log events when things happen. Dynamically grant or restrict permissions based on the situation. *** ## Quick Example Create `.devin/hooks.v1.json` in your project: ```json theme={null} { "PreToolUse": [ { "matcher": "exec", "hooks": [ { "type": "command", "command": "./scripts/check-command.sh" } ] } ] } ``` This runs `./scripts/check-command.sh` before every shell command execution. The script receives event data on stdin and can block the action by returning a non-zero exit code. *** ## Hook Events Hooks can respond to these lifecycle events: | Event | When it fires | | ------------------- | ----------------------------------------------- | | `PreToolUse` | Before a tool executes | | `PostToolUse` | After a tool finishes | | `PermissionRequest` | When a permission decision is needed | | `UserPromptSubmit` | When the user submits a message | | `Stop` | When the agent wants to stop | | `PostCompaction` | After context compaction completes successfully | | `SessionStart` | When a session begins | | `SessionEnd` | When a session ends | See [Lifecycle Hooks](/cli/extensibility/hooks/lifecycle-hooks) for details on each event and its available data. *** ## Hook Format Each hook has a **type** (`command` or `prompt`), an optional **matcher** (regex on the hook event's `tool_name`), and configuration: ```json theme={null} { "PreToolUse": [ { "matcher": "exec", "hooks": [ { "type": "command", "command": "./scripts/validate.sh", "timeout": 10 } ] } ] } ``` | Field | Description | | --------- | -------------------------------------------------------------------------------------------------------------- | | `matcher` | Regex matched against the hook event's `tool_name`. Empty string or an omitted matcher matches all tool names. | | `type` | `"command"` to run a shell command, or `"prompt"` to evaluate an LLM prompt. | | `command` | Shell command to run (for `command` type). | | `prompt` | LLM prompt to evaluate (for `prompt` type). | | `timeout` | Timeout in seconds (optional). | ### Command Hooks Command hooks run a shell command. Event data is passed as JSON on **stdin**, and the command can return JSON on **stdout** to control the outcome (see [Output format](#output-format) below). **Input** (stdin): ```json theme={null} { "hook_event_name": "PreToolUse", "tool_name": "exec", "tool_input": { "command": "rm -rf /" }, "session_id": "3f8d1c2a-...", "prompt_id": "b71e9d40-..." } ``` Every event payload also carries two correlation ids alongside the event fields: | Field | Description | | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `session_id` | Stable id for the agent session. Use it to correlate hook invocations across a whole session. | | `prompt_id` | Per-turn id, rotated on every user prompt. All hooks fired during the same turn share one `prompt_id`. Absent for events that fire before the first user prompt (e.g. `SessionStart`). | The `DEVIN_PROJECT_DIR` environment variable is automatically set to the project root directory. See [Using the Matcher](/cli/extensibility/hooks/lifecycle-hooks#using-the-matcher) for the built-in tool names and MCP tool name format you can match. ### Output format A command hook can print a JSON object to **stdout** to control the outcome. To approve or block an action, return a top-level `decision` (with an optional `reason`): ```json theme={null} { "decision": "block", "reason": "Destructive command blocked by policy" } ``` To inject text into the agent's context, return `additionalContext` inside a `hookSpecificOutput` object tagged with the event name: ```json theme={null} { "hookSpecificOutput": { "hookEventName": "UserPromptSubmit", "additionalContext": "Remember: deploys require an approved change ticket." } } ``` To transparently rewrite a tool's input before it executes, return `updatedInput` inside a `PreToolUse` `hookSpecificOutput`. Fields in `updatedInput` are merged into the tool's arguments, so you can update a subset (e.g. just `command`): ```json theme={null} { "hookSpecificOutput": { "hookEventName": "PreToolUse", "updatedInput": { "command": "rtk git status" } } } ``` | Output field | Description | | -------------------------------------- | -------------------------------------------------------------------------------------------------- | | `decision` | `"approve"` to allow the action, or `"block"` to deny it | | `reason` | Explanation shown to the agent | | `hookSpecificOutput.hookEventName` | Event the output applies to (e.g. `UserPromptSubmit`, `SessionStart`, `PreToolUse`, `PostToolUse`) | | `hookSpecificOutput.additionalContext` | Text injected into the agent's context (for `UserPromptSubmit`, `SessionStart`, `PostToolUse`) | | `hookSpecificOutput.updatedInput` | Object merged into the tool's arguments before execution (for `PreToolUse`) | ### Exit Codes | Code | Meaning | | ----- | --------------------------------- | | 0 | Success — hook continues normally | | 2 | Block — action is denied | | Other | Error — logged but doesn't block | *** ## Where Hooks Live Devin CLI reads hooks from the following locations. All use the same JSON format. Project-level hook files are discovered in the working directory and its ancestor directories up to the repository root, matching how skills and rules are loaded. ### Project-Level | Location | Description | | ----------------------------- | ------------------------------------------ | | `.devin/hooks.v1.json` | Standalone hooks file (recommended) | | `.devin/config.json` | `"hooks"` key in the config file | | `.devin/config.local.json` | `"hooks"` key (local override, gitignored) | | `.claude/settings.json` | `"hooks"` key (Claude Code format) | | `.claude/settings.local.json` | `"hooks"` key (Claude Code format) | ### User-Level (Global) | Location | Description | | ------------------------------------------------------------------------ | ---------------------------------- | | `~/.config/devin/config.json` (`%APPDATA%\devin\config.json` on Windows) | `"hooks"` key in user config | | `~/.claude.json` | `"hooks"` key (Claude Code format) | | `~/.claude/settings.json` | `"hooks"` key (Claude Code format) | | `~/.claude/settings.local.json` | `"hooks"` key (Claude Code format) | In `.devin/hooks.v1.json`, the hooks object is the **entire file** (no wrapper key needed). In all other locations, hooks are nested under the `"hooks"` key in a settings file. Hooks from `.claude/` paths are loaded when `read_config_from.claude` is enabled (the default). You can disable this in your [user config](/cli/reference/configuration/read-config-from) if needed. *** ## Verifying Hooks Use the `/hooks` slash command to see all currently loaded hooks and their source files: ``` /hooks ``` *** ## Next Steps Deep dive into each event type and what data is available. Control which config locations Devin CLI reads hooks from. # Extensibility Overview Source: https://docs.devinenterprise.com/cli/extensibility/index Customize and extend Devin CLI with rules, skills, and MCP servers Devin CLI is designed to be deeply customizable. You can shape how the agent behaves, what tools it has access to, and how it responds to events — all through configuration files in your project or home directory. Provide always-on context and instructions that guide the agent's behavior across every session. Create reusable prompts and workflows the agent can invoke as slash commands or use autonomously. Install and share bundles of skills across projects. Define specialized subagent profiles with their own system prompts, tools, and models. Connect external tool servers to give the agent access to APIs, databases, and more. Run shell commands or LLM prompts at key points in the agent's lifecycle to enforce policies and automate workflows. *** ## How It All Fits Together These features work at different layers: * **Rules** shape the agent's personality and constraints — they're always active. * **Skills** give the agent new capabilities it can invoke on demand. * **Custom Subagents** define specialized worker profiles the agent can delegate tasks to. * **MCP Servers** provide entirely new tools the agent can call. * **Hooks** run shell commands or LLM prompts at lifecycle events (e.g., before a tool runs) to enforce policies or trigger workflows. You can combine all of these in a single project. For example, you might have an `AGENTS.md` file with coding standards, a `review` skill for code review, an MCP server for your issue tracker, and hooks to block destructive commands. *** ## Where Configuration Lives All project-level extensibility configuration lives in the `.devin/` directory at your project root: ``` my-project/ ├── .devin/ │ ├── config.json # Project config (MCP, permissions) │ ├── config.local.json # Personal overrides (gitignored) │ ├── hooks.v1.json # Lifecycle hooks (Claude Code compatible) │ ├── skills/ │ │ └── review/ │ │ └── SKILL.md # A custom skill │ └── agents/ │ └── reviewer.md # A custom subagent profile (reviewer/AGENT.md also works) ├── AGENTS.md # Project rules └── src/ ``` User-level configuration lives in `~/.config/devin/` and applies to all projects. On Windows, this path is `%APPDATA%\devin\` instead. Files with `.local.` in the name are automatically excluded from git, so you can have personal overrides without affecting your team. *** ## Importing From Other Tools Devin CLI can read configuration from other AI coding tools you may already use: | Source | What's Imported | | -------------------------------------------- | --------------------------------------------------------------------------------------------------------- | | `AGENTS.md` / `AGENT.md` / `CLAUDE.md` | Rules (always-on context) | | `.cursor/rules/*.md` / `.cursor/rules/*.mdc` | Rules | | `.windsurf/rules/*.md` | Rules | | `.claude/` directory | Commands, [custom subagents](/cli/subagents#custom-subagents), [hooks](/cli/extensibility/hooks/overview) | This means you can start using Devin CLI without rewriting your existing configuration. Import is enabled by default and can be controlled in your config file: ```json theme={null} { "read_config_from": { "cursor": true, "windsurf": true, "claude": true } } ``` Set any provider to `false` to disable importing from it. # MCP Configuration Source: https://docs.devinenterprise.com/cli/extensibility/mcp/configuration How to add, configure, and manage MCP servers ## Adding MCP Servers ### Via Command Line The quickest way to add an MCP server: ```bash theme={null} # stdio server — just pass the command after -- devin mcp add -- [args...] # HTTP server — pass the URL as a positional argument devin mcp add # HTTP server — or use the --url flag devin mcp add --url ``` The transport type is inferred automatically: a URL implies HTTP (Streamable HTTP), and trailing args (or `--command`) imply stdio. Remote MCP servers use Streamable HTTP by default. If the server responds with an HTTP 4xx error, the CLI falls back to SSE on the same URL. Set `"transport": "sse"` explicitly if needed — see [Legacy SSE fallback](#legacy-sse-fallback) below. By default, servers are saved to **local** scope (`.devin/mcp_config.local.json`, gitignored). Use `-s`/`--scope` to change: ```bash theme={null} devin mcp add -s project # shared via .devin/mcp_config.json devin mcp add -s user # global (~/.config/devin/mcp_config.json; %APPDATA%\devin\mcp_config.json on Windows) ``` You can also manage servers from the command line: ```bash theme={null} devin mcp list # List all configured servers devin mcp get # Show details for a specific server devin mcp remove # Remove a configured server devin mcp login # Authenticate with a server via OAuth devin mcp logout # Remove stored OAuth credentials devin mcp enable # Enable a disabled server devin mcp disable # Disable a server without removing it ``` ### Via Config File Add servers directly to your MCP config file's `mcpServers` section: **The MCP config file location changed in v3000.3 (the Local 3.6 release).** Older versions (before v3000.3) store MCP servers in the `mcpServers` key of the main config files (`~/.config/devin/config.json`, `.devin/config.json`, `.devin/config.local.json`). Newer versions store them in dedicated files at the same locations: `~/.config/devin/mcp_config.json` (`%APPDATA%\devin\mcp_config.json` on Windows), `.devin/mcp_config.json`, and `.devin/mcp_config.local.json`. Any `mcpServers` entries found in the main config files are migrated to the dedicated files automatically on startup. ```json theme={null} // .devin/mcp_config.json { "mcpServers": { "server-name": { "command": "npx", "args": ["-y", "@company/mcp-server"], "env": { "API_KEY": "your-key" } } } } ``` Project-level servers are shared with your team via version control. ```json theme={null} // ~/.config/devin/mcp_config.json { "mcpServers": { "my-server": { "command": "node", "args": ["/path/to/my-server.js"], "env": {} } } } ``` User-level servers apply to all your projects. ```json theme={null} // .devin/mcp_config.local.json { "mcpServers": { "server-name": { "command": "npx", "args": ["-y", "@company/mcp-server"], "env": { "API_KEY": "my-personal-key" } } } } ``` Local configs are gitignored — use these for personal API keys. *** ## Server Configuration Options MCP servers can be configured in two ways: as a **local command** (stdio transport) or as a **remote server** (HTTP transport). ### Local Command (stdio) | Field | Type | Required | Description | | ---------- | --------- | -------- | --------------------------------------------------------------------------------------------------------- | | `command` | string | Yes | The executable to run | | `args` | string\[] | No | Command-line arguments | | `env` | object | No | Environment variables to set | | `disabled` | boolean | No | Set to `true` to skip this server (see [Enabling and disabling servers](#enabling-and-disabling-servers)) | ### Remote Server (Streamable HTTP) | Field | Type | Required | Description | | ------------------- | ------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `url` | string | Yes | The URL of the MCP server endpoint | | `transport` | string | No | `"http"` (Streamable HTTP, default for URL-based servers) or `"sse"` (legacy SSE). When set to `"http"` or omitted, the CLI tries Streamable HTTP first and falls back to SSE on 4xx errors ([per spec](https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/transports/#backwards-compatibility)). Set `"sse"` explicitly if the server's SSE endpoint is at a different path. | | `headers` | object | No | Custom HTTP headers to include in requests | | `oauthClientId` | string | No | Pre-registered OAuth client ID, for servers that don't support dynamic client registration (DCR), e.g. GitHub. See the "Pre-registered OAuth clients" section below. | | `oauthClientSecret` | string | No | OAuth client secret, for confidential clients. Pair with `oauthClientId`. | | `oauthResource` | string | No | Override the RFC 8707 `resource` parameter sent in OAuth requests (default: the MCP server URL). Set to an empty string (`""`) to omit the parameter entirely, for providers that reject it. See [OAuth resource override](#oauth-resource-override). | | `disabled` | boolean | No | Set to `true` to skip this server (see [Enabling and disabling servers](#enabling-and-disabling-servers)) | ### Examples ```json theme={null} { "mcpServers": { "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_TOKEN": "ghp_..." } } } } ``` ```json theme={null} { "mcpServers": { "notion": { "url": "https://mcp.notion.com/mcp", "transport": "http" } } } ``` After adding an OAuth-based server, run `devin mcp login notion` to authenticate. See [Authentication](#authentication) below. ```json theme={null} { "mcpServers": { "linear": { "url": "https://mcp.linear.app/mcp", "transport": "http" } } } ``` ```json theme={null} { "mcpServers": { "atlassian": { "url": "https://mcp.atlassian.com/v1/mcp", "transport": "http" } } } ``` After adding, run `devin mcp login atlassian` to authenticate. Each MCP client (Windsurf, Claude Code, Devin CLI) maintains its own OAuth session, so you must log in separately even if you've already authenticated in another tool. ```json theme={null} { "mcpServers": { "my-tools": { "command": "python", "args": ["./scripts/mcp-server.py"], "env": { "DB_URL": "postgres://localhost/mydb" } } } } ``` *** ## Authentication Some remote MCP servers require OAuth authentication. After adding an OAuth-based server to your config, authenticate using the `login` command: ```bash theme={null} devin mcp login ``` For example: ```bash theme={null} devin mcp login notion # Authenticate with Notion devin mcp login linear # Authenticate with Linear ``` This opens a browser window where you can authorize access. The OAuth tokens are stored locally and refreshed automatically. You can optionally request specific OAuth scopes: ```bash theme={null} devin mcp login notion --scopes read,write ``` To remove stored OAuth credentials for a server: ```bash theme={null} devin mcp logout ``` If the server supports OAuth, you will also be prompted to authenticate automatically when the server is first used. ### Re-authenticating Stored OAuth credentials don't last forever — they expire, and an administrator can revoke them on the provider side. When that happens the server reports an **auth-required** state instead of connecting, and its tools (and [prompts](/cli/extensibility/mcp/overview#prompts-as-slash-commands)) stop being available until you sign in again. To re-authenticate, clear the stored credentials and run the browser flow again: ```bash theme={null} devin mcp logout devin mcp login ``` `logout` deletes the persisted tokens for that server; `login` re-runs the OAuth flow and stores fresh ones. Do the same after changing `oauthClientId`, `oauthClientSecret`, or `oauthResource` — credentials issued under the old settings are not reused. Editor integrations that drive Devin CLI over ACP surface the same auth-required state, with a re-authenticate action that clears the stored credentials and reopens the browser flow — equivalent to the `logout` + `login` pair above. ### Pre-registered OAuth clients Most OAuth-based MCP servers support [dynamic client registration](https://datatracker.ietf.org/doc/html/rfc7591) (DCR), so Devin CLI registers itself automatically and you don't need to provide any client credentials. Some providers (e.g. GitHub) don't support DCR and instead require a **pre-registered** OAuth client. For those, supply the client ID — and a client secret if it's a confidential client — via `oauthClientId` / `oauthClientSecret`: ```json theme={null} { "mcpServers": { "my-server": { "url": "https://mcp.example.com/mcp", "transport": "http", "oauthClientId": "Iv1.abc123def456", "oauthClientSecret": "${env:MY_MCP_CLIENT_SECRET}" } } } ``` When `oauthClientId` is set, Devin CLI skips dynamic client registration and uses your pre-registered client during the OAuth flow. Run `devin mcp login ` (or trigger first use) to authenticate as usual. You can also set these from the command line when adding or logging into a server: ```bash theme={null} devin mcp add my-server --oauth-client-id --oauth-client-secret devin mcp login my-server --oauth-client-id --oauth-client-secret ``` `oauthClientId` / `oauthClientSecret` are OAuth client credentials used during the authorization flow. They are **not** generic per-request credentials — if a server expects a static token, use `headers` (HTTP) or `env` (stdio) instead. Don't commit a client secret to a shared config. Reference it from an environment variable (`${env:VAR}`), read it from a file (`${file:/path}`), or put it in `.devin/mcp_config.local.json` (gitignored). See the "Managing Secrets" section below. ### OAuth resource override During OAuth authorization and token exchange, Devin CLI sends an [RFC 8707](https://datatracker.ietf.org/doc/html/rfc8707) `resource` parameter so the authorization server can issue audience-restricted tokens. By default the value is the MCP server's URL. Override it with `oauthResource`: ```json theme={null} { "mcpServers": { "my-server": { "url": "https://my-server.example.com/mcp", "transport": "http", "oauthResource": "" } } } ``` The field has three behaviors: * **Unset** (default): sends `resource` set to the MCP server URL. * **Non-empty value**: replaces the default with your value (e.g. a specific application ID URI). * **Empty string (`""`)**: omits the `resource` parameter entirely from both the authorization URL and the token exchange. You can also set it from the command line when adding or logging into a server: ```bash theme={null} devin mcp add my-server --oauth-resource "" devin mcp login my-server --oauth-resource "" ``` Like other OAuth fields, `oauthResource` supports `${env:VAR}` and `${file:/path}` expansion. *** ## Enabling and Disabling Servers You can temporarily disable an MCP server without removing its configuration. A disabled server is skipped during tool discovery — its tools won't appear and the server process won't be started. ```bash theme={null} devin mcp disable # Disable a server devin mcp enable # Re-enable it ``` This sets the `"disabled": true` flag on the server entry in the config file. Use `-s`/`--scope` to target a specific scope: ```bash theme={null} devin mcp disable -s project my-server devin mcp enable -s user my-server ``` You can also set the flag directly in your config file: ```json theme={null} { "mcpServers": { "my-server": { "command": "npx", "args": ["-y", "@company/mcp-server"], "disabled": true } } } ``` Disabling is useful when you want to keep a server's configuration (including environment variables and OAuth credentials) but temporarily stop using it — for example, to reduce startup time or isolate an issue. *** ## Managing Secrets Never commit API keys or secrets to version control. Use `.devin/mcp_config.local.json` for sensitive values. For team projects, the recommended pattern is: 1. Define the server in `.devin/mcp_config.json` with placeholder or no env vars 2. Each team member adds their personal keys in `.devin/mcp_config.local.json` The local config file is automatically excluded from git. *** ## MCP Permissions You can pre-approve, deny, or force-ask for specific MCP tools in your permissions config: ```json theme={null} { "permissions": { "allow": [ "mcp__github__list_issues", "mcp__github__create_issue" ], "deny": [ "mcp__github__delete_repo" ], "ask": [ "mcp__linear__*" ] } } ``` **Permission matcher patterns:** | Pattern | Matches | | ------------------- | ------------------------------------ | | `mcp__server__tool` | A specific tool on a specific server | | `mcp__server__*` | All tools on a specific server | | `mcp__*` | All MCP tools on all servers | *** ## Prompts Prompts need no configuration of their own: any connected server that declares the MCP `prompts` capability automatically contributes `/mcp____` slash commands. Because the command name embeds the server name, renaming a server in `mcpServers` renames its prompt commands too. See [MCP Overview — Prompts as slash commands](/cli/extensibility/mcp/overview#prompts-as-slash-commands). *** ## Organization restrictions If you're on an enterprise team, your admin may restrict which MCP servers you can connect to. A server you've configured can be blocked if MCP is disabled for your team, or if it isn't on your team's allowlist or in an enforced **MCP registry** — in which case it won't connect and its tools won't be available. See [Team Settings — MCP Registry](/cli/enterprise/team-settings#mcp-registry) for details. *** ## Troubleshooting If you see errors like `Auth required` or `AuthRequired` when connecting to a remote MCP server, the server requires OAuth authentication. Run: ```bash theme={null} devin mcp login ``` Each MCP client authenticates independently. Even if you've already authenticated in Windsurf or Claude Code, you need to run `devin mcp login` separately for Devin CLI. To verify your auth status, try removing and re-adding credentials: ```bash theme={null} devin mcp logout devin mcp login ``` Verify the command works outside Devin CLI: ```bash theme={null} npx -y @modelcontextprotocol/server-github ``` Check that all required environment variables are set. Ask the agent to list MCP servers and tools. The server may need a moment to initialize. Check your permissions config. MCP tools default to prompting for approval. Add them to `permissions.allow` to auto-approve. Some authorization servers reject OAuth requests that include the RFC 8707 `resource` parameter. Set `oauthResource` to an empty string to omit the parameter: ```json theme={null} { "mcpServers": { "my-server": { "url": "https://my-server.example.com/mcp", "oauthResource": "" } } } ``` Then re-authenticate: ```bash theme={null} devin mcp logout my-server devin mcp login my-server ``` See [OAuth resource override](#oauth-resource-override) for the full set of `oauthResource` behaviors. When connecting to an HTTP server, Devin CLI tries **Streamable HTTP** first. If the server responds with an HTTP 4xx error (e.g. 404 or 405), it automatically falls back to **legacy SSE** on the **same configured URL**. This follows the [MCP spec's backwards-compatibility guidance](https://spec.modelcontextprotocol.io/specification/2025-03-26/basic/transports/#backwards-compatibility). The fallback only triggers on 4xx responses — connection errors, timeouts, and 5xx responses are reported directly without attempting SSE. If your server's SSE endpoint is at a different path (e.g. `/sse` instead of `/mcp`), set `"transport": "sse"` with the SSE URL to connect directly without the Streamable HTTP attempt. If both transports fail, the error message includes details from both attempts to help with troubleshooting. # MCP Overview Source: https://docs.devinenterprise.com/cli/extensibility/mcp/overview Extend Devin CLI with external tool servers using the Model Context Protocol MCP (Model Context Protocol) lets you connect external tool servers to Devin CLI, giving the agent access to APIs, databases, issue trackers, and any other service you can wrap in an MCP server. When you configure an MCP server, its tools become available to the agent just like built-in tools. The agent can discover what tools are available and call them as needed. *** ## How It Works You define an MCP server in your config file with a command, arguments, and optional environment variables. Devin CLI starts the server process when needed. The server connects to the external API (GitHub, Linear, etc.). The agent discovers what tools the server provides (e.g., `create_issue`, `list_repos`). When the agent calls an MCP tool, the request flows through the server to the external service and the result is returned. *** ## Quick Example Add a GitHub MCP server to your project: ```json theme={null} // .devin/mcp_config.local.json (gitignored — keep tokens out of committed config) { "mcpServers": { "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_TOKEN": "ghp_your_token_here" } } } } ``` Now the agent can create issues, read PRs, search repos, and more — all through natural language. *** ## Permission Control Once configured, MCP tools appear with a namespaced format: `mcp____`. For example, a "github" server with a "create\_issue" tool becomes `mcp__github__create_issue`. MCP tools are subject to the same permission system as built-in tools. You can control access at multiple levels: ```json theme={null} { "permissions": { "allow": [ "mcp__github__*" ], "deny": [ "mcp__github__delete_repo" ] } } ``` See [Permissions](/cli/reference/permissions) for the full permission syntax. *** ## Prompts as Slash Commands Beyond tools, an MCP server can publish **prompts** — reusable, parameterized instructions declared through the MCP `prompts` capability. Devin CLI exposes each one as a slash command: ``` /mcp____ [arguments] ``` For example, a `linear` server that publishes a `bug_report` prompt becomes `/mcp__linear__bug_report`. Prompt commands are listed in the command palette under their own **MCP** category, described with the title or description the server publishes, and annotated with an argument hint built from the prompt's declared parameters — `` for required arguments and `[name]` for optional ones. When you send the command, Devin CLI fetches the prompt from the server and substitutes the messages it returns as your message for that turn. ### How arguments map Whatever you type after the command name is mapped **positionally** onto the prompt's declared arguments — first word to the first argument, second word to the second, and so on. The last declared argument receives all of the remaining text, so free-form trailing input survives intact: ``` /mcp__linear__bug_report ENG-1234 login page hangs after the SSO redirect ``` Here `ENG-1234` fills the first declared argument and the rest of the line fills the last one. If the prompt declares no arguments at all, anything you type is appended to the expanded prompt rather than dropped. Only servers that have already connected contribute advertised commands (connections are warmed in the background at startup), but invocation resolves lazily — typing `/mcp____` works even when the command was never advertised, connecting to the server on demand. Prompt expansion happens in the agent rather than in the terminal UI, so the same commands are advertised over ACP — editor integrations such as [Zed](/cli/acp/zed) and [JetBrains](/cli/acp/jetbrains) list them alongside built-in commands. *** ## Authentication Some remote MCP servers (such as Atlassian, Notion, and Linear) require OAuth authentication. Each MCP client authenticates independently — tokens from Windsurf or Claude Code are **not** shared with Devin CLI. After adding a remote server, authenticate with: ```bash theme={null} devin mcp login ``` This opens a browser window for the OAuth flow. If stored credentials later expire or are revoked, the server reports an auth-required state and you re-authenticate with `devin mcp logout` followed by `devin mcp login` — see [MCP Configuration — Authentication](/cli/extensibility/mcp/configuration#authentication) and [Re-authenticating](/cli/extensibility/mcp/configuration#re-authenticating) for details. *** ## Disabling Servers You can temporarily disable an MCP server without removing its configuration or credentials: ```bash theme={null} devin mcp disable devin mcp enable ``` See [MCP Configuration — Enabling and disabling servers](/cli/extensibility/mcp/configuration#enabling-and-disabling-servers) for details. *** ## Next Steps Learn how to configure MCP servers in detail Control which MCP tools the agent can use # Plugins Source: https://docs.devinenterprise.com/cli/extensibility/plugins/overview Reference for installing, authoring, and governing plugins across Devin cloud sessions, the CLI, and Devin Desktop. Plugins are in **closed beta**. To request access, contact [support@cognition.ai](mailto:support@cognition.ai). Behavior and configuration may change in future releases. A **plugin** is a bundle of [skills](/cli/extensibility/skills/overview) and optional rules, hooks, MCP servers, or custom subagents that you can install from a GitHub repo, a git URL, a subfolder of a repo, or a local folder. Plugins work across Devin cloud sessions, the [Devin CLI](/cli/index), and Devin Desktop, subject to the surface-specific limitations described below. Installing a plugin makes its skills available as `/:` slash commands. The **plugin is the unit of installation**. Installing a plugin installs all of its skills and its `requiredPlugins`; you can't install individual skills from a plugin. To offer skills separately, split them into separate plugins. A plugin is just a source that contains: ``` my-plugin/ ├── .devin-plugin/ │ └── plugin.json # The plugin manifest ├── AGENTS.md # Optional always-on rule ├── rules/ # Optional triggered rules ├── agents/ │ └── reviewer.md # Optional custom subagent (reviewer/AGENT.md also works) ├── hooks.json # Optional lifecycle hooks ├── .mcp.json # Optional MCP servers └── skills/ └── review/ └── SKILL.md # An ordinary skill ``` The `skills/` directory holds ordinary skills — plugins introduce no new skill format. See [Creating Skills](/cli/extensibility/skills/creating-skills) for the `SKILL.md` format. One repo (or one `git-subdir` subfolder) is one plugin. A single repo can host many plugins as subfolders, each referenced with its own `git-subdir` source. Beyond skills, a plugin can ship: * **Rules** — an `AGENTS.md` at the plugin root is injected as an always-on rule in every session, alongside your project's own rules. Markdown files in a `rules/` folder are loaded too, with the same `trigger` frontmatter and [activation types](/cli/extensibility/rules#rule-activation-types) as [Windsurf rules](/cli/extensibility/rules#rules-from-other-tools). * **Custom subagents** — `agents/.md` or `agents//AGENT.md` profiles (the same [custom subagent format](/cli/subagents#custom-subagents) as project subagents), available as `:`. Plugin subagents currently load in local Devin agents only — the CLI and Devin Desktop — not in cloud Devin sessions. * **Hooks** — a `hooks.json` at the plugin root registers [lifecycle hooks](/cli/extensibility/hooks/lifecycle-hooks) that run in every session where the plugin is installed. In cloud sessions, `command` hooks run on the session's machine and only fire while that machine is up. They support every event except `SessionStart` and `SessionEnd` — including `PreToolUse`, `PostToolUse`, `PermissionRequest`, `UserPromptSubmit`, `Stop`, and `PostCompaction`; `prompt`-type hooks are CLI/local-only. * **MCP servers** — plugins can provide optional [MCP servers](/cli/extensibility/mcp/overview) that start with the session. Their tools are available to Devin, although plugin MCP servers don't yet appear in the MCP settings UI. A plugin MCP config may set an OAuth client ID and scopes, but never a client secret — a server config carrying one is rejected at activation. ### Compatible formats The layout above is Devin's own plugin format. Devin also loads plugins packaged in two other layouts, with manifest precedence `.devin-plugin/plugin.json` > `.claude-plugin/plugin.json` > root `plugin.json`: * **Claude plugins** — if there's no `.devin-plugin/plugin.json`, Devin falls back to `.claude-plugin/plugin.json`. Claude plugins' root `.mcp.json` and manifest `mcpServers` field are honored, and `${CLAUDE_PLUGIN_ROOT}` in server configs expands to the plugin root. * **Agent Plugins** — plugins packaged per the open [Agent Plugins 1.0.0](https://github.com/agentplugins/agent-plugins-spec) spec (a `plugin.json` manifest at the plugin root, MCP servers in a root `mcp.json`, skills under `skills/`) load too. For these plugins the root `mcp.json` is read as a conventional MCP source (after `.mcp.json`, which wins on a server-name collision) — legacy Devin/Claude-layout plugins never read it unless their manifest declares it explicitly. MCP entries may declare their transport with the spec's `type` field (`stdio`, `streamable-http`, or `sse`) instead of `transport`, and `${PLUGIN_ROOT}` in server configs expands to the plugin root like `${CLAUDE_PLUGIN_ROOT}`. An unrecognized `$schema` version is warned about and the plugin still loads best-effort. Agent Plugins MCP servers also get the spec's runtime conventions (these apply only to plugins whose manifest is the root `plugin.json`; Devin and Claude layouts behave exactly as before): * `${PLUGIN_DATA}` in `args`, `env` values, and `cwd` expands to a persistent, writable per-plugin data directory. The directory is keyed by plugin identity — not version — so its contents survive plugin updates, and it's deleted when the plugin is uninstalled. * `stdio` server processes receive `PLUGIN_ROOT` and `PLUGIN_DATA` environment variables alongside any `env` the config sets. * A server may set `cwd` (relative to the plugin root); it defaults to the plugin root. A `./`-prefixed `command` resolves against the plugin root, so plugins can ship their own executables. Both are validated to stay inside the plugin root or data directory. *** ## Installing a plugin A plugin source can be a GitHub `owner/repo`, a git URL, or a local path: ```bash theme={null} # From GitHub devin plugins install acme/review-tools # From any git host devin plugins install https://gitlab.com/acme/review-tools.git # From a local folder (great for authoring) devin plugins install ./my-plugin ``` Before installing, Devin shows what the plugin adds — the skills it provides, any required plugins that will be auto-installed, and any policy it introduces (for example, if it forbids other plugins). Pass `-y` / `--yes` to skip the prompt. Plugins are installed at the **user** level and are available across all your projects. *** ## Managing plugins ```bash theme={null} # List installed plugins, their versions, and whether any are blocked by policy devin plugins list # Show a plugin's skills and its required/optional/forbidden lists devin plugins info review-tools # Re-fetch a plugin (or all plugins) at the latest version devin plugins update review-tools devin plugins update # Remove a plugin (auto-installed required plugins are left in place) devin plugins remove review-tools ``` Local plugins are linked directly to their source folder, so edits are live: `devin plugins install ./my-plugin` → edit `skills//SKILL.md` → changes apply on the next session, no `update` needed. *** ## Manifest `.devin-plugin/plugin.json` describes the plugin. Only `name` is required, and it must be unique among installed plugins (it is the `/:…` namespace). Names are lowercase alphanumeric characters with single `-` or `.` separators (e.g. `review-tools`, `acme.tools`). ```jsonc theme={null} { "name": "review-tools", "version": "1.0.0", "description": "Code-review skills for our team", "requiredPlugins": [ "acme/secure-base", { "source": "github", "repo": "acme/audit-logging" } ], "optionalPlugins": [ "acme/deploy-tools", { "source": "url", "url": "https://gitlab.com/acme/extra.git" } ], "forbiddenPlugins": ["sketchy-org/bad-plugin", "acme/*", "*"] } ``` ### Metadata `name`, `version`, `description`, `author` (`{ name, email }`), `homepage`, `repository`, `license`, and `keywords`. Only `name` is used for the plugin's identity and namespace; the rest are descriptive and shown by `devin plugins info`. ### Skills & Rules The `skills` field controls where skills load from, replacing the default `skills/` directory. It accepts a single plugin-root-relative path or an array of them: ```jsonc theme={null} { "skills": "custom-skills" } { "skills": ["skills", "extra/skills"] } ``` An empty array (`"skills": []`) disables skill loading entirely. Paths must stay inside the plugin — absolute paths, `~`, and `..` traversal are rejected, and an invalid entry fails the whole manifest. Rules load independently of `skills`: an `AGENTS.md` at the plugin root is always-on, and Markdown files in the `rules/` directory are loaded as triggered rules. See [Rules](/cli/extensibility/rules) for activation details. ### MCP Servers The `mcpServers` field adds [MCP server](/cli/extensibility/mcp/overview) declarations. Plugins can also use the conventional root `.mcp.json` (and `mcp.json` for plugins using the Agent Plugins root-manifest layout). Four shapes are accepted: ```jsonc theme={null} // One declaration file { "mcpServers": "config/mcp.json" } // Several, read in the order listed { "mcpServers": ["config/mcp.json", "config/extra.json"] } // Only these files — suppresses the root .mcp.json / mcp.json convention { "mcpServers": { "paths": ["config/mcp.json"], "exclusive": true } } // Inline server map (suppresses the root convention when non-empty) { "mcpServers": { "linear": { "command": "npx", "args": ["-y", "linear-mcp"] } } } ``` Declared paths follow the same containment rules as `skills`, but unsafe entries are dropped rather than failing the plugin. An invalid `mcpServers` field only disables MCP loading, leaving skills, rules, and hooks usable. An empty array adds no declaration files but does not suppress the root convention. An empty inline map likewise leaves the root convention enabled. When the same server name appears in more than one source, the first source wins. ### Dependencies A dependency entry is a **source** — either a string shorthand or an object: | Form | Meaning | | ------------------------------------------------------------------ | ----------------------------------------------- | | `"owner/repo"` | GitHub repository | | `"https://…"`, `"git@…"`, `"ssh://…"` | any git URL | | `{ "source": "github", "repo": "owner/repo" }` | GitHub, object form | | `{ "source": "url", "url": "https://gitlab.com/team/plugin.git" }` | git URL, object form | | `{ "source": "git-subdir", "url": "…", "path": "sub/dir" }` | a plugin living in a subfolder of a shared repo | All GitHub forms for the same repo (`owner/repo`, the HTTPS URL, the `.git` URL, the SSH form) refer to the same plugin identity. A plugin can declare three lists, which let a single plugin act as a curated, governed collection of other plugins. #### `requiredPlugins` Auto-installed (recursively) when the plugin is installed. If a required plugin is blocked by policy, the whole install fails — there is no partial install. #### `optionalPlugins` An **allow-list** of plugins this plugin endorses. They are **not** auto-installed; the list only matters as a carve-out against a forbidden entry (see below). #### `forbiddenPlugins` A **deny-list** of plugin identities and glob patterns. `forbiddenPlugins` entries are matched against plugin identities: * An **exact identity**, written as `owner/repo` or a git URL. All GitHub forms of the same repo (`owner/repo`, the HTTPS URL, the `.git` URL, the SSH form) refer to the same identity. * A **glob pattern** — any entry containing `*`. The `*` matches any sequence of characters, including `/`: `acme/*` matches all of `acme`'s GitHub repos, `*/secrets` matches a repo named `secrets` under any owner, and `https://gitlab.com/acme/*` matches any repo under that path. * The lone `"*"`, which matches everything else (a full lockdown). The lists combine deny-wins: * **Deny wins.** A plugin is blocked if any active manifest or installed plugin forbids it. If nothing forbids anything, nothing is blocked. * **Self-override.** A manifest's (or plugin's) own `requiredPlugins` and `optionalPlugins` — and, for a plugin, the plugin itself — are exempt from its **own** forbidden list, so `"forbiddenPlugins": ["*"]` plus `"optionalPlugins": ["acme/approved"]` means "allow only what this manifest lists; forbid everything else." The carve-out covers only those direct entries, not a required plugin's transitive dependencies — list those explicitly under a lockdown. * **No cross-scope re-permitting.** One manifest's or plugin's allow-list cannot re-permit what **another** forbids. A `"forbiddenPlugins": ["*"]` lockdown can't be defeated from a lower scope. Enforcement happens at two points: * **Install time** — installing a blocked plugin (or one whose required plugins can't be satisfied, or whose name collides with an installed plugin) is refused. * **Load time** — a plugin blocked after it's already installed stays on disk, but its skills are skipped at session start with a warning naming the forbidder. A forbidden identity can also be a **local path** (for plugins installed from a local folder), in addition to the `owner/repo` and git-URL forms above. *** ## Inheritance and levels Plugins aren't declared in one place. Beyond your own installs, plugins can be required, endorsed, or forbidden by your repo and by your organization's admin. Each source is a **level**, and the levels are ranked by **authority**, highest first: 1. **Enterprise** — the account-wide managed manifest, configured by an admin. 2. **Org** — an org-level managed manifest, layered below its account (an org can add to what its account declares, but can't overrule it). This applies only to **cloud Devin sessions**: the CLI authenticates at the account level and has no org context, so org-level requires and forbids don't reach CLI users. Put anything you need enforced in the CLI in the enterprise/account manifest. 3. **Repo** — the `requiredPlugins` / `optionalPlugins` / `forbiddenPlugins` in a checkout's `.devin/config.json`, discovered by walking up from your working directory. 4. **User** — plugins you install yourself with `devin plugins install`. Every level declares the same three lists, and within a level they combine with the same [deny-wins, self-override rules](#dependencies) as a single manifest. What the levels add on top is one rule: **higher authority wins**. ### Higher authority wins * A lower level can never **re-permit** what a higher level forbids. * A lower level can never **forbid** what a higher level requires — the forbid is ignored and the plugin still loads. So an admin can mandate a plugin no repo or user can opt out of, and forbid a plugin no lower level can bring back. ### A denylist is only overridden at its own level Because allow-lists don't cross levels, the **only** way to carve an exception out of a denylist is at the same level that declared it. A level's `forbiddenPlugins` is overridden only by that same manifest's own `optionalPlugins` (or `requiredPlugins`) — never by a list at a lower level. For example, an enterprise-level managed manifest can lock the account down to a single approved plugin: ```jsonc theme={null} // Enterprise-level managed manifest { "forbiddenPlugins": ["*"], "optionalPlugins": ["acme/approved"] } ``` This means "across the whole account, allow only `acme/approved` and forbid every other plugin." No org, repo, or user can widen that allow-list — not by installing a plugin, and not by adding it to a lower level's `optionalPlugins`. The carve-out also covers only the entries this manifest lists directly; a required plugin's own transitive dependencies aren't exempt, so list those explicitly under a lockdown. ### Conflicts and dependencies * A require and a forbid for the same plugin at the **same level** but from **different manifests** (for example two separately installed user-level plugins) resolve to the forbid — an allow-list only exempts entries in its *own* manifest, so it can't rescue a plugin another manifest forbids. (Within a single manifest, its own required/optional stay exempt from its own forbids, as [above](#a-denylist-is-only-overridden-at-its-own-level).) * A plugin blocked by governance **soft-fails**: at session start its skills are skipped with a warning naming the forbidder, rather than aborting the session. * Being depended upon grants no exemption. A plugin pulled in only as a transitive dependency is still subject to every forbid that applies to it, and it inherits the highest authority level of any plugin that requires it. # Quickstart: team marketplace Source: https://docs.devinenterprise.com/cli/extensibility/plugins/quickstart Set up a shared Devin plugin marketplace for your team with reusable skills, rules, hooks, MCP servers, and governance. Plugins are in **closed beta**. To request access, contact [support@cognition.ai](mailto:support@cognition.ai). Behavior and configuration may change in future releases. This quickstart takes you from zero to a **team plugin marketplace**: one repo your org owns that bundles your skills, rules, hooks, and MCP servers, installed automatically for every Devin session and CLI user. For the full background, see [Set up your plugin ecosystem](/product-guides/plugin-ecosystem). ## 1. Fork the template Fork [CognitionAI/team-marketplace-template](https://github.com/CognitionAI/team-marketplace-template). Its layout: ``` your-marketplace/ ├── .devin-plugin/ │ └── plugin.json # the meta-plugin: your baseline + policy ├── AGENTS.md # always-on rule shipped with the baseline ├── plugins/ │ ├── engineering-baseline/ # each subfolder is its own plugin │ ├── security-guardrails/ │ ├── frontend-standards/ │ └── docs-and-release/ └── scripts/validate-template.mjs # CI validation ``` The repo root is itself a plugin — the **meta-plugin**. Installing the repo installs your whole baseline: its manifest's `requiredPlugins` pulls in the plugins every teammate should have, `optionalPlugins` endorses extras, and `forbiddenPlugins` blocks what you don't want. ## 2. Make it yours * In the root `.devin-plugin/plugin.json`, change every `git-subdir` URL to point at **your fork**, and edit the required/optional/forbidden lists. * Add a plugin per team or concern under `plugins//` — each needs its own `.devin-plugin/plugin.json` and typically a `skills//SKILL.md`. Starting a plugin from scratch? Use [CognitionAI/plugin-template](https://github.com/CognitionAI/plugin-template). * Have an existing repo of skills? Drop each skill folder into a plugin's `skills/` directory — skills inside plugins are ordinary [skills](/cli/extensibility/skills/creating-skills), no format change. ## 3. Test locally with the CLI ```bash theme={null} node scripts/validate-template.mjs # structural validation (also runs in CI) devin plugins install . # install the meta-plugin from your checkout devin plugins list # see everything it pulled in ``` Local installs are linked, so edits apply on your next session — iterate on a skill, then start a session and invoke it as `/:`. ## 4. Distribute it to everyone An org or enterprise admin adds one required plugin to the managed manifest at [Settings → Resources → Plugins](https://app.devin.ai/settings/marketplace): ```json theme={null} { "requiredPlugins": ["your-org/your-marketplace"] } ``` Everyone in scope gets the baseline automatically — cloud sessions and, for the enterprise/account manifest, CLI and Devin Desktop users logged into the account too (org-level manifests reach cloud sessions only). A private repo works as-is: cloud fetches through your Git integration; CLI users fetch with their own git credentials. ## 5. Evolve and govern * Merging to your marketplace repo's default branch **is** the release — new sessions pick it up automatically. See [how updates roll out](/product-guides/plugins#how-updates-roll-out). * Teams add plugins by PR to the marketplace repo; CI validates the layout. * To lock the account down to your approved set only, add `"forbiddenPlugins": ["*"]` to the managed manifest and list every approved plugin (including the meta-plugin's dependencies — transitive deps aren't exempt) in `requiredPlugins`/`optionalPlugins`. Full semantics: [dependencies and governance](/cli/extensibility/plugins/overview#dependencies). ## Next steps * [Set up your plugin ecosystem](/product-guides/plugin-ecosystem) — the full org playbook * [Plugins reference](/cli/extensibility/plugins/overview) — manifest format, install flows, governance levels * [Plugin marketplace](/product-guides/plugins) — the web app side: manifests, scopes, uploads # Rules & AGENTS.md Source: https://docs.devinenterprise.com/cli/extensibility/rules Provide always-on instructions and context that guide the agent in every session Rules are persistent instructions that shape how Devin CLI behaves in your project. They're injected into the agent's context at the start of every session, ensuring consistent behavior across your team. Common uses for rules include coding standards, architectural guidelines, preferred libraries, testing conventions, and project-specific constraints. **To improve coding ability, speed of completion, and lower cost**, we highly recommend **using Skills instead whenever possible**. Skills are only injected into the context when relevant. **Rules and AGENTS should be kept as small as possible.** **Our recommended pattern** is to use a rule to reference skills that the model should use in particular scenarios. *** ## AGENTS.md The simplest way to add rules is with an `AGENTS.md` file at your project root: ```markdown theme={null} # Project Rules - Use TypeScript for all new files - Follow the existing patterns in src/components/ - Always run `npm run lint` before committing - Use pnpm, not npm or yarn - Write tests for all new utility functions ``` Devin CLI reads this file automatically. `AGENTS.md` is the recommended approach for project rules. It's easy to read, version-controlled, and works across multiple AI tools. *** ## Global Rules You can also create rules that apply to **every project** by placing an `AGENTS.md` file in your user config directory: ``` ~/.config/devin/AGENTS.md ``` ``` %APPDATA%\devin\AGENTS.md ``` Global rules are loaded at the start of every session, regardless of which project you're working in. Use them for personal preferences that apply everywhere: ```markdown theme={null} # My Global Rules - Always write commit messages in conventional commit format - Prefer functional patterns over imperative code - Run tests before suggesting a task is complete ``` Global rules work alongside project rules — both are loaded and active at the same time. `AGENT.md` is also supported at this location. If you use Claude Code, Devin CLI also reads `~/.claude/CLAUDE.md` as a global rule. *** ## Personal Rules with AGENTS.local.md If you have personal instructions that shouldn't be shared with collaborators — such as preferred working style, testing habits, or review preferences — create an `AGENTS.local.md` file next to your `AGENTS.md`: ```markdown theme={null} # My Personal Rules - Always start by writing failing tests before implementing a fix - Prefer functional patterns over imperative code - Run the full test suite before marking a task as complete ``` This file is loaded alongside `AGENTS.md` with the same always-on behavior. Add it to your `.gitignore` so it stays local: ```gitignore theme={null} AGENTS.local.md ``` This follows the same convention as `.devin/config.local.json` — the `.local.` suffix signals a personal override that shouldn't be committed. *** ## Supported File Names Devin CLI reads rules from any of these files: | File | Notes | | ----------------- | ------------------------------- | | `AGENTS.md` | Recommended | | `AGENTS.local.md` | Personal rules (gitignored) | | `AGENT.md` | Singular alternative | | `.windsurfrules` | Legacy Windsurf workspace rules | | `CLAUDE.md` | Compatible with Claude Code | All of these are treated identically — their contents are loaded as always-on rules. These files can exist at multiple levels in your project (not just the root). Files at the workspace root are loaded at session start. Files in subdirectories are discovered lazily when the agent accesses files in that directory, keeping the context focused on the relevant part of the codebase. They can also be placed in the [global config directory](#global-rules) to apply across all projects, except `CLAUDE.md` which is read globally from `~/.claude/CLAUDE.md`. Installed [plugins](/cli/extensibility/plugins/overview) can ship rules too: an always-on `AGENTS.md` at the plugin root plus `rules/*.md` files with `trigger` frontmatter. *** ## Rules in the .devin Directory Devin CLI also reads rules from the `.devin/` directory, one rule per file: | Path | Notes | | ------------------------ | ------------------------------------------------- | | `.devin/rules/*.md` | One rule per file. Supports `trigger` frontmatter | | `.devin/global_rules.md` | Single always-on file | These files use the same frontmatter as `.windsurf/rules/*.md`, so the `trigger` values `always_on`, `manual`, `model_decision`, `agent`, and `glob` all apply. `.devin/` is the preferred location and takes precedence over `.windsurf/`. If both `.devin/global_rules.md` and `.windsurf/global_rules.md` exist, Devin CLI loads only `.devin/global_rules.md`. Rule files in `.devin/rules/` and `.windsurf/rules/` are both loaded. Like other project rules, these directories are read at the workspace root and in each directory between the workspace root and your current directory. You can also place them in your home directory (`~/.devin/rules/*.md`, `~/.devin/global_rules.md`) to apply them to every project. *** ## Rules From Other Tools If you're coming from another AI coding tool, Devin CLI can read your existing rules: Devin CLI reads from `.cursor/rules/*.md` and `.cursor/rules/*.mdc`. Cursor rules support frontmatter to control activation: ```markdown theme={null} --- description: "React component guidelines" globs: "src/components/**/*.tsx" alwaysApply: false --- Use functional components with hooks. Never use class components. ``` **Activation behavior:** * `alwaysApply: true` — Always active * `globs` specified — Active when working with matching files * `description` only — Agent decides when to apply * None of the above — User must invoke manually Devin CLI reads from `.windsurf/rules/*.md` and `.windsurf/global_rules.md`. The Devin-native [`.devin/` equivalents](#rules-in-the-devin-directory) take precedence. **Subdirectory support:** `.windsurf/rules/` directories can exist at multiple levels in your project, not just the root. Rules at the workspace root are loaded at session start. Rules in subdirectories are discovered lazily — when the agent accesses files in that directory, any `.windsurf/rules/` found there (and in parent directories up to the workspace root) are automatically loaded. This avoids polluting the agent's context with rules from unrelated parts of the project. Windsurf rules support frontmatter: ```markdown theme={null} --- description: "API design rules" trigger: always_on --- All API endpoints must return JSON with a consistent envelope format. ``` **Trigger values:** `always_on`, `manual`, `model_decision`, `agent`, `glob` Devin CLI reads from the `.claude/` directory. Devin CLI does not support `.codeiumignore` files. If you use Codeium's autocomplete and have configured ignore patterns, those patterns will not apply to Devin CLI. *** ## Controlling Imports You can enable or disable reading from specific tool formats in your config file (`~/.config/devin/config.json` — or `%APPDATA%\devin\config.json` on Windows — or `.devin/config.json`): ```json theme={null} { "read_config_from": { "agents_standard": true, "cursor": true, "windsurf": true, "claude": true } } ``` Standard project rules from `AGENTS.md`, `AGENTS.local.md`, `AGENT.md`, and `.windsurfrules` are read by default. Set `"agents_standard": false` to disable importing them. *** ## Rule Activation Types Rules loaded from external formats may have different activation behaviors: | Type | Behavior | | ------------------ | ----------------------------------------------------------------- | | **Always-on** | Active in every session, no user action needed | | **Glob-activated** | Active when the agent works with files matching specific patterns | | **Agent-decided** | The agent chooses when to apply based on the rule's description | | **User-invocable** | Only active when explicitly triggered by the user | Rules from `AGENTS.md` are always "always-on". *** ## Best Practices Long, verbose rules dilute the agent's attention. Focus on what matters most. "Use pnpm" is better than "use the right package manager". Concrete instructions are easier to follow. Show the pattern you want, not just a description of it. Keep rules in your repo so the whole team benefits from the same guidelines. For most common types of rules, consider using skills instead. Skills give you more control over when and how they're applied. # Creating Skills Source: https://docs.devinenterprise.com/cli/extensibility/skills/creating-skills Full reference for the SKILL.md format and frontmatter options Skills are defined as `SKILL.md` files inside a named directory. This page covers everything you need to know to write effective skills. *** ## File Structure Place skills in the appropriate directory depending on scope: ``` # Project-specific (committed to git) .devin/skills/ └── my-skill/ └── SKILL.md # Global — available in all projects (not committed) # Linux/macOS: ~/.config/devin/skills/ └── my-skill/ └── SKILL.md # Windows: %APPDATA%\devin\skills\ └── my-skill\ └── SKILL.md ``` The directory name is the skill's identifier (used for `/my-skill` invocation). The `SKILL.md` file contains optional YAML frontmatter and the skill's prompt content. On Windows, `%APPDATA%` typically resolves to `C:\Users\\AppData\Roaming`. *** ## Frontmatter Reference ```yaml theme={null} --- name: my-skill description: What this skill does (shown in completions) argument-hint: "[file] [options]" model: sonnet subagent: true allowed-tools: - read - grep - glob - exec permissions: allow: - Read(src/**) deny: - exec ask: - Write(**) triggers: - user - model --- Your prompt content goes here... ``` ### All Frontmatter Fields | Field | Type | Default | Description | | --------------- | ------- | --------------- | ------------------------------------------------------------------------------------------------------- | | `name` | string | directory name | Display name of the skill | | `description` | string | none | Shown in slash command completions | | `argument-hint` | string | none | Hint shown after the command name (e.g., `[filename]`) | | `model` | string | current model | Override the model used when running this skill | | `subagent` | boolean | `false` | Run the skill as a [subagent](/cli/subagents) instead of inline | | `agent` | string | none | Run the skill as a subagent using a specific [custom subagent](/cli/subagents#custom-subagents) profile | | `allowed-tools` | list | all tools | Restrict which tools the skill can use | | `permissions` | object | inherit | Permission overrides for this skill | | `triggers` | list | `[user, model]` | How the skill can be invoked | *** ## Model Override Use the `model` field to run a skill with a different model than the one active in the current session. This is useful for using a faster model for simple tasks or a more capable model for complex ones: ```yaml theme={null} --- name: quick-fix description: Fast lint fix using a lightweight model model: swe --- Fix the lint errors in the current file. ``` The model name uses the same values as the `--model` CLI flag (e.g., `opus`, `sonnet`, `swe`, `codex`). See [Models](/cli/models) for the full list. *** ## Running Skills as Subagents Running skills as subagents is **experimental**. The `subagent` and `agent` frontmatter fields may change in future releases. By default, a skill's prompt is injected into the current conversation — the agent processes it inline. You can instead run a skill as a **subagent**, which spawns an independent worker with its own context window. This is useful for skills that perform focused, self-contained tasks where you don't want the output to clutter the main conversation. There are two ways to run a skill as a subagent: ### `subagent: true` Set `subagent: true` to run the skill as a subagent using the default `subagent_general` profile: ```yaml theme={null} --- name: deep-research description: Thorough codebase research on a topic subagent: true model: sonnet allowed-tools: - read - grep - glob --- Research the topic the user asked about thoroughly. Search broadly, follow references, and trace call chains. Report all findings with specific file paths and line numbers. ``` When invoked, this skill spawns a foreground subagent that runs the skill's prompt as its task. The parent agent waits for the subagent to complete, then reads and summarizes the results. ### `agent: ` Use the `agent` field to run the skill as a subagent with a specific [custom subagent profile](/cli/subagents#custom-subagents): ```yaml theme={null} --- name: review-pr description: Review the current PR using the reviewer subagent agent: reviewer --- Review the staged changes for correctness, security, and style issues. ``` The `agent` value must match the name of a registered subagent profile (either built-in like `subagent_explore` / `subagent_general`, or a custom profile you've defined). The subagent inherits the profile's system prompt, tool restrictions, and model — while the skill's content becomes the task. If both `agent` and `subagent` are set, `agent` takes precedence. The `model` field on the skill overrides the subagent profile's model when both are specified. Skills running as subagents do not spawn nested subagents — if the skill is already executing inside a subagent, it runs inline instead to prevent infinite recursion. ### Orchestrating Subagents Using Skills Because skills can run as subagents, you can use them to orchestrate multi-step work. Define a set of subagent skills that each handle a focused task, then write a regular skill that invokes them. The outer skill becomes the orchestrator — it calls each subagent, collects the results, and decides what to do next. For example, here are two subagent skills and an orchestrator that coordinates them: ```markdown theme={null} --- name: research-changes description: Research recent code changes and their impact subagent: true allowed-tools: - read - grep - glob - exec --- Analyze the recent changes in this repository: 1. Run `git log --oneline -20` to see recent commits 2. For each significant commit, examine what changed and why 3. Identify any patterns, risks, or areas that need attention Report your findings with specific file paths and commit references. ``` ```markdown theme={null} --- name: validate-tests description: Run tests and validate coverage for recent changes subagent: true allowed-tools: - read - grep - glob - exec --- Validate the test suite for the project: 1. Identify the test framework and run command 2. Run the full test suite 3. Check for any failing tests 4. Review test coverage for recently changed files Report which tests pass, which fail, and any coverage gaps. ``` ```markdown theme={null} --- name: health-check description: Full project health check — research changes then validate tests --- Perform a full health check on this project: 1. First, use the /research-changes skill to understand recent changes 2. Then, use the /validate-tests skill to verify the test suite 3. Finally, synthesize the findings from both into a summary: - What changed recently and why - Whether tests are passing - Any risks or recommended actions ``` Invoking `/health-check` runs the orchestrator in the main agent. It calls `/research-changes`, which spawns a subagent to explore the repo. Once that finishes, it calls `/validate-tests`, which spawns another subagent to run the tests. The orchestrator then synthesizes both results into a final summary. A subagent skill will **never** use a subagent when calling other skills, even if those skills have `subagent: true` — they run inline instead. This means you don't need to worry about unbounded nesting. The orchestration pattern is always one level deep: the orchestrator spawns subagents, and those subagents execute everything else inline. *** ## Prompt Content The body of the SKILL.md file (after the frontmatter) is the prompt that gets injected when the skill is invoked. *** ## Permissions Skills can define their own permission scope using the same syntax as the main permissions config: ```yaml theme={null} permissions: allow: - Read(src/**) - Exec(npm run test) deny: - Write(/etc/**) - exec ask: - Write(src/**) ``` **How skill permissions work:** * `allow` — These scopes are auto-approved during skill execution * `deny` — These scopes are blocked during skill execution * `ask` — These scopes always prompt the user Skill permissions are additive to (not replacing) the session's base permissions. A skill cannot grant permissions that are denied at a higher level (project or organization config). *** ## Allowed Tools Restrict which tools the skill can use: ```yaml theme={null} allowed-tools: - read - grep - glob ``` Available tool names: `read`, `edit`, `grep`, `glob`, `exec` You can also allow MCP tools: ```yaml theme={null} allowed-tools: - read - mcp__github__list_issues - mcp__github__create_issue ``` If `allowed-tools` is not specified, the skill has access to all tools. For safety-critical skills, always restrict to the minimum needed. *** ## Examples ### Code Review Skill ```markdown theme={null} --- name: review description: Review staged changes for issues allowed-tools: - read - grep - glob - exec permissions: allow: - Exec(git diff) - Exec(git log) --- Run `git diff --staged` and review the changes for quality issues. Evaluate: 1. **Correctness** — Any logic errors or edge cases? 2. **Security** — Any vulnerabilities introduced? 3. **Performance** — Any obvious inefficiencies? 4. **Style** — Consistent with the codebase? Provide a summary with specific line references. ``` ### Component Generator ```markdown theme={null} --- name: component description: Generate a React component from a description argument-hint: "" allowed-tools: - read - edit - grep - glob model: sonnet permissions: allow: - Write(src/components/**) --- Create a new React component using the name the user provides: 1. Check existing components in src/components/ for style conventions 2. Create the component file at src/components//.tsx 3. Create a barrel export at src/components//index.ts 4. Add basic tests at src/components//.test.tsx 5. Follow the patterns you find in existing components ``` ### Deployment Checklist ```markdown theme={null} --- name: deploy description: Run through the deployment checklist triggers: - user allowed-tools: - read - exec - grep permissions: allow: - Exec(npm run) - Exec(git) --- Run through the deployment checklist: 1. Run the test suite: `npm run test` 2. Run the linter: `npm run lint` 3. Check for uncommitted changes: `git status` 4. Verify the build: `npm run build` 5. Show the current branch and last commit Report the status of each step. If anything fails, stop and explain the issue. ``` ### Search Expert ```markdown theme={null} --- name: find description: Find relevant code across the project argument-hint: "" allowed-tools: - read - grep - glob triggers: - user - model --- Search the codebase thoroughly for what the user asked about. Use grep for content search and glob for file discovery. Provide relevant file paths and code snippets. Explain how the pieces connect. ``` *** ## Tips A skill should do one thing well. Create multiple skills rather than one mega-skill. Show the agent what good output looks like in your prompt. Restricting tools makes skills safer and more predictable. Invoke your skill and iterate on the prompt until the output is what you want. # Skills Overview Source: https://docs.devinenterprise.com/cli/extensibility/skills/overview Create reusable prompts and workflows that extend the agent's capabilities Skills are self-contained units of functionality that you can teach to Devin CLI. They bundle prompts, tool access, permissions, and workflows into a reusable package that can be invoked by either the agent or the human operator. *** ## What Are Skills? Think of skills as expert knowledge you give the agent. A skill might teach it how to: * Review code according to your team's standards * Generate a specific type of component * Run a deployment workflow * Perform a security audit * Set up a new service from a template Users can invoke skills with `/skill-name` in the chat. The agent can invoke skills on its own when relevant. Skills can have their own permission grants and restrictions. Restrict which tools a skill can use for safety. Run skills as independent [subagents](/cli/subagents) with their own context window. Use a different [model](/cli/models) for specific skills. *** ## Quick Example Create a code review skill at `.devin/skills/review/SKILL.md` (or `.windsurf/skills/review/SKILL.md`): ```markdown theme={null} --- name: review description: Review code changes before committing allowed-tools: - read - grep - glob - exec --- Review the current git diff and provide feedback: 1. Run `git diff --staged` (or `git diff` if nothing is staged) 2. Check for: - Logic errors or bugs - Missing error handling - Security issues - Style inconsistencies 3. Summarize findings and suggest improvements ``` Now you can invoke it with `/review` in any session. *** ## How Skills Work When a skill is invoked: 1. The skill's prompt is injected into the conversation 2. Tool access is restricted to the skill's `allowed-tools` (if specified) 3. Additional permissions from the skill's config are applied 4. The specified model is used (if different from the current one) *** ## Skill Triggers Skills can be invoked in two ways: | Trigger | Description | Default | | ------- | ------------------------------------------- | ------- | | `user` | User can invoke with `/skill-name` | Enabled | | `model` | Agent can invoke autonomously when relevant | Enabled | ```yaml theme={null} --- name: security-check triggers: - user - model --- ``` Set `triggers: [user]` to prevent the agent from invoking a skill on its own. *** ## Third-party Skills We support the `.agents` skills standards, so third-party skill installation tools work with Devin CLI. Third-party skills can execute arbitrary code, so install them at your own risk. *** ## Where Skills Live Skills can be scoped to a single project or shared across all projects: | Location | Scope | Committed to git? | | --------------------------------------------- | ---------------------------------------- | ----------------- | | `.agents/skills//SKILL.md` | Project-specific | Yes | | `.devin/skills//SKILL.md` | Project-specific | Yes | | `.windsurf/skills//SKILL.md` | Project-specific | Yes | | `~/.agents/skills//SKILL.md` | Global (all projects) | No | | `~/.config/devin/skills//SKILL.md` | Global (all projects) | No | | `~/.codeium//skills//SKILL.md` | Global (all projects, channel-dependent) | No | **Project skills** live in the `.devin/skills/` or `.windsurf/skills/` directory at your project root and are committed to version control, making them shareable with your team. Both locations use the same `SKILL.md` format. **Global skills** live in `~/.config/devin/skills/` (following [XDG conventions](https://specifications.freedesktop.org/basedir-spec/latest/)) or `~/.codeium//skills/` (where `` is `windsurf`, `windsurf-next`, or `windsurf-insiders` depending on your CLI channel) and are available in every project on your machine. **Windows:** The global skills path follows your system's application data directory. On Windows, use `%APPDATA%\devin\skills\\SKILL.md` (typically `C:\Users\\AppData\Roaming\devin\skills\\SKILL.md`) instead of `~/.config/devin/skills/`. *** ## Next Steps Learn the full skill format including frontmatter options, dynamic content, and examples. Bundle skills into a plugin you can install and share across projects. # Hand off to cloud Devins Source: https://docs.devinenterprise.com/cli/handoff Hand off a task from the Devin CLI to a cloud Devin session with /handoff. When a task outgrows your local machine — or you want Devin to keep working while you step away — use the built-in `/handoff` command to transfer the current session to a cloud [Devin session](/get-started/first-run). The cloud session gets its own VM with a shell, browser, and full repo access, so it can keep going after you close your laptop. ``` /handoff fix the flaky integration tests in CI ``` The Devin CLI packages up the conversation context and your current git branch, then creates a cloud session that picks up where you left off. Track its progress from your terminal or in the [Devin web app](https://app.devin.ai). Run `/handoff` without a task description and the cloud session continues from where you left off automatically. ## When to hand off Hand a task off when it needs more than your local terminal, or when you want it to run in the background: * **VM or server** — running a dev server, hitting endpoints, Docker builds * **Browser** — screenshots, OAuth flows, end-to-end tests, scraping * **CI/CD** — pipeline debugging, deployments, infrastructure changes * **Long-running work** — migrations, batch jobs, large refactors * **Parallel execution** — offload work to the cloud while you keep coding locally ## What carries over The cloud session starts in a fresh VM, so the CLI includes everything it needs to pick up the thread: * **Repo and branch** — so the cloud session clones the right repo and checks out the branch you're on. * **Conversation context** — what you and Devin have been working on in the current session. * **Uncommitted changes** — your work-in-progress diff carries over. Commit or stash anything you don't want sent. Not using the Devin CLI? You can hand off from Claude Code, Codex, Cursor, or any coding agent — and from plain shell scripts — with the open-source [Devin Handoff](https://github.com/club-cog/devin-handoff) plugin. See [Hand off to Devin](/work-with-devin/devin-handoff) for setup and usage across every agent. ## Related resources Hand off from any coding agent, not just the Devin CLI Source, install guides, and the full script reference # Quickstart Source: https://docs.devinenterprise.com/cli/index Get up and running in 2 minutes with Devin CLI, a local command-line coding agent with deep Devin Cloud integration. ```bash theme={null} curl -fsSL https://cli.devin.ai/install.sh | bash ``` On macOS, install Devin CLI with [Homebrew](https://brew.sh): ```bash theme={null} brew install --cask devin-cli ``` To upgrade to the latest version later, run: ```bash theme={null} brew upgrade --cask devin-cli ``` Download and run the installer: * [x86\_64 (most Windows PCs)](https://static.devin.ai/cli/devin-updater-x86_64-pc-windows.exe) * [ARM64 (Windows on ARM)](https://static.devin.ai/cli/devin-updater-aarch64-pc-windows.exe) Alternatively, open **PowerShell** and run: ```powershell theme={null} irm https://static.devin.ai/cli/setup.ps1 | iex ``` `irm` and `iex` are PowerShell commands. Do not run this in Git Bash or CMD — it will fail with "command not found". Use PowerShell for installation only. After installing, you can use Devin CLI from **PowerShell**, **Windows Terminal**, or **Git Bash**. Devin CLI is bundled with **Devin Desktop**. This installation method is available for **Legacy Windsurf Enterprise** and **Devin Enterprise** plans. **Admin setup:** For the Devin Desktop-bundled install, an admin must first enable the install option in Devin CLI team settings by toggling on **Show "Install Devin CLI" in the Devin Desktop Command Palette**. **User installation:** 1. Open Devin Desktop 2. Open the Command Palette with Cmd+Shift+P (macOS) or Ctrl+Shift+P (Windows/Linux) 3. Search for and run **Install Devin CLI** This adds the `devin` binary to your PATH so you can use it from any terminal. That's it! After you restart your terminal, enter a project directory and type `devin` to activate Devin CLI. Also try preloading the session with a prompt for automation: ```bash theme={null} devin -- check out this code and suggest a feasible, helpful feature ``` You're ready to go. For must-know tips, see [Essential Commands](/cli/essential-commands). ## What's next? Devin CLI can implement new features, fix bugs, review code, answer questions, automate tasks, and more. Must-know commands and slash commands Choose the right model for your task Connect MCP servers and skills Explore all commands and flags *** ## Devin CLI vs. Devin Devin CLI and [Devin](/get-started/devin-intro) are separate tools designed for different workflows. **Devin CLI** is a local coding agent that runs directly in your terminal. It works with your local files and environment, giving you fast, interactive assistance right where you code. **Devin** is our cloud-based AI software engineer that runs in a virtual machine. It includes features like Playbooks, Secrets, Knowledge, and other capabilities that are not available in Devin CLI. Devin CLI does not yet support Knowledge, Playbooks, or Secrets from your Devin account. We're actively working on adding support for each of these and plan to roll them out soon. Devin CLI overview # Models Source: https://docs.devinenterprise.com/cli/models Available models and how to configure them Devin CLI supports multiple AI models. You can choose the best model for your task to optimize for maximum capability, speed, or cost efficiency. For most users, we recommend **Adaptive** — our intelligent model router that automatically selects the best model for each task, delivering the right level of intelligence for every prompt. *** ## Available Models Models release frequently. We typically support the latest and greatest models from **Anthropic**, **OpenAI**, **Google**, and **Cognition** within minutes of their launch. We also support a number of **leading open source models** like **DeepSeek**, **Kimi**, and **GLM**. To stay up-to-date on model releases, consider following the [**Cognition** X account](http://x.com/cognition). Short names like `opus`, `sonnet`, `swe`, `codex`, and `gemini` always resolve to the latest version in that model family. ### Reasoning / Thinking Levels Some models support configurable reasoning levels, which control how much compute the model spends "thinking" before responding. You can cycle the thinking level with `Alt+T` (macOS: `Opt+T`) during a session. *** ## Setting the Model ```bash theme={null} devin --model opus -- refactor this module devin --model sonnet -- explain this code ``` Switch models during a session: ```text theme={null} /model opus /model sonnet /model codex ``` Run `/model` with no argument to open the model selector. Set a default in `~/.config/devin/config.json` (on Windows, `%APPDATA%\devin\config.json`): ```json theme={null} { "agent": { "model": "swe-1-6-fast" } } ``` *** ## Model Selection Tips The correct choice of language model varies wildly from person-to-person and task-to-task. Many engineers working on the same project are convinced that their model is the best for the task, despite using different models. The fact of the matter is, AI can perform differently depending on your personal usage and writing style! **As such, we strongly recommend trying multiple models to see which one you prefer.** At minimum we recommend trying `swe`, `gpt`, and `opus`. We find that the vast majority of use-cases can be covered by these three. Use `opus` or `gpt` for multi-file refactors, architecture changes, and tasks requiring deep reasoning. Use `swe` (fast) for straightforward edits, bug fixes, and questions. It's both fast and cheap at a reasonable level of intelligence. Enterprise teams can restrict which models are available through [Team Settings](/cli/enterprise/team-settings). # Sandbox Source: https://docs.devinenterprise.com/cli/sandbox OS-level isolation for Devin CLI sessions: how the sandbox works, network filtering, and enterprise enforcement. The `--sandbox` flag runs the CLI with OS-level isolation, enforcing writable paths and `deny` rules at the operating-system level and optionally restricting network traffic. ## How the sandbox works When the sandbox is active: * **Writable paths** are derived from granted `Write(...)` permission scopes plus the workspace directory; everything else is read-only * **Readable paths** are everything except paths covered by `Read(...)` rules in the `deny` list, which are hidden from sandboxed commands entirely * `Write(...)` scopes granted mid-session dynamically expand the sandbox for subsequent commands. Mid-session `Read(...)` approvals affect only the agent's own tools — they cannot reveal a path hidden by a `Read(...)` deny rule, which stays hidden for the whole session If sandbox resolution fails (e.g., the sandboxing tools are unavailable on the user's platform), the CLI will **refuse to start** rather than running unsandboxed. This fail-closed behavior applies whether sandbox was enabled by a [team setting](/cli/enterprise/team-settings#sandbox-enforcement) or by the user passing `--sandbox` directly, ensuring the security intent is never silently bypassed. Common causes of sandbox resolution failure: * **Windows**: OS-level sandboxing is not currently supported on Windows. Sessions on Windows will hard-fail when `--sandbox` is passed or when sandbox enforcement is **Required**, including when the CLI runs as an ACP server inside an IDE (e.g., Devin Desktop). * **Linux**: Sandboxing requires `bubblewrap` (`bwrap`) and `socat` to be installed. Sessions hard-fail with installation instructions when these are missing. * **Permission scope errors**: Invalid paths in permission scopes that can't be resolved. ## Network filtering Sandbox network filtering is currently unstable. If you need this feature, please reach out to your account representative for stability timelines. Configure domain-level network filtering for the sandbox in the [`sandbox` section of your config file](/cli/reference/configuration/config-file#sandbox) (user config only). When `--sandbox` is active and domain filtering is configured, a managed network proxy starts on loopback and the sandbox restricts all child traffic to route through it. | Option | Type | Default | Description | | ----------------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------- | | `allowed_domains` | string\[] | `[]` | Domain patterns allowed through the proxy. When non-empty, only matching domains are allowed (allowlist mode) | | `denied_domains` | string\[] | `[]` | Domain patterns always blocked. Deny rules take precedence over allow rules | | `network_mode` | string | `"full"` | `"full"` allows all HTTP methods; `"limited"` allows only GET/HEAD/OPTIONS | **Domain pattern syntax:** | Pattern | Matches | | ---------------- | ----------------------------- | | `example.com` | Exact match only | | `*.example.com` | Any subdomain (not the apex) | | `**.example.com` | Apex domain and any subdomain | **Example:** ```json theme={null} { "sandbox": { "allowed_domains": [ "github.com", "**.npmjs.org", "**.crates.io", "**.pypi.org" ], "denied_domains": ["evil.example.com"], "network_mode": "full" } } ``` Domain filtering applies when the sandbox is active (`--sandbox`). Without `--sandbox`, the sandbox section is ignored. ## Excluded commands Sometimes a specific command needs to run *outside* the sandbox — for example `git` commands that must access credentials or hooks the sandbox blocks. The `sandbox.excluded` config section lets you exclude matching commands from sandbox isolation using the same `Exec(...)` rule syntax as [permissions](/cli/reference/permissions): | Option | Type | Description | | ---------------- | --------- | -------------------------------------------------------------------------- | | `excluded.allow` | string\[] | Matching commands run outside the sandbox automatically | | `excluded.ask` | string\[] | Matching commands run outside the sandbox after the user approves a prompt | | `excluded.deny` | string\[] | Matching commands are never excluded — they always stay inside the sandbox | **Example:** ```json theme={null} { "sandbox": { "excluded": { "allow": ["Exec(git status *)"], "ask": ["Exec(git push *)"], "deny": ["Exec(git tag *)"] } } } ``` **Rule resolution:** for each command, the most specific matching rule wins within a source (e.g., `Exec(git push *)` beats `Exec(git *)`), and when both user config and [team settings](#enterprise-excluded-commands) match, the more restrictive verdict wins (`deny` > `ask` > `allow`). Commands with no matching rule — including when `sandbox.excluded` is not configured at all — always run inside the sandbox. * Only `Exec(...)` rules are supported in `sandbox.excluded`; any other rule type (e.g., `Read(...)`, `Write(...)`) is ignored with a warning. * Exclusion is fail-closed: if a command can't be safely resolved (e.g., it can't be parsed), it stays inside the sandbox. * Exclusions apply to the default per-command exec path. Commands run through a persistent PTY shell (interactive sessions, or when `pty_for_noninteractive_exec` is enabled) always stay inside the sandbox. ## Enterprise enforcement Enterprise admins can control sandbox behavior for their entire organization via [Team Settings](/cli/enterprise/team-settings#sandbox-enforcement). ### Sandbox enforcement mode Set the enforcement level for the `--sandbox` flag across your organization: * **Optional** (default) — Users choose whether to pass `--sandbox`. No enforcement. * **Required** — The `--sandbox` flag is forced on for all users, even if they don't pass it on the command line. All CLI sessions run with OS-level file system sandboxing that enforces writable paths and `Read(...)` deny rules. A future **Strict** mode may lock down sandbox configuration entirely, preventing users from modifying sandbox settings. Ensure all target machines are provisioned before setting sandbox enforcement mode to **Required** across your organization. If any users are on Windows, they will be unable to run the CLI until OS-level sandboxing is supported on Windows or the policy is relaxed to **Optional**. ### Enterprise domain filtering Admins can also configure organization-wide domain allowlists and denylists: * **Domain allowlist** — When set, **only** the domains in this list are reachable through the sandbox network proxy. This list is **authoritative**: it completely replaces any user-configured `allowed_domains`. Users cannot add additional domains to bypass admin restrictions. * **Domain denylist** — Domains that are always blocked. Enterprise denied domains are **additive**: they are merged with the user's local `denied_domains`, making the combined list more restrictive. **How enterprise and user domain lists interact:** | Scenario | Enterprise config | User config | Effective result | | -------------------- | --------------------------------- | --------------------------------- | ------------------------------------------------------------ | | Admin sets allowlist | `allowed_domains: ["github.com"]` | `allowed_domains: ["npmjs.org"]` | Only `github.com` is allowed (enterprise replaces user list) | | Admin sets denylist | `denied_domains: ["evil.com"]` | `denied_domains: ["risky.io"]` | Both `evil.com` and `risky.io` are blocked (merged) | | No admin allowlist | `allowed_domains: []` | `allowed_domains: ["github.com"]` | User's allowlist is used | Because the user's local `denied_domains` are preserved and merged additively, a user could deny a domain that appears in the enterprise allowlist. This is intentional: the combined effect is always more restrictive, never less. If this causes access issues, the user should remove the conflicting entry from their local config. ### Enterprise excluded commands Admins can also set organization-wide [excluded command](#excluded-commands) rules in team settings: * **Excluded allow / ask** — `Exec(...)` rules for commands that may run outside the sandbox across the organization, automatically or after a prompt. * **Excluded deny** — `Exec(...)` rules for commands that must never run outside the sandbox. A team `deny` overrides any user-level `allow` or `ask` for matching commands, so users cannot exclude commands their admins have locked down. Team and user rules are resolved together: the most specific matching rule wins within each source, and the more restrictive verdict wins across sources (`deny` > `ask` > `allow`). **Example: lock down all exclusions except `gh`.** A wildcard `deny` with an `allow` carve-out keeps every command inside the sandbox except `gh`, regardless of what users configure locally. These values go into the team-settings excluded-commands configuration (not the user config file, so there is no enclosing `sandbox` key): ```json theme={null} { "excluded": { "deny": ["Exec(**)"], "allow": ["Exec(gh *)"] } } ``` Because the more specific `Exec(gh *)` rule beats the wildcard `Exec(**)`, `gh` commands run outside the sandbox while everything else stays inside — and the team-level wildcard `deny` overrides any user-level `allow` or `ask` rules for other commands. ## Further reading * [Team Settings](/cli/enterprise/team-settings#sandbox-enforcement) — enterprise sandbox enforcement and domain filtering * [Config file reference](/cli/reference/configuration/config-file#sandbox) — the user-level `sandbox` config section * [Permissions](/cli/reference/permissions) — permission scopes that drive sandbox writable paths and deny rules # Subagents Source: https://docs.devinenterprise.com/cli/subagents Delegate tasks to independent subagents that work in the foreground or background Subagents let the main agent spawn independent workers to handle subtasks. A subagent shares tools and codebase context with the parent, but operates in its own conversation chain -- it does not inherit the parent's conversation history. This is useful for tasks that benefit from focused, independent work -- like exploring a codebase, running tests, or implementing a feature in parallel. You can ask the agent to use subagents explicitly (e.g. "research how auth works in a subagent"), or the agent may decide to delegate on its own when it determines a task would benefit from independent work. In our measurements, **subagents** **both** **improve overall coding performance** **and** **reduce cost**. *** ## How Subagents Work When the agent spawns a subagent, it selects one of the available **subagent profiles** and chooses whether the subagent should run in the foreground or background. Subagents can run in two modes: Runs inline in your session. The parent agent pauses and waits for the subagent to finish before continuing. You can approve or deny tool calls as they come up. Runs in parallel while the parent agent continues working. The parent is automatically notified when the subagent completes. Unapproved tools are automatically denied. You do not see the subagent's raw output directly. When a subagent finishes, the parent agent reads the result and summarizes the key findings and actions for you. ### Subagent Cost Subagents run as their own agent sessions, each with its own context window and inference calls, so they consume cost independently of the parent. The parent's spend covers its own work; every subagent it spawns adds its own usage on top of that. On prompt-based plans, each subagent consumes additional credits, just like a user message does. The number of credits depends on the model the subagent uses, so tasks that spawn multiple subagents (or [nest](/cli/subagents#nesting-depth) them) consume more credits. Because cost scales with the number of subagents, tasks that fan out into many subagents (or [nest](#nesting-depth) them) cost more. Use subagents deliberately when the parallelism or focused context is worth the additional spend. *** ## Which Model Does a Subagent Use? Subagents do not all run on the model you picked in the model picker. Each profile decides where its model comes from: | Profile | Model used | Effect on quota / credits | | ------------------ | ------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- | | `subagent_explore` | The **default subagent model** — a fast, cheap model (SWE-1.6 by default) | Cheap: SWE-1.6 usage is billed at SWE rates, not at your primary model's rate | | `subagent_general` | **The same model as the parent agent** — whatever you selected in the model picker (e.g. Claude Opus, GPT-5) | Same rate as the parent: a general subagent costs like a full extra session on your selected model | | Custom subagents | The `model` field in the definition file if set, otherwise the **default subagent model** | Depends on the model you pin | `subagent_general` inherits the parent's model. If you are running a premium model, every general subagent runs on that premium model too, with its own context window and inference calls — so a task that fans out into several general subagents multiplies your spend. Ask for an explore subagent (or a [custom subagent](#custom-subagents) with a cheaper `model:` pinned) when the work is research rather than code changes. The **default subagent model** is not a fixed model name — it resolves through a router at spawn time, and an admin can override it (see below). With the default **Subagent router** setting it resolves to SWE-1.6 (a faster or slower SWE-1.6 variant depending on your plan tier). The CLI does not currently label which model a running subagent is using in the subagent panel. ### Influencing the Model There is no way to name a model for a subagent in a prompt — the `run_subagent` tool takes a *profile*, not a model. You have two levers: 1. **Ask for a profile in natural language.** Requesting an explore subagent ("research how auth works in an explore subagent") keeps the work on the cheap default subagent model. Asking for code changes gets you `subagent_general`, which runs on your selected model. 2. **Pin a model in a [custom subagent](#custom-subagents) profile.** `model:` in the definition file is the only way to run a *write-capable* subagent on a model other than the parent's. A [skill](/cli/extensibility/skills) that runs in a subagent can also set `model:` in its frontmatter to override the profile's model. ### Enterprise Controls Administrators can govern which model subagents use — and whether subagents run at all — through the **Default subagent model** setting in the org/enterprise settings. This setting controls the model for `subagent_explore` and for custom subagents that don't pin a `model:` — it does not change `subagent_general`, which always follows the parent agent's model. Default subagent model setting It has three choices: | Option | Behavior | | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | **Subagent router (default)** | The default subagent model is chosen by a router at spawn time. Today it resolves to SWE-1.6 (the exact variant depends on your plan tier). | | **A specific model** | Pins the default subagent model to the selected model, for every subagent that doesn't run on the parent's model. | | **None** | Disables subagents entirely — Devin will not spawn any subagents. | *** ## Enabling and Disabling Subagents Subagents are on by default. Set `subagents_enabled` to `false` in your [config file](/cli/reference/configuration/config-file#subagents_enabled) to remove the `run_subagent` and `read_subagent` tools so the agent does everything itself: ```json theme={null} // ~/.config/devin/config.json { "subagents_enabled": false } ``` The change applies live — a running session picks it up without restarting. In Devin Desktop, the same capability is the **Subagents (Preview)** toggle in settings. Organization policy wins: if an admin has set **Default subagent model** to **None**, subagents stay disabled no matter what this setting says. *** ## Subagent Profiles Each subagent runs with a specific profile that determines its capabilities. There are two built-in profiles: | Profile | Description | Tool Access | Model | | ------------------ | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | | `subagent_explore` | Read-only codebase exploration and research | Read-only codebase tools plus web search; cannot edit files or fetch arbitrary URLs (regardless of foreground or background) | Default subagent model (SWE-1.6 by default) | | `subagent_general` | General-purpose tasks including code changes | Full tool access (foreground) or pre-approved tools only (background) | Same model as the parent agent | The agent automatically chooses the appropriate profile based on the task. Explore subagents are ideal for research and understanding, while general subagents can make changes. See [Which Model Does a Subagent Use?](#which-model-does-a-subagent-use) for how each profile picks its model — the two profiles do **not** run on the same model. You can also define your own custom subagent profiles — see [Custom Subagents](#custom-subagents) below. *** ## Tool Permissions How tool permissions work depends on whether the subagent is running in the foreground or background: * **Foreground subagents** behave like the main agent -- you are prompted to approve or deny tool calls as usual. The prompt names the subagent that requested the action, so you know who is asking. * **Background subagents** inherit any tool permissions you have already granted during the current session. Any tool that has not been pre-approved is automatically denied. Background subagents cannot prompt you for new permissions. If a background subagent fails because a required tool was denied, you can resume it in the foreground to approve the necessary permissions. See [Resuming Subagents](#resuming-subagents) below. *** ## Monitoring Subagents ### Subagent Indicator When background subagents are running, an indicator appears below the input area showing their status. You can navigate to the indicator by pressing from the input area, then press Enter to open the subagent panel. When a foreground subagent is running, the spinner displays **"Subagent running · Ctrl+B to run in background"**. ### Subagent Panel The subagent panel lets you view and manage all active and completed subagents. It shows each subagent's profile, title, status, elapsed time, and tool call count. Subagent activity survives a session reload, so the panel still reflects your subagents after resuming. *** ## Foreground / Background Switching You can move subagents between foreground and background while they're running: * **Background a foreground subagent:** Press Ctrl+B while a foreground subagent is running. The subagent continues working in the background, and the parent agent resumes. * **Foreground a background subagent:** Open the subagent panel and press f on a running background subagent. The subagent's output will display inline. When you move a subagent to the background, the parent agent's tool call has already returned, so the parent continues independently. The subagent's result won't feed back into the parent's current pipeline, but you'll be notified when it completes. *** ## Interrupting a Turn Interrupting the agent does not kill its subagents. Running subagents **park** with their state intact and resume on your next message, so an interruption to redirect the parent agent doesn't throw away work in flight. *** ## Cancelling Subagents You can cancel a running subagent in two ways: 1. **From the subagent panel:** Open the panel and press x on a running subagent. 2. **Foreground subagent:** Press Ctrl+C or Esc to cancel the currently running foreground subagent. *** ## Resuming Subagents Cancelled, failed, or completed subagents can be resumed with a new prompt. You can ask the agent to resume a subagent, and it will continue where it left off. Resumed subagents always run in the **foreground**, so you can approve any tool calls that were previously denied. This is especially useful when: * A background subagent failed because a required tool was denied -- resume it in the foreground to grant the necessary permissions. * A subagent completed but you want it to do additional follow-up work based on its findings. * A subagent was cancelled prematurely and you want it to continue. *** ## Nesting Depth By default, subagents cannot spawn their own subagents — only the root agent can. Subagent tools (`run_subagent` and `read_subagent`) are disabled inside a subagent to prevent unbounded nesting. However, **custom subagent profiles** can opt in to nested spawning by setting the `max-nesting` field in their frontmatter. This value overrides the default maximum depth, allowing subagents to spawn children as long as the tree stays within that limit. For example, `max-nesting: 3` allows the following chain: ``` Root agent (depth 0) └── Custom subagent (depth 1) — can spawn children └── Child subagent (depth 2) — can spawn children └── Grandchild subagent (depth 3) — cannot spawn (depth limit reached) ``` Nested subagents can increase cost significantly. Each level of nesting spawns additional agents with their own context windows and inference calls. Use this feature deliberately. *** ## Custom Subagents Custom subagents are **experimental**. The format, behavior, and configuration options may change in future releases. Beyond the built-in `subagent_explore` and `subagent_general` profiles, you can define your own custom subagent profiles. Custom subagents let you create specialized workers with their own system prompts, tool restrictions, and model overrides — tailored to specific tasks in your workflow. This is also the way to get a write-capable subagent that does **not** run on your (possibly expensive) primary model: give it a `model:` and the tools it needs. ### Creating a Custom Subagent Custom subagents are defined as markdown files under `agents/`, using either layout: * **Flat file** — `agents/.md` (the same convention used by Claude Code, Cursor, and other tools). The file name (without `.md`) becomes the profile's identifier. * **Directory** — `agents//AGENT.md`. The directory name becomes the profile's identifier. `AGENTS.md`, `agent.md`, and `agents.md` are also accepted as the file name (if multiple are present, `AGENT.md` takes precedence, then `AGENTS.md`, `agent.md`, `agents.md`). In both layouts, a `name:` in the frontmatter overrides the identifier derived from the path. ```text theme={null} .devin/agents/ ├── reviewer.md └── researcher/ └── AGENT.md ``` Also supported: ```text theme={null} .agents/agents/ ├── reviewer.md └── researcher/ └── AGENT.md ``` ```text theme={null} # Linux/macOS ~/.config/devin/agents/ ├── reviewer.md └── researcher/ └── AGENT.md # Windows %APPDATA%\devin\agents\ ├── reviewer.md └── researcher\ └── AGENT.md ``` ### Definition File Format A subagent definition file uses the same YAML frontmatter as skills, followed by the subagent's system prompt: ```markdown theme={null} --- name: reviewer description: Reviews code changes for correctness and style model: sonnet allowed-tools: - read - grep - glob - exec --- You are a code review subagent. Your job is to review code changes thoroughly and report findings back to the parent agent. Focus on: 1. Correctness — logic errors, edge cases, off-by-one mistakes 2. Security — potential vulnerabilities 3. Style — consistency with the rest of the codebase 4. Performance — obvious inefficiencies Always cite specific file paths and line numbers in your findings. ``` ### Frontmatter Fields | Field | Type | Default | Description | | --------------- | ------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | | `name` | string | file or directory name | Identifier for the profile (must not conflict with built-in profiles) | | `description` | string | none | Shown to the agent when selecting a profile | | `model` | string | default subagent model (SWE-1.6 by default) — **not** the parent's model | Override the model used by this subagent | | `allowed-tools` | list | all tools | Restrict which tools the subagent can use. Cannot grant `ask_user_question`, which is always withheld from subagents. | | `max-nesting` | integer | none | Override the maximum nesting depth, allowing this subagent to spawn its own subagents | ### How Custom Subagents Are Used Once defined, custom subagent profiles appear alongside the built-in ones. The agent sees a description of each available profile and chooses the most appropriate one when spawning a subagent. You can also ask the agent to use a specific profile by name (e.g., "review this code using the reviewer subagent"). Custom subagent profiles that conflict with a built-in profile name (e.g., `subagent_explore`, `subagent_general`) are skipped with a warning. ### Importing From Other Tools Custom subagents are also imported from Claude Code's agent format: | Source | File Pattern | | --------------------- | ------------------------------------------ | | `.claude/agents/*.md` | Each `.md` file becomes a subagent profile | Claude Code agent files use `tools` instead of `allowed-tools` in their frontmatter. Both formats are supported automatically. ### Examples #### Read-Only Research Agent ```markdown theme={null} --- name: researcher description: Deep codebase research and architecture analysis model: sonnet allowed-tools: - read - grep - glob --- You are a research subagent specializing in codebase exploration. Your job is to thoroughly investigate a topic and report back with: - Relevant files and their purposes - Architecture patterns and dependencies - Code flow traces with specific line references Be exhaustive — search broadly and follow references. ``` #### Test Runner Agent ```markdown theme={null} --- name: test-runner description: Runs tests and reports results allowed-tools: - read - grep - glob - exec --- You are a test runner subagent. Run the relevant test suites and report: - Which tests passed and failed - Failure messages and stack traces - Suggestions for fixing failures ``` # Troubleshooting Source: https://docs.devinenterprise.com/cli/troubleshooting Common issues and how to fix them ## Installation Issues If the install script fails to download: 1. Check your internet connection 2. Verify curl is installed: `which curl` 3. Try with verbose output: `curl -fsSL -v https://cli.devin.ai/install.sh | bash` If you're behind a corporate proxy, you may need to configure proxy settings: ```bash theme={null} export https_proxy=http://your-proxy:port curl -fsSL https://cli.devin.ai/install.sh | bash ``` If the PowerShell install script fails: 1. Check your internet connection 2. Ensure you are running PowerShell as a regular user (not as Administrator unless necessary) 3. If you see an execution policy error, try: ```powershell theme={null} Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned irm https://static.devin.ai/cli/setup.ps1 | iex ``` 4. If you're behind a corporate proxy, configure proxy settings in PowerShell before running the install command As an alternative to the PowerShell script, you can download and run the standalone installer directly: * [x86\_64](https://static.devin.ai/cli/devin-updater-x86_64-pc-windows.exe) * [ARM64](https://static.devin.ai/cli/devin-updater-aarch64-pc-windows.exe) The installer needs write access to install the binary. If you see permission errors: 1. Check the install location has write permissions 2. Do not run the installer with `sudo` — this can cause ownership issues 3. If installing to a system directory, ensure your user has appropriate permissions If the install completes but `devin` isn't found: **macOS / Linux / WSL:** 1. Restart your terminal or run `source ~/.bashrc` (or `~/.zshrc`) 2. Check if the binary location is in your PATH: `echo $PATH` 3. Verify the binary exists: `ls -la ~/.local/bin/devin` (or the install location shown during setup) **Windows:** 1. Restart your PowerShell session 2. Check if the binary location is in your PATH: `$env:PATH -split ';'` 3. Verify the binary exists in the install location shown during setup `irm` and `iex` are PowerShell aliases. If you see this error, you're running the install command in Git Bash or CMD instead of PowerShell. **Fix:** Open **PowerShell** and run the install command there: ```powershell theme={null} irm https://static.devin.ai/cli/setup.ps1 | iex ``` Alternatively, from Git Bash or CMD you can invoke PowerShell explicitly: ```bash theme={null} powershell -Command "irm https://cli.devin.ai/install.ps1 | iex" ``` After installation, you can use Devin CLI from **PowerShell**, **Windows Terminal**, or **Git Bash**. *** ## Authentication Issues If browser-based login doesn't work: 1. Try the manual token flow for remote/SSH sessions: ```bash theme={null} devin auth login --force-manual-token-flow ``` 2. Check that your browser can reach the authentication URL 3. Verify your enterprise account has Devin CLI access enabled If you see authorization errors after logging in: 1. Verify your account has the correct permission needed to access Devin CLI. You may need to ask your admin. For enterprises, see [Devin Auth](/cli/enterprise/devin-auth#configuring-access) or [Legacy Windsurf Auth](/cli/enterprise/windsurf-auth#prerequisites) on how to configure access. 2. Try logging out and back in: `devin auth logout && devin auth login` 3. Check your authentication status: `devin auth status` Devin CLI API tokens do not expire by default. If a stored token has been revoked or is no longer accepted, remove it before logging in again: ```bash theme={null} devin auth logout && devin auth login ``` to replace your stored credentials. *** ## Network & Proxy Issues The CLI routes its own outbound HTTPS traffic (authentication, updates, model API calls, MCP servers) through a proxy when one is configured. There are two ways to set it: **Environment variables** — the default `system` proxy mode respects these: ```bash theme={null} export HTTPS_PROXY=http://proxy.corp.example.com:8080 export HTTP_PROXY=http://proxy.corp.example.com:8080 export ALL_PROXY=socks5://proxy.corp.example.com:1080 # optional, SOCKS5 export NO_PROXY=localhost,127.0.0.1,.internal.corp # hosts to bypass ``` **`config.json`** — applies regardless of environment: ```json theme={null} { "proxy": { "mode": "manual", "url": "http://proxy.corp.example.com:8080", "no_proxy": "localhost,127.0.0.1,.internal.corp" } } ``` See the [`proxy` configuration reference](/cli/reference/configuration/config-file#proxy) for all options. On macOS and Windows, `system` mode also honors platform-native PAC (Proxy Auto-Configuration) settings. If your proxy performs TLS inspection, the CLI uses your operating system's certificate store, so install the proxy's root CA at the OS level (Keychain on macOS, the Windows certificate store, or your distribution's CA bundle on Linux). To get full visibility into the request lifecycle (DNS, connection pooling, TLS handshake, headers, redirects, and retries), raise the log level with `RUST_LOG` and mirror logs to your terminal with `CHISEL_LOG_STDOUT`: ```bash theme={null} RUST_LOG="chisel=trace,windsurf_api_client=trace,connect_rpc=trace,reqwest=trace,hyper=trace,hyper_util=trace,rustls=trace" \ CHISEL_LOG_STDOUT=1 \ devin auth login ``` What each target adds: * `chisel`, `windsurf_api_client`, `connect_rpc` — the CLI's own request and authentication logging * `reqwest=trace` — high-level request/response and redirect handling * `hyper=trace` / `hyper_util=trace` — connection establishment, pooling, and HTTP/1.1 & HTTP/2 framing * `rustls=trace` — TLS handshake details (useful for proxy and certificate problems) Use `CHISEL_LOG_STDERR=1` instead of `CHISEL_LOG_STDOUT=1` if you don't want logs interleaved with command output. (Stdout logging is suppressed automatically in the interactive REPL and ACP mode to avoid corrupting their output.) Logs are also always written to a per-run log file under the CLI's data directory, regardless of these env vars: * **macOS / Linux:** `~/.local/share/devin/cli/logs/devin__.log` * **Windows:** `%APPDATA%\devin\cli\logs\devin__.log` Log files from finished processes that have been untouched for 48 hours are gzipped at startup to keep the directory small, so older logs are `.log.gz`. Search them with `zgrep` (or `rg -z`) and read them with `zless`: ```bash theme={null} zgrep "error" ~/.local/share/devin/cli/logs/*.log.gz rg -z "error" ~/.local/share/devin/cli/logs/ ``` Trace-level logs can include sensitive data such as `Authorization` headers and tokens. Scrub log output before sharing it. `RUST_LOG` exposes the request lifecycle but not full payloads. To capture complete request and response bodies, route the CLI through an intercepting proxy such as [mitmproxy](https://mitmproxy.org/): ```bash theme={null} # Terminal 1 — start the intercepting proxy: mitmproxy --listen-port 8080 # Terminal 2 — point the CLI at it: export HTTPS_PROXY=http://127.0.0.1:8080 devin auth login ``` Because the CLI trusts the OS certificate store, install mitmproxy's CA certificate (`~/.mitmproxy/mitmproxy-ca-cert.pem`) into your system trust store first — otherwise the TLS connection to the proxy will fail. *** ## Runtime Issues If you see errors about a model not being available: 1. Check if your enterprise restricts available models in [Team Settings](/cli/enterprise/team-settings) 2. Verify the model name is correct — use `/model` to see available options 3. Try a different model: `devin --model sonnet -- your prompt` If you hit usage limits: 1. Wait a few minutes before retrying 2. Check your organization's usage dashboard for quota status 3. Contact your admin if you need higher limits Commands the agent runs inherit your login shell's environment on macOS and Linux, so tools installed through `nvm`, `pyenv`, `rbenv`, `direnv`, or `mise` are normally available. If the agent reports "command not found" for something that works in your terminal: 1. Confirm the tool is on the `PATH` exported by your shell profile, not only by an interactive-only alias or function 2. Restart Devin — the environment is snapshotted once at session startup, so profile changes made mid-session are not picked up 3. On Windows, the login-shell snapshot does not apply; make sure the tool is on the system `PATH` At session startup, Devin runs `$SHELL` as an interactive login shell once and reads exported variables from your shell configuration, such as `.bash_profile`, `.bashrc`, `.zshrc`, `.zprofile`, or your fish config. If the agent stops responding: 1. Press `Ctrl+C` to interrupt the current operation 2. Try `/clear` to start a fresh session 3. Check your network connection 4. Restart Devin CLI *** ## MCP Server Issues If an MCP server fails to start: 1. Verify the command works outside Devin CLI: ```bash theme={null} npx -y @modelcontextprotocol/server-github ``` 2. Check that all required environment variables are set 3. Look for error messages in the server output If MCP tools don't show up: 1. The server may need a moment to initialize — wait a few seconds 2. Check that the server is configured correctly in your config file 3. Verify your enterprise allows MCP servers in [Team Settings](/cli/enterprise/team-settings) MCP tools default to prompting for approval. To auto-approve specific tools, add them to your permissions config: ```json theme={null} { "permissions": { "allow": ["mcp__github__list_issues"] } } ``` *** ## Getting Help If you're still experiencing issues: * **Email support:** [support@cognition.ai](mailto:support@cognition.ai) * **Submit a bug report:** Use the `/bug` command inside Devin CLI to report issues directly to the Devin CLI developers * **Check for updates:** Run `devin update` to ensure you're on the latest version # Devin Outposts orchestration guide Source: https://docs.devinenterprise.com/cloud/outposts/orchestration Build a Devin Outposts orchestrator for your own infrastructure: watch the queue, claim sessions, provision machines, and run workers automatically. An orchestrator watches the outposts API for sessions waiting on an outpost, provisions a VM or container for each one, and starts the worker inside it. This page describes the orchestration loop: polling the queue, claiming sessions, running workers, and tearing machines down. If you just want to serve sessions from a machine you already have, start with the [quickstart](/cloud/outposts/quickstart) — no orchestrator is required. If you run on a supported platform, an [integration](/cloud/outposts/overview#integrations) may already implement this loop for you. For the full API and CLI surface, see the [reference](/cloud/outposts/reference). Running on Kubernetes? [devin-outpost-k8s](https://github.com/CognitionAI/devin-outpost-k8s) is an open-source operator that implements this loop for you: it watches the queue, claims pending sessions, and runs each one as a worker pod on any certified cluster (GKE, EKS, ...). Install it with its Helm chart instead of building your own orchestrator. ## The core flow ### 1. Register an outpost An outpost is a named queue of sessions served by many workers on your infrastructure (for example, `rhel`, `gpu-h200`, or `my-outpost`). Create one with `devin worker outpost create`: ```bash theme={null} devin worker outpost create --platform --description "..." ``` Once registered, the outpost appears as a machine option in Devin Cloud (alongside Ubuntu, Windows, etc.) when starting a session. Sessions targeting it wait in its queue until a worker claims them. In the fleet API, outposts are represented as `outposts` resources, scoped to your account (shared across all of its organizations). See the [outposts endpoints](/cloud/outposts/reference#outposts). ### 2. Watch the fleet API for waiting sessions Your orchestrator lists pending sessions for the outposts it serves: ```bash theme={null} curl -H "Authorization: Bearer $DEVIN_API_TOKEN" \ "https://api.devin.ai/opbeta/outposts/devins?outpost=&phase=pending" ``` Then it keeps its view current with a Server-Sent Events (SSE) watch, resuming from the list's final cursor: ```bash theme={null} curl -N -H "Authorization: Bearer $DEVIN_API_TOKEN" \ "https://api.devin.ai/opbeta/outposts/devins?outpost=&watch=true&cursor=" ``` This is the standard Kubernetes-style list-then-watch pattern: page through the list with the response cursor, then start a watch from where the list left off, persisting each event's cursor so you can reconnect without missing changes. Delivery is at-least-once, so upsert by `metadata.session_id` and tolerate duplicates. See [List queued sessions](/cloud/outposts/reference#list-queued-sessions) and [Watch for changes](/cloud/outposts/reference#watch-for-changes) for query parameters, response shapes, and full pagination semantics. ### 3. Claim before provisioning Before starting a machine for a session, atomically claim it so no other worker picks it up. Pass an `acceptor_id` — a self-reported identity for your worker: ```bash theme={null} curl -X POST -H "Authorization: Bearer $DEVIN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"acceptor_id": "worker-1"}' \ "https://api.devin.ai/opbeta/outposts/devins/{session_id}/claim" ``` Claims are atomic: if another worker claimed the session first, you get a `409`. Claiming promises that a worker will be ready within the server-assigned claim deadline (`status.claim_deadline`); expired claims return to the queue automatically. If provisioning fails, [release the claim](/cloud/outposts/reference#release-a-claim) so the session returns to the queue immediately. ### 4. Spawn a machine and run the worker For each claimed session, provision a VM or container from your image. Inside it, run the worker from the directory you want the session to work in — its repositories live in that directory's `repos` subdirectory, i.e. `$(pwd)/repos/`: ```bash theme={null} cd /path/to/worker/directory devin worker start --session= --outpost= --acceptor-id= ``` Pass the same `--acceptor-id` you used for the API claim, and provide the token via `--token` or `DEVIN_OUTPOSTS_TOKEN` (see the [full flag list](/cloud/outposts/reference#devin-worker-start)). The worker connects out to Devin's cloud, marks the session ready, and begins executing tool calls. ### 5. Terminate the machine when the worker exits When `devin worker start` exits, the session is over (or has been suspended). Terminate the VM or container. If your outpost is resumable, snapshot the machine before terminating so you can restore it if the session resumes. Your orchestrator can track its claimed sessions and their states: ```bash theme={null} curl -H "Authorization: Bearer $DEVIN_API_TOKEN" \ "https://api.devin.ai/opbeta/outposts/devins?phase=claimed&acceptor_id=worker-1" ``` Each entry reports a `status.session_status` of `pending`, `running`, `suspended`, or `terminated`. ## Centralization-free scheduling Planning to run more than \~16 coordinators (workers or orchestrators watching and claiming from an outpost)? Contact your account team first — larger fleets amplify claim contention and queue read load, and we want to make sure the outpost is provisioned for it. You don't need a central scheduler to run a fleet. The queue API is designed so that many independent workers can serve the same outpost without talking to each other: * **Claims are the only coordination primitive.** Every worker independently watches the queue and races to claim pending sessions. The claim is an atomic compare-and-swap on the server: exactly one worker wins, and every loser gets a `409` and simply moves on to the next pending session. Losing a claim race is normal operation, not an error. * **Each worker has its own identity.** The `acceptor_id` scopes a worker's claims, renewals, and restart recovery to that worker alone. `devin worker start` generates and persists one automatically per machine, so a fleet needs no identity configuration. Never share an acceptor ID (or a copied worker data directory) across machines — colliding workers will steal each other's claims. * **Failures self-heal.** If a worker dies after claiming, its claim expires at the claim deadline and the session returns to the queue for another worker to pick up. No fleet-level health tracking is required. This means scaling out is just running the worker on more machines pointed at the same outpost: N machines serve N concurrent sessions, and the rest wait as pending. ## Building a custom orchestrator Everything `devin worker start` does is available directly through the fleet API, so you can replace the CLI entirely: fetch the `devin-remote` binary from Devin's static distribution and launch it yourself with the documented environment. See [Remote binary distribution](/cloud/outposts/reference#remote-binary-distribution) and the [spawn contract](/cloud/outposts/reference#spawn-contract) in the reference. # Devin Outposts: self-hosted infrastructure Source: https://docs.devinenterprise.com/cloud/outposts/overview Learn how Devin Outposts runs sessions on your own infrastructure, including self-hosted workers, networking, machine setup, and partner integrations. Outposts lets you run Devin sessions inside infrastructure you control — your own VMs, containers, Kubernetes clusters, or even a Mac Mini on your desk. Devin's agent loop (inference and planning) continues to run in Devin's cloud, while all command execution, file edits, and repository access happen on machines you operate. Use Outposts when you need: * Sessions to run inside your network, next to internal services, registries, and secrets * Custom hardware profiles (e.g. GPUs, large memory machines, specific OS images) * Existing dev box, VM, or Kubernetes infrastructure to host Devin workloads * Enterprise controls over network access, build outputs, and monitoring Devin's agent loop and the outpost queue run in Devin Cloud; your machines — a GPU box in your lab, a VM in your VPC, or a Mac mini on your desk — serve sessions over an outbound-only connection ## How it works An **outpost** is a named queue of Devin sessions to be served on your own machines. Once you register an outpost (e.g. `gpu-h200` or `dev-boxes`), it appears as a machine option in Devin Cloud alongside Ubuntu, Windows, etc. — Cloud sessions started on an outpost wait in its queue until one of your machines picks them up. Every machine that serves sessions from an outpost is a **worker**. To turn a machine into a worker, install the [Devin CLI](/work-with-devin/devin-cli) and run: ```bash theme={null} devin worker start --outpost= ``` The worker opens an outbound connection to Devin's cloud and watches the outpost's queue. When a session is waiting, the worker claims it and executes its tool calls locally — every command, file edit, and repository operation runs on your machine. When the session ends, the worker goes back to watching the queue for the next session. Scaling out is just running the worker on more machines: N workers serve N concurrent sessions, and any further sessions wait in the queue until a worker becomes available. Workers only need **outbound** HTTPS access. No inbound ports, public IPs, or VPN tunnels are required. ### Orchestration Long-lived worker machines are the simplest setup, but with the Outposts API you can also write an **orchestrator**: software that watches the outpost's queue and, for each waiting session, spins up a fresh VM or container, starts the worker inside it, and tears the machine down when the session ends. See [Orchestration](/cloud/outposts/orchestration) to learn how, deploy [devin-outpost-k8s](https://github.com/CognitionAI/devin-outpost-k8s) — our open-source operator that runs the loop on any Kubernetes cluster — or run on a partner platform that already implements it for you (see [Integrations](#integrations)). ## Machine dependencies Sessions execute directly on your machines, so the worker relies on tools you install there. | Dependency | Required | Used for | | --------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `git` (on `PATH`) | Yes | Cloning and all repository operations | | `ffmpeg` (on `PATH`) | No | Devin's screen-recording features. Without it, sessions cannot record the screen. | | Chrome or Chromium | No | Browser and computer-use features. The worker looks for Chrome in standard install locations by default; set `DEVIN_CHROME_PATH` in the worker's environment to the absolute path of the binary to override (e.g. `DEVIN_CHROME_PATH=/usr/bin/google-chrome`). Without it, browser tools are unavailable. | | Graphical desktop / display | No | [Computer Use](/work-with-devin/computer-use#computer-use-on-outposts) (mouse, keyboard, screenshots). Linux machines need a running X session (`DISPLAY` set for the worker, e.g. Xvfb); macOS machines use the existing desktop session and need the **Screen Recording** (screenshots) and **Accessibility** (input) permissions granted to the worker. Without a display, computer actions return a clear error. | | Passwordless `sudo` | No | Lets Devin install software it needs during a session (e.g. missing build tools or system packages). Only grant this when the machine is dedicated to Devin and recycled after each session — never on shared or long-lived machines. | ## Get started Create an outpost and serve sessions from a single machine with `devin worker start` — no orchestrator required. Scale to a fleet: poll the queue, claim sessions, provision machines, and run workers automatically. The full surface area: CLI commands and flags, fleet API endpoints, binary distribution, and the spawn contract. ## Integrations Partner platforms implement the orchestration loop for you — sessions run on their infrastructure with no worker to run and no orchestrator to build. Each partner documents its own setup: | Platform | What you get | Docs | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- | | Namespace | First-class macOS environments on Apple silicon — with computer use, Devin builds, runs, and tests iOS apps end to end | [Devin Outposts on Namespace](https://namespace.so/docs/devbox/devin) | | Modal | The same infrastructure you train and serve models on — reproduce failures and profile fixes on production hardware, scaling back to zero | [Devin Outposts on Modal](https://modal.com/docs/devin) | | OpenShell | A sandbox for every session via the OpenShell runtime — from a single VM to a GPU cluster, built for secure and government environments | [Devin Outposts on NVIDIA OpenShell](https://github.com/NVIDIA/OpenShell#supported-agents) | | Brev | GPU instances on NVIDIA Brev, deployed as a one-click Launchable | [Devin Outposts on NVIDIA Brev](https://brev.nvidia.com/launchable/deploy?launchableID=env-3Ge1ZXazlZQuJHfQed2od9IT8R5) | | Daytona | Linux and Windows sandboxes that start in under 90 ms from snapshots — repos, dependencies, and toolchains already in place | [Devin Outposts on Daytona](https://www.daytona.io/docs/en/guides/devin/devin-outposts/) | | E2B | Agent machines at any CPU/RAM configuration with sub-second starts — including access to your private cloud | [Devin Outposts on E2B](https://e2b.dev/docs/agents/devin-outposts) | | Cloudflare | An isolated sandbox per session, with traffic flowing through customizable proxies and private connectivity to internal services — no VPN or public exposure | [Devin Outposts on Cloudflare](https://developers.cloudflare.com/sandbox/tutorials/devin-outposts/) | ## Limitations * Devin Outposts is available on all Pro, Max, and Teams accounts. * Devin Outposts is also available on [Dedicated Tenant deployments](/enterprise/deployment/overview) but is off by default, since a few Devin features behave differently when agents run on customer-managed infrastructure. Your account team can go over the details and enable it. * Outposts shifts significant infrastructure and operational responsibility to the customer. Teams must secure and operate their remote development VMs at scale, including provisioning, isolation, access controls, capacity management, monitoring, and recovery. For security-conscious customers, we recommend [Dedicated Tenant (Dedicated SaaS)](/enterprise/deployment/overview), which provides a customer-isolated environment with security and orchestration managed by Cognition. # Devin Outposts partner integrations Source: https://docs.devinenterprise.com/cloud/outposts/partners Connect Devin Outposts to your own infrastructure through a partner integration using PKCE, admin authorization, and secure server-to-server tokens. Rough notes — this flow is in early development and the details below may change. Partner platforms (e.g. compute providers) can connect an outpost on behalf of a customer. The customer's Devin admin authorizes the connection in the browser; Devin then creates an outpost and a service user and hands the partner a token to run workers against the outpost. The flow is an OAuth-light authorization-code exchange with [PKCE](https://datatracker.ietf.org/doc/html/rfc7636). The browser only ever carries a short-lived, single-use **code** — the service-user token is exchanged server-to-server and never transits the browser. ## Prerequisites * **Callback allowlist.** Every `callback_url` you use must be on Devin's allowlist for your integration. This is configured by Cognition — send us the exact URLs ahead of time. A URL that is not on the list is rejected. * **Outposts enabled.** The customer's account must have Outposts enabled. * **Admin authorization.** Authorizing a connection requires a Devin admin with both enterprise-settings and service-user management rights. The partner never needs a Devin token — the admin authorizes it in their own browser session. ## Flow overview ``` Partner backend Admin's browser Devin │ │ │ │ 1. gen code_verifier, │ │ │ derive code_challenge │ │ │ 2. redirect to app.devin.ai/outposts/connect?…code_challenge│ │───────────────────────────────> │ │ │ 3. admin confirms, "Connect"│ │ │──────confirm connection──────> │ │ 4. redirect callback_url?code=… │ │<─────────────────────────────── │ │ 5. POST /outposts/connection-token (code + code_verifier) │ │────────────────────────────────────────────────────────────> │ 6. { access_token, api_base_url, … } │ │<──────────────────────────────────────────────────────────── │ 7. run outpost workers with access_token │ ``` ### 1. Generate a PKCE verifier and challenge On your backend, per connection attempt: * Generate a high-entropy, random **`code_verifier`**: 43–128 characters from the unreserved alphabet `[A-Za-z0-9-._~]` (e.g. `base64url(random 32 bytes)` with padding stripped). * Derive the **`code_challenge`** as the unpadded base64url of the SHA-256 of the verifier (PKCE "S256"): ```python theme={null} import base64, hashlib, secrets code_verifier = secrets.token_urlsafe(32) # 43+ chars, unreserved alphabet code_challenge = ( base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode()).digest()) .rstrip(b"=") .decode() ) ``` Store the `code_verifier` server-side (keyed to whatever state you use to correlate the eventual callback). Never send the verifier to the browser — only the challenge leaves your backend. ### 2. Redirect the admin to the connect page Send the customer's admin to Devin's connect page with the challenge and your callback: ``` https://app.devin.ai/outposts/connect ?callback_url=https://partner.example.com/devin/outpost-callback &outpost_name=my-outpost &outpost_image=https://partner.example.com/logo.png &platform=linux &code_challenge= ``` | Param | Required | Notes | | ---------------- | -------- | -------------------------------------------------------------------------------------- | | `callback_url` | yes | Where Devin relays the one-time code. Must be on your allowlist. | | `code_challenge` | yes | The PKCE S256 challenge from step 1. | | `outpost_name` | no | Suggested outpost name. The admin can edit it before confirming. | | `outpost_image` | no | URL of a PNG icon used to represent the outpost, such as your company logo. | | `platform` | no | Preselected outpost platform: `macos`, `linux`, or `windows`. The admin can change it. | If the admin isn't signed in, the connect page stashes these params and prompts them to sign in first, then resumes. ### 3. Admin confirms The connect page shows a confirmation with an editable outpost name and platform (and your `outpost_image` if provided). When the admin clicks **Connect**, Devin validates permissions, the callback allowlist, and that the outpost name is free, stores an encrypted, single-use code (10-minute TTL), and redirects back to your app with the one-time code. No outpost or service user exists yet — they are created only when the code is redeemed (step 5). An unredeemed code simply expires. ### 4. Devin redirects the code to your callback The browser is redirected to your `callback_url` with the code appended: ``` https://partner.example.com/devin/outpost-callback?code= ``` ### 5. Exchange the code server-to-server From your backend, look up the `code_verifier` you stored in step 1 and redeem the code at the token endpoint. This is a form-encoded, OAuth-style token request: ```bash theme={null} curl -X POST "https://api.devin.ai/outposts/connection-token" \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-urlencode "grant_type=authorization_code" \ --data-urlencode "code=" \ --data-urlencode "code_verifier=" ``` This endpoint needs no Devin auth — possession of the code plus the matching PKCE verifier is the proof. It is unauthenticated on purpose: the code is single-use (atomically consumed), short-lived, and bound to your challenge. ### 6. Receive the credentials On success Devin creates the outpost and a service user scoped to run the outpost worker, and returns: ```json theme={null} { "outpost_id": "...", "account_id": "...", "outpost_name": "my-outpost", "service_user_id": "...", "api_base_url": "https://api.devin.ai", "access_token": "cog_...", "token_type": "bearer" } ``` Responses carry `Cache-Control: no-store` — do not cache them. ### 7. Run outpost workers Store `access_token` and `api_base_url` securely and use the token as a bearer credential to run outpost workers against the outpost. ## Error handling The token endpoint follows [RFC 6749 §5.2](https://datatracker.ietf.org/doc/html/rfc6749#section-5.2). An unknown, expired, already-redeemed (replayed), or PKCE-mismatched code returns `400`: ```json theme={null} { "error": "invalid_grant", "error_description": "Invalid or expired connection code" } ``` Because codes are single-use and expire after 10 minutes, treat any `invalid_grant` as terminal: discard the stored `code_verifier` and restart the flow from step 1. ## Security notes * **The token never touches the browser.** Only the single-use code is relayed via redirect; the service-user token is returned solely from the server-to-server exchange. * **PKCE binds the code to you.** The code is useless without the `code_verifier` held only on your backend, so intercepting the redirect (or the code) is not enough to redeem it. * **Codes are single-use and short-lived.** Redemption atomically consumes the code; it also expires after 10 minutes. * **Callback URLs are allowlisted.** Devin only relays a code to a `callback_url` Cognition has pre-approved for your integration. * **Verify the code is for the requesting user.** Confirm that the code returned to your callback belongs to the same user who originally requested the connection. This prevents an attacker from tricking a user into unsuspectingly binding Devin to a sandbox the attacker controls. * **Keep `outpost_name` sensible.** The admin may override it; the name you pass is only a suggestion. # Devin Outposts quickstart Source: https://docs.devinenterprise.com/cloud/outposts/quickstart Set up Devin Outposts on your own machines with a self-hosted worker, API token, and repository access to run sessions from one machine. * An organization with Outposts enabled * A [v3 API token](/api-reference/v3/overview) with the appropriate Outposts scopes: * `account.outposts.write` ("Outposts write") for workers claiming/releasing sessions and orchestrators creating/deleting outposts (implies the read scope) * `account.outposts.read` ("Outposts read") for listing outposts and reading the session queue * A machine (VM or container) with: * The Devin CLI installed * The [machine dependencies](/cloud/outposts/overview#machine-dependencies) * Your repositories cloned, with configured remotes * Access to the build tools, package registries, secrets, and internal services your sessions need Sessions execute directly on the machine with your user's permissions. We recommend running the worker under a dedicated directory you're comfortable letting an agent work in freely — or better yet, on a machine reserved for long-running agentic work, like a Mac Mini on your desk. Download and install the [Devin CLI](/cli): ```bash theme={null} curl -fsSL https://cli.devin.ai/install.sh | bash ``` On [Devin Cloud](https://app.devin.ai) go to Settings → Environment → Outposts, and click on the "Create Outpost" button. Navigate to a directory where you want your worker to run: ```bash theme={null} cd /path/to/worker/directory ``` Sessions get their repositories under a `repos` subdirectory of that directory — a session working on `your-org/app` uses `/path/to/worker/directory/repos/app`. Clone repositories there ahead of time to skip the clone at session start; anything missing is cloned on demand. And run the `devin worker start` command with your Outpost's name and token you copied earlier: ```bash theme={null} devin worker start --outpost= --token= ``` On [Devin Cloud](https://app.devin.ai), start a new session and configure it to run on your Outpost. Under "Configuration" → "Virtual environment", you will see your new Outpost listed. Select it to run your session on it. ### Next steps Start the worker in a directory where your code lives and ask Devin to build on top of it. Sessions see the repositories checked out under `repos/` in the worker's working directory. To serve more sessions concurrently, run the worker on more machines pointed at the same outpost: N workers serve N concurrent sessions, and the rest wait in the queue. Provision machines automatically as sessions queue, instead of keeping long-lived workers around. Run your outpost on the platform you already use — Namespace, Modal, E2B, and more. On [Devin Cloud](https://app.devin.ai) go to Settings → Environment → Outposts, and click on the "Create Outpost" button. Build on the official Devin CLI image (`public.ecr.aws/e0h8a4b6/devin-cli`), adding the [machine dependencies](/cloud/outposts/overview#machine-dependencies) and any repositories or tools your sessions need: ```dockerfile Dockerfile theme={null} # The Devin CLI is preinstalled and is the image's entrypoint. # Use :stable, or pin a specific CLI version tag. FROM public.ecr.aws/e0h8a4b6/devin-cli:stable # git is required; ffmpeg unlocks screen-recording features RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates git ffmpeg \ && rm -rf /var/lib/apt/lists/* # The directory the worker runs in. Sessions get their repositories under # its `repos` subdirectory, e.g. /workspace/repos/app. WORKDIR /workspace # Optionally, pre-clone the repositories your sessions need so they don't # have to be cloned at session start: # RUN git clone https://github.com/your-org/app.git repos/app \ # && git clone https://github.com/your-org/infra.git repos/infra CMD ["worker", "start"] ``` Or tell Devin to make a Dockerfile for you: ``` Write a Dockerfile for a Devin Outposts worker image. Base it on public.ecr.aws/e0h8a4b6/devin-cli:stable, which has the Devin CLI preinstalled as the image's entrypoint. Install git and ffmpeg. Clone these repositories into the `repos` subdirectory of the working directory the worker runs in: . The default command should be ["worker", "start"]. ``` Browser features need Chrome or Chromium in the image, with `DEVIN_CHROME_PATH` pointing at the binary. The base image is Ubuntu, and Ubuntu's `chromium` apt package is a snap stub that does not work in containers — for amd64 images, install Google Chrome instead: ```dockerfile theme={null} RUN apt-get update && apt-get install -y --no-install-recommends curl \ && curl -fsSL https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -o /tmp/chrome.deb \ && apt-get install -y --no-install-recommends /tmp/chrome.deb \ && rm /tmp/chrome.deb && rm -rf /var/lib/apt/lists/* ENV DEVIN_CHROME_PATH=/usr/bin/google-chrome ``` For private repositories, bake in credentials with your preferred mechanism (e.g. [build secrets](https://docs.docker.com/build/building/secrets/)) so the clones and remotes work at runtime. When you're happy with your Dockerfile, build the image: ```bash theme={null} docker build -t devin-worker . ``` Run a container from your image with the `worker start` command, passing your Outpost's name and the token you copied earlier (the image's entrypoint is the Devin CLI, so arguments go straight to `devin`): ```bash theme={null} docker run devin-worker \ worker start --outpost= --token= ``` On [Devin Cloud](https://app.devin.ai), start a new session and configure it to run on your Outpost. Under "Configuration" → "Virtual environment", you will see your new Outpost listed. Select it to run your session on it. ### Next steps Bake the repositories you want Devin to work on into the image and ask Devin to build on top of them — sessions see the repositories checked out under `repos/` in the worker's working directory. To serve more sessions concurrently, run more containers pointed at the same outpost: N workers serve N concurrent sessions, and the rest wait in the queue. Provision containers automatically as sessions queue, instead of keeping long-lived workers around. Run your outpost on the platform you already use — Namespace, Modal, E2B, and more. # Devin Outposts API and CLI reference Source: https://docs.devinenterprise.com/cloud/outposts/reference Use the Devin Outposts reference for self-hosted workers: devin-remote, fleet API endpoints, CLI flags, binary downloads, and the spawn contract. Complete reference for the Outposts surface area: the worker CLI, the fleet API, the `devin-remote` binary distribution, and the spawn contract for custom orchestrators. ## Authentication Workers and orchestrators authenticate with a [v3 API token](/api-reference/v3/overview) belonging to a service user. The role assigned to the service user grants the token its Outposts scopes: | Role permission | Token scope | Grants | | ------------------------------------ | ------------------------ | ----------------------------------------------------------------------------------- | | **Outposts read** (`ReadOutposts`) | `account.outposts.read` | Listing outposts and reading the session queue | | **Outposts write** (`WriteOutposts`) | `account.outposts.write` | Claiming/releasing sessions and creating/deleting outposts (implies the read scope) | The older `account.outposts.machine` and `account.outposts.orchestrator` scopes are deprecated. Roles that were granted them still work (both imply the write scope), but new roles should use **Outposts read** / **Outposts write**. Outposts are scoped to your **account** and shared across all of its organizations. `devin worker start` can also run without a pre-provisioned token by using your existing CLI login — see [Starting without a token](#starting-without-a-token). ## CLI ### `devin worker start` Polls an outpost's queue, claims sessions, downloads the correct `devin-remote` binary, and serves sessions. Run it from the directory you want sessions to work in: a session's repositories live under that directory's `repos` subdirectory, so `your-org/app` is checked out at `$(pwd)/repos/app`. Repositories already present there are reused; missing ones are cloned at session start. ```bash theme={null} devin worker start --outpost= ``` | Flag | Environment variable | Description | | ---------------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `--outpost` | — | Only claim sessions from this outpost, given as its name or its id. If omitted in an interactive terminal, the worker prompts you to pick from your account's outposts. | | `--session` (alias `--session-id`) | — | Claim and serve one specific session, then exit. | | `--acceptor-id` | `DEVIN_WORKER_ACCEPTOR_ID` | Stable worker identity used for claims, renewals, and restart recovery. Defaults to a generated ID persisted under the worker data directory. Never share one across machines. | | `--token` | `DEVIN_OUTPOSTS_TOKEN` | Auth token for the worker. Optional — if both are unset, the worker falls back to your CLI login (see [Starting without a token](#starting-without-a-token)). | | `--once` | — | Exit after serving one session instead of returning to the queue. | | `--api-url` | `DEVIN_API_URL` | Devin API base URL. Defaults to `https://api.devin.ai`. | | `--cache-dir` | `DEVIN_WORKER_CACHE_DIR` | Directory where downloaded `devin-remote` binaries are cached. Defaults to `~/.devin/worker/cache`. | | `--static-base-url` | `DEVIN_WORKER_STATIC_BASE_URL` | Base URL `devin-remote` binaries are published to. | | `--gateway-url` | `DEVIN_OUTPOST_GATEWAY_URL` | Outpost gateway URL fallback when the claim response does not carry one. | | `--remote-binary-sha` | `DEVIN_WORKER_REMOTE_SHA` | Fallback `devin-remote` git SHA when the session does not pin one. When neither is set, the latest published SHA is used. | | `--pty-bridge-port` | `DEVIN_PTY_BRIDGE_PORT` | Fixed PTY bridge port. Defaults to a free port allocated per session. | | `--poll-interval-secs` | — | Seconds between queue polls and session status checks. Defaults to `5`. | The worker's environment can also carry `DEVIN_CHROME_PATH` to point sessions at a Chrome/Chromium binary for browser features. #### Starting without a token A pre-provisioned outposts token is not required. With no `--token` and no `DEVIN_OUTPOSTS_TOKEN`, `devin worker start` creates an outpost using your existing CLI login and reuses the saved worker token on later runs. #### Platform validation The worker checks that the machine's OS matches the outpost's platform and fails with a clear message on a mismatch, rather than repeatedly claiming and releasing queued sessions. Windows x64 machines are supported: the worker downloads the correct `devin-remote` binary and passes the Windows system environment through to sessions. ### `devin worker outpost create` Creates an outpost — a named queue of sessions served by your infrastructure. Requires the write scope. ```bash theme={null} devin worker outpost create --platform --description "..." ``` | Argument / flag | Description | | --------------- | ----------------------------------------------------------- | | `` | Unique (per account) outpost name, e.g. `rhel`, `gpu-h200`. | | `--platform` | Machine platform: `linux`, `macos`, or `windows`. | | `--description` | Human-readable description shown in the web app. | Prints the new outpost's ID (`outpost_env-...`). You can also create outposts in the web app under **Settings → Environment → Outposts**. ### `devin worker outpost delete` Deletes an outpost. Requires the write scope. ```bash theme={null} devin worker outpost delete ``` ## Fleet API All endpoints live under `https://api.devin.ai/opbeta/outposts/` and take a bearer token: ```bash theme={null} curl -H "Authorization: Bearer $DEVIN_API_TOKEN" ... ``` Resources follow a Kubernetes-style `metadata` / `spec` / `status` shape, and the queue follows Kubernetes list-then-watch semantics with at-least-once delivery. ### Objects #### Queue entry (`devins`) Each queued session is represented by one queue entry: | Field | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------- | | `metadata.session_id` | The session (devin) ID. | | `metadata.outpost_id` | The outpost the session is queued on. | | `metadata.created_at` | When the session was enqueued (Unix timestamp). | | `metadata.updated_at` | When this object last changed (Unix timestamp). | | `spec.kind` | `new` or `resume`. | | `spec.platform` | Machine platform, e.g. `linux`. | | `spec.remote_binary_sha` | Short commit SHA of the `devin-remote` binary the worker should run; `null` means the worker's default. | | `spec.network_policy` | The session's effective network policy (see below). | | `status.phase` | Queue phase: `pending` or `claimed`. | | `status.acceptor_id` | Worker that currently holds the claim, if claimed. | | `status.claim_deadline` | When the current claim expires and the session returns to the queue. | | `status.session_status` | Coarse status of the underlying session: `pending`, `running`, `suspended`, or `terminated`. | | `status.connect_token` | Gateway connect token; only returned from a successful claim. | | `status.gateway_url` | Public websocket URL of the outpost gateway; only returned from a successful claim. | `spec.network_policy` reports whether the session's network access is restricted (`enabled`) and the allowed destinations (`allow`): hostname globs (`{"hostname": ...}`), IPv4 addresses/CIDRs (`{"ipv4": ...}`), or IPv6 addresses/CIDRs (`{"ipv6": ...}`). #### Outpost | Field | Description | | ---------------------- | ---------------------------------------------------- | | `metadata.outpost_id` | The outpost ID (`outpost_env-...`). | | `metadata.account_id` | Account that owns the outpost. | | `metadata.created_at` | When the outpost was created (Unix timestamp). | | `spec.name` | Unique (per account) outpost name. | | `spec.platform` | Machine platform; `null` means the default platform. | | `spec.description` | Human-readable description. | | `status.queue_depth` | Number of pending (unclaimed) sessions in the queue. | | `status.active_claims` | Number of unexpired claims held by workers. | ### List queued sessions ``` GET /opbeta/outposts/devins ``` | Query param | Description | | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `outpost` | Filter by outpost ID. Applies to both list and watch. | | `phase` | Filter by queue phase (`pending` or `claimed`). Ignored when watching. | | `acceptor_id` | Filter by claiming worker. Ignored when watching. | | `first` | Maximum rows per list page, 1–200. Defaults to 100. | | `cursor` | Opaque cursor from a previous list response or watch event (the two are interchangeable). For a list, returns rows at or after this position; for a watch, replays changes after it before streaming live ones. | | `watch` | Stream changes as SSE instead of listing. | Example response: ```json theme={null} { "items": [ { "metadata": { "session_id": "devin-...", "outpost_id": "outpost_env-...", "created_at": 1781050000, "updated_at": 1781050000 }, "spec": { "kind": "new", "platform": "linux", "remote_binary_sha": null }, "status": { "phase": "pending", "acceptor_id": null, "claim_deadline": null, "session_status": "pending" } } ], "cursor": "djE6MTc4MTA1MDAwMC4w", "has_next_page": false, "total": 1 } ``` Pagination and delivery semantics: * Pass each response's `cursor` into the next request while `has_next_page` is `true`. * Delivery is at-least-once: a session at a page boundary can appear in both pages, so upsert entries by `metadata.session_id` rather than treating every item as new (the claim CAS makes duplicates harmless). * When `has_next_page` becomes `false`, save the returned cursor as the starting position for a watch. ### Watch for changes ``` GET /opbeta/outposts/devins?watch=true&cursor= ``` Streams Server-Sent Events. `MODIFIED` events fire when a session's queue entry changes (newly queued sessions also arrive as `MODIFIED`); `DELETED` events fire when it is removed. Each SSE `data` field contains: ```json theme={null} { "type": "MODIFIED", "object": { "metadata": { "session_id": "devin-...", "outpost_id": "outpost_env-...", "created_at": 1781050000, "updated_at": 1781050100 }, "spec": { "kind": "new", "platform": "linux", "remote_binary_sha": null }, "status": { "phase": "pending", "acceptor_id": null, "claim_deadline": null, "session_status": "pending" } }, "cursor": "djE6MTc4MTA1MDEwMC4w" } ``` Watch semantics: * Persist each event's top-level `cursor` after processing it; reconnect with the last persisted cursor to replay changes that occurred while disconnected. * Delivery is at-least-once — tolerate duplicate events. * Streams end after at most five minutes; a reconnecting watch loop is expected. * `phase` and `acceptor_id` filters are ignored when `watch=true`; filter watched events using the fields in each event's `object`. * Omitting the cursor starts from the beginning, so use list-then-watch for normal reconciliation. ### Get a queue entry ``` GET /opbeta/outposts/devins/{session_id} ``` Returns the queue entry for one session. ### Claim a session ``` POST /opbeta/outposts/devins/{session_id}/claim ``` ```json theme={null} { "acceptor_id": "worker-1" } ``` Atomically claims the session for the given worker identity. If another worker claimed it first, the request fails with `409`. A successful claim response includes `status.connect_token` and `status.gateway_url` — the credentials `devin-remote` needs to connect (see the [spawn contract](#spawn-contract)). Claiming promises that a worker will be ready within the server-assigned claim deadline (`status.claim_deadline`); expired claims return to the queue automatically. ### Release a claim ``` POST /opbeta/outposts/devins/{session_id}/release ``` ```json theme={null} { "acceptor_id": "worker-1" } ``` Releases the worker's claim so the session returns to the queue immediately (e.g. when provisioning fails). ### Outposts ``` GET /opbeta/outposts/outposts # list outposts POST /opbeta/outposts/outposts # create an outpost GET /opbeta/outposts/outposts/{outpost_id} # get an outpost DELETE /opbeta/outposts/outposts/{outpost_id} # delete an outpost ``` Create request body: ```json theme={null} { "name": "my-outpost", "platform": "linux", "description": "Dev boxes in our VPC" } ``` Create and delete require the write scope, get and list require the read scope; each outpost response reports live `status.queue_depth` and `status.active_claims`. ## Remote binary distribution The `devin worker start` command automatically downloads the correct `devin-remote` binary. Custom orchestrators that do not use the Devin CLI can fetch it directly from: ``` https://static.devin.ai/devin-rs/remote/ ``` **Determine the latest version:** ```bash theme={null} # Returns the git SHA of the latest published binary for your platform curl -fsSL "https://static.devin.ai/devin-rs/remote/latest_linux_x64" ``` **Download and verify:** ```bash theme={null} SHA=$(curl -fsSL "https://static.devin.ai/devin-rs/remote/latest_linux_x64") # Download the binary curl -fL "https://static.devin.ai/devin-rs/remote/devin-remote_${SHA}_linux_x64" \ -o devin-remote # Download and verify the checksum curl -fsSL "https://static.devin.ai/devin-rs/remote/devin-remote_${SHA}_linux_x64.sha256" \ -o devin-remote.sha256 echo "$(cat devin-remote.sha256) devin-remote" | sha256sum -c chmod +x devin-remote ``` **Available platforms:** | Suffix | OS / Architecture | | ----------------- | ------------------- | | `linux_x64` | Linux x86\_64 | | `linux_arm64` | Linux aarch64 | | `macos_arm64` | macOS Apple Silicon | | `windows_x64.exe` | Windows x86\_64 | If the session's queue entry includes a `spec.remote_binary_sha`, use that SHA instead of `latest` — it pins the session to a specific tested version. ## Spawn contract If your orchestrator launches `devin-remote` itself instead of using `devin worker start`, spawn it as: ```bash theme={null} devin-remote serve ``` with the following environment variables: | Variable | Required | Description | | ----------------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `DEVIN_OUTPOST_GATEWAY_URL` | Yes | Outpost gateway base URL, e.g. `wss://outpost-gateway.devin.ai`. | | `DEVIN_OUTPOST_CONNECT_TOKEN` | Yes | Bearer connect token for the gateway, from the claim response. | | `DEVIN_OUTPOST_SESSION_ID` | Yes | The session ID being served. All three `DEVIN_OUTPOST_*` variables must be set together. | | `DEVIN_REMOTE_STATE_DIR` | Strongly recommended | Per-session state directory where the remote stores its credentials, tokens, and shell-integration files. Use a unique directory per session (e.g. `~/.devin/worker/sessions/`, which is what `devin worker` uses). If unset, the remote falls back to a shared system-wide default (`/opt/.devin` on Linux, `~/.devin` on macOS, `C:\ProgramData\devin` on Windows), which must then exist and be writable — and which leaks per-session state across concurrent sessions. Always set this. | | `DEVIN_CHROME_PATH` | Optional | Path to a Chrome/Chromium binary on the box for the browser tool (there is no Devin-managed Chrome on Outposts). | | `DEVIN_OUTPOST_DESKTOP` | Optional | Set to `true` to enable the desktop (VNC) stream. It is lazy on the remote side — nothing is captured until a viewer connects — so it is safe to enable unconditionally. | Give the remote a clean environment containing only the variables above plus basic system variables (`PATH`, `HOME`, `USER`, `LOGNAME`, `TMPDIR`, `LANG`, `TZ`, and — for the desktop stream's screen capture on Linux/X11 — `DISPLAY`, `WAYLAND_DISPLAY`, `XAUTHORITY`). Do not leak anything the agent should not be able to see into the remote: it is inherited by the agent's shell. Additional lifecycle expectations: * **Working directory**: launch the remote from the directory you want the session to work in — repositories live under its `repos` subdirectory, i.e. `$(pwd)/repos/` (the same rule as `devin worker start`). * **Session end**: when the session ends (sleeps or terminates), Devin notifies the remote and it exits with status 0 on its own. Treat a clean exit as the end of the session: confirm the queue entry's `status.session_status` is `suspended` or `terminated` (the status update can lag the exit by a few seconds, so re-read a few times), then release the claim. As a fallback, also poll `status.session_status` while the remote runs and kill the process yourself once it reaches `terminated` (or the queue entry disappears). # Good vs. Bad Instructions Source: https://docs.devinenterprise.com/essential-guidelines/good-vs-bad-instructions What works and what doesn't Make sure to read [When to Use Devin](/essential-guidelines/when-to-use-devin) and [Instructing Devin Effectively](/essential-guidelines/instructing-devin-effectively) for more essential tips. **Good Approach** "Create a new endpoint `/users/stats` that returns a JSON object with user count and average signup age. Use our existing users table in PostgreSQL. You can reference the `/orders/stats` endpoint in `statsController.js` for how we structure responses. Ensure the new endpoint is covered by the `StatsController.test.js` suite." **Why This Works:** * Clearly specifies the route and expected response format * References existing code as a template * Defines data source (users table) * Includes test coverage requirements
***
**Bad Approach** "Add a user stats endpoint." **Why This Fails:** * Unspecific about what stats to include * No mention of data sources * No reference to existing patterns * Missing test requirements
**Good Approach** "In `UserProfileComponent`, add a dropdown that shows a list of user roles (admin, editor, viewer). Use the styling from `DropdownBase`. When a role is selected, call the existing API to set the user role. Validate by checking that the selection updates the user role in the DB. Refer to your Knowledge for how to test properly." **Why This Works:** * Names specific components * Lists exact roles to include * References existing styling component * Defines the user interaction flow * Includes validation steps
***
**Bad Approach** "Make the user profile page more user-friendly. Add some way for them to change roles and confirm it's working." **Why This Fails:** * "User-friendly" is subjective * No specific UI components mentioned * Unclear user interaction flow * Vague validation criteria
## More Examples ### Good "Add Jest tests for the AuthService methods: login and logout. Ensure test coverage for these two functions is at least 80%. Use `UserService.test.js` as an example. After implementation, run `npm test -- --coverage` and verify the coverage report shows >80% for both functions. Also confirm that tests pass with both valid and invalid credentials, and that logout properly clears session data." **Why Good?** Clear success metric (80% coverage), references to guide Devin (`UserService.test.js`), and a well-defined scope with specific verification steps. "Migrate `logger.js` from JavaScript to TypeScript. We already have a `tsconfig.json` and a `LoggerTest.test.js` suite for validation. Make sure it compiles without errors and make sure not to change the existing config! After migration, verify by: 1) running `tsc` to confirm no type errors, 2) running the test suite with `npm test LoggerTest.test.js` to ensure all tests pass, and 3) checking that all existing logger method calls throughout the codebase still work without type errors." **Why Good?** There's a clear template (`tsconfig.json`) and test suite for immediate feedback, plus specific compilation and validation steps. "We're switching from pg to sequelize (read [https://sequelize.org/api/v6/identifiers](https://sequelize.org/api/v6/identifiers)). Please update the UserModel queries to use Sequelize methods. Refer to `OrderModel` for how we do it in this codebase. After implementation, verify by: 1) running `npm run test:integration UserModel.test.js` to check all integration tests pass, 2) confirming query performance hasn't degraded by checking execution time on a test dataset of 1000 users, and 3) validating that all CRUD operations still maintain data integrity by running `npm run test:e2e user-flows.test.js`." **Why Good?** Devin can mimic a known pattern and there are explicit references (`OrderModel.js`). Provides a link to docs so Devin knows to reference them, and includes specific performance and functionality verification steps with exact test commands. "Implement the pricing page from this Figma file: [https://figma.com/file/abc123/Pricing-Page](https://figma.com/file/abc123/Pricing-Page). Focus on the 'Pricing Section' frame. Use our Tailwind config in tailwind.config.ts for colors and spacing. Reuse the existing Card and Button components from src/components/ui/. After implementing, spin up the dev server and take screenshots at desktop (1440px) and mobile (375px) widths. Do not open a PR until it matches the design." **Why Good?** Links the specific Figma file, names the exact frame, references the project's design system and existing components, and tells Devin to visually verify its work before opening a PR. With the [Figma MCP](/work-with-devin/mcp) connected, Devin can read design tokens directly from the file. "Users are reporting 500 errors on the checkout page. Use the Sentry MCP to pull the latest stack traces for the payments-api project. Check the database for any related data issues. Find the root cause, fix it, and add a regression test. Link the Sentry issue in the PR description." **Why Good?** Points Devin to the right tools ([MCP integrations](/work-with-devin/mcp)), gives a clear investigation path, and defines the expected deliverable (fix + regression test + PR). ### Bad "Find issues with our codebase and fix them" **Why Bad?** The request is too vague and open-ended. There are no success criteria and no way for Devin to know when it's done. **Instead:** Use [Devin Review](/work-with-devin/devin-review) for automated code review on specific PRs, or give Devin a targeted task like "Find and fix all uses of the deprecated `oldLogger` API in `src/services/`." "Make the landing page look better" **Why Bad?** "Better" is subjective and Devin has no criteria to aim for. Devin can build functional UIs and implement designs from specs, but it can't make aesthetic judgment calls on its own. **Instead:** Provide a Figma design, a reference site, or specific changes: "Increase the hero section font size to 48px, add 32px padding, and use the `indigo-500` color from our Tailwind config." "Build a new microservices architecture for our app." **Why Bad?** This is a very large and unstructured task. It requires many architectural decisions, trade-offs, and context that isn't in the prompt. **Instead, break it down:** 1. Use [Ask Devin](/work-with-devin/ask-devin) to investigate your codebase and map dependencies 2. Ask Devin to propose specific architectures with trade-offs 3. Create separate sessions for implementing each service — run them in parallel with [managed Devins](/work-with-devin/advanced-capabilities#managed-devins) # Instructing Devin Effectively Source: https://docs.devinenterprise.com/essential-guidelines/instructing-devin-effectively Learn how to write clear Devin prompts, provide useful context, and define success criteria for reliable results across engineering tasks. The most important thing to remember when instructing Devin is to **be as specific as possible**. Just as you would provide a detailed spec when asking a coworker to code something, you should do the same with Devin. This guide will help you structure your instructions/prompts to effectively use Devin. For broader strategies on working with coding agents effectively, also check out our [Coding Agents 101 guide](https://devin.ai/agents101). ## How to Write Effective Prompts Here is an example prompt that demonstrates effective instruction: In the Devin repo, I want you to build a tool that monitors the RAM and CPU usage of the remote machines that Devin runs on. To do that, please perform the following tasks: * Create a background task that launches automatically when devin.rs starts. * The task should open a connection to all forked remote machines used in this Devin session and monitor their RAM and CPU usage. * If usage exceeds 80% of the available resource, emit a new type of Devin event to signal this (check how we use Kafka). * Architect this in a smart way that doesn't block other operations. You should understand how all the containers for the Devin sub-agents interact with each other. ### Why This Works Well * **Detail:** Specifies the Devin repo and the broader purpose (monitoring resource usage). * **Benefit:** Devin knows the scope and domain clearly. * **Detail:** Tasks like "create a background task" and "emit an event at 80% usage." * **Benefit:** Breaks down the work into logical parts. * **Detail:** Defines "success" as emitting a specific event upon 80% usage. * **Benefit:** Devin knows exactly what to achieve. * **Detail:** Mentions Kafka and container interactions. * **Benefit:** Encourages reuse of established code or design approaches. ## Best Practices: Do's and Don'ts **Do: Provide Clear Directives** * **Why:** Devin can get stuck without a clear path or when faced with too many interpretations. * **How:** * Make important decisions and judgment calls for Devin. * Offer specific design choices and implementation strategies. * Define clear scope, boundaries, and success criteria. * **Example:** "Optimize the getOrderDetails query in orderService.js by adding a composite index on the order\_id and product\_id columns in the order\_items table. Refactor the query to replace the existing correlated subquery with a JOIN to the products table for fetching product details." **Don't: Leave Decisions Open-Ended** * **Why:** Vague instructions can lead Devin to implement solutions that don't align with your actual needs. * **How:** * Avoid statements that require Devin to make significant design or implementation decisions without guidance. This can lead to unexpected results. * **Example:** Don't: "Improve our database's performance." **Do: Pick [tasks that Devin is good at](when-to-use-devin#evaluating-tasks-for-devin)** * **Why:** * **Maximize Results:** By assigning tasks that align with Devin's capabilities, you get the best results for the least amount of effort and ACUs spent. * **How:** * Read this guide: [When to use Devin](when-to-use-devin) * Provide examples, modules, resources, and templates that Devin can follow. * Share direct links to docs sites so Devin can read about details like API request bodies and features it might not know about. * Share specific filenames that you want Devin to look at and learn from. * Connect [MCP integrations](/work-with-devin/mcp) to give Devin access to Figma designs, databases, monitoring tools, and more. * **Example:** Do: "Refactor state management in the Header component to use React's useReducer hook for better scalability and maintainability. Ensure that all existing functionality is preserved and add unit tests to cover the new state logic." * **Example:** Do: "Use authTemplate.rs as a reference to maintain consistency in error handling." * **Example:** Do: "Check out the official Sequelize docs at [https://sequelize.org/docs/v6/getting-started/](https://sequelize.org/docs/v6/getting-started/) for migration steps." **Don't: Skip Providing Context for Complex Tasks** * **Why:** Even though Devin can handle complex work, it performs best when you provide context and clear direction. * **How:** * For tasks requiring domain knowledge, provide relevant docs, examples, or references. * For visual tasks, provide Figma files via the [Figma MCP](/work-with-devin/mcp), reference designs, or detailed specs — Devin can build from these but won't invent aesthetics on its own. * For Android apps, Devin can build and test on an [Android emulator](/onboard-devin/environment/android-emulation). For iOS apps, Devin doesn't have access to a phone emulator, so provide clear testing criteria. * **Example:** Don't: "Make the app look better" — instead, provide specific design specs or a Figma file. * **Example:** Don't: "Improve our database's performance" — instead, specify which queries to optimize and what metrics to target. **Do: Establish Clear and Frequent Checks** * **Why:** Frequent feedback (both from you and from tests/checks/linters) ensures Devin corrects mistakes effectively. * **How:** * Use tests (unit/integration) to confirm correctness. * Maintain build validations, lint checks, and static analysis for code quality. * Enable [Devin Review](/work-with-devin/devin-review) with [Auto-Fix](/work-with-devin/devin-review#auto-fix) so Devin automatically responds to review comments and CI failures — creating a closed loop where PRs iterate toward merge-ready quality without you in the loop. * **Example:** Do: "Run npm test after each iteration." * **Example:** Do: "Ensure the pipeline on CircleCI doesn't fail." * **Example:** Do: "Pass ESLint/Prettier checks before pushing any commits." **Don't: Neglect Providing Feedback** * **Why:** Without feedback, Devin won't know if its solutions meet your standards. * **How:** * Avoid assigning tasks without defining how you'll evaluate them. **Do: Set Clear Checkpoints and Sub-Tasks** * **Why:** Breaking down complex tasks into smaller checkpoints helps Devin stay focused and reduces errors. * **How:** * Split tasks into verifiable sub-tasks, and start one Devin session for each sub-task. * Define what success looks like for each sub-task and optionally set checkpoints within each sub-task. * Ask Devin to report back after completing each checkpoint or sub-task. **Examples:** * **Example:** Do: "When working with the dataset, verify that it has at least 500 rows and contains columns X, Y, Z." * **Example:** Do: "When modifying the API, confirm the endpoint returns status 200 and includes all required fields." * **Example:** Do: "When updating UI, check that the component renders without console errors and matches the design spec." **Don't: Skip Specific Validation Requirements** * **Why:** Without defined validation steps, Devin cannot confidently complete tasks. * **How:** * Avoid vague success criteria. * Don't leave verification steps implicit or undefined. * **Example:** Don't: "Make sure it works." Devin has a full desktop environment — shell, IDE, and browser. Tell Devin to test its own work before opening a PR: * **Spin up the app:** "Run `npm run dev` and verify the new page renders at `/settings`." * **Browser testing:** "Open the browser, navigate to the login page, and confirm the OAuth flow completes successfully." * **Visual verification:** "Take screenshots at desktop (1440px) and mobile (375px) widths and confirm the layout matches the design." * **Screen recording:** "Record yourself testing the checkout flow end-to-end." This lets Devin QA its changes the same way you would — before you ever need to look at the PR. For repetitive or complex tasks, we suggest using and iterating on [Playbooks](/product-guides/creating-playbooks). Learn more about [using playbooks effectively](/product-guides/using-playbooks). Playbooks are reusable and shareable prompts that streamline task delegation. For example, if you want Devin to address ongoing CI build failures, create a playbook that includes the general steps Devin should follow each time. For persistent context that Devin should remember across all sessions — such as coding standards, common bugs and fixes, [deployment workflows](/product-guides/deployment-capabilities), or how to use internal tools — use [Knowledge](/product-guides/knowledge). Knowledge items are automatically recalled when relevant, so you don't need to repeat the same instructions in every prompt. You can pin Knowledge to specific repos or apply it globally. **Playbooks vs. Knowledge:** Use Playbooks for step-by-step procedures tied to specific tasks. Use Knowledge for general tips, conventions, and context that apply broadly across sessions. # Prompt Templates Cheat Sheet Source: https://docs.devinenterprise.com/essential-guidelines/prompt-templates-cheat-sheet Ready-to-use prompt templates for common tasks Use these templates as starting points for your prompts. Customize the bracketed sections `[like this]` to fit your specific needs. ## Bug Fixes ### Fix a Specific Bug ``` Fix the bug where `[describe the bug behavior]`. Steps to reproduce: 1. `[Step 1]` 2. `[Step 2]` 3. `[Step 3]` Expected behavior: `[what should happen]` Actual behavior: `[what actually happens]` Please: 1. Investigate the root cause in `[relevant file/directory]` 2. Implement a fix that addresses the root cause 3. Add a regression test to prevent this issue from recurring 4. Run the existing test suite to ensure no regressions ``` ### Investigate Production Issue ``` Users are reporting `[describe the issue]` in production. Please: 1. Use the `[Sentry/DataDog/Log monitoring tool]` MCP to pull recent error logs and stack traces 2. Identify the root cause of the issue 3. Implement a fix 4. Add appropriate error handling to prevent similar issues 5. Create a regression test 6. Link the monitoring/alert in the PR description ``` ## Feature Implementation ### Add a New API Endpoint ``` Create a new API endpoint `[endpoint path]` that `[describe what it does]`. Requirements: - Method: `[GET/POST/PUT/DELETE]` - Request body: `[describe request structure]` - Response format: `[describe response structure]` - Authentication: `[describe auth requirements]` Please: 1. Reference the existing `[similar endpoint file]` for patterns 2. Implement the endpoint following our existing conventions 3. Add input validation and error handling 4. Write unit tests for the new endpoint 5. Update API documentation if applicable 6. Run the test suite to ensure everything passes ``` ### Add a New UI Component ``` Add a new `[component type]` component to `[file/location]`. Requirements: - Component name: `[ComponentName]` - Props: `[list props and their types]` - Functionality: `[describe what it should do]` - Styling: Use `[existing component/library]` as a reference Please: 1. Create the component following our existing patterns 2. Implement the required functionality 3. Add proper TypeScript types 4. Style it to match our design system 5. Add unit tests for the component 6. Integrate it into `[parent component/page]` 7. Test it manually by running the dev server ``` ### Implement a Feature from Design ``` Implement the `[feature name]` from this design file: `[Figma/link to design]` Focus on the `[specific frame/section]` frame. Requirements: - Use our existing components from `[component library path]` - Follow the styling in `[design system file]` - Ensure responsive design at `[breakpoint 1]` and `[breakpoint 2]` Please: 1. Implement the feature following the design specifications 2. Reuse existing components where possible 3. Test at desktop (1440px) and mobile (375px) widths 4. Take screenshots to verify it matches the design 5. Do not open a PR until it visually matches the design ``` ## Code Refactoring ### Refactor a Module ``` Refactor the `[module/file name]` to improve `[specific aspect: maintainability/performance/readability]`. Current issues: - `[Issue 1]` - `[Issue 2]` - `[Issue 3]` Requirements: - Keep all existing functionality intact - Follow the patterns in `[reference file]` - Improve `[specific metric: code complexity/performance]` Please: 1. Analyze the current implementation 2. Refactor following best practices 3. Ensure all existing tests still pass 4. Add tests for any new functions introduced 5. Run the full test suite 6. Measure and report performance improvements if applicable ``` ### Convert to New Pattern ``` Convert `[file/directory]` to use `[new pattern/library/framework]`. Reference: `[link to documentation or example file]` Requirements: - Maintain all existing functionality - Follow the conventions in `[example file]` - Update any dependent code Please: 1. Review the documentation and examples 2. Convert the code step by step 3. Update imports and dependencies 4. Ensure all tests pass 5. Run `[build command]` to verify no errors 6. Test the functionality manually ``` ## Testing ### Add Test Coverage ``` Add comprehensive test coverage for `[file/module/function]`. Current coverage: `[current coverage %]` Target coverage: `[target coverage %]` Please: 1. Analyze the existing code to identify edge cases 2. Write unit tests for all public methods 3. Add integration tests if applicable 4. Reference `[existing test file]` for testing patterns 5. Run `npm test -- --coverage` and verify coverage meets target 6. Ensure all tests pass ``` ### Debug Failing Tests ``` Fix the failing tests in `[test file or directory]`. Test failures: - `[Test name 1]`: `[error message]` - `[Test name 2]`: `[error message]` Please: 1. Investigate why these tests are failing 2. Determine if the tests or the implementation need fixing 3. Fix the root cause 4. Ensure all tests in the suite pass 5. Run the full test suite to check for regressions ``` ## Documentation ### Document a Module ``` Add comprehensive documentation to `[file/module]`. Please: 1. Add JSDoc/TypeDoc comments to all public functions 2. Document parameters, return values, and exceptions 3. Add usage examples for complex functions 4. Create a README if this is a new module 5. Follow our documentation style guide in `[style guide link]` 6. Update the main API documentation if applicable ``` ### Update API Documentation ``` Update the API documentation for `[endpoint/function]`. Changes made: - `[Change 1]` - `[Change 2]` Please: 1. Update the `[OpenAPI/Swagger]` specification 2. Update any inline code comments 3. Add usage examples if the behavior changed 4. Update the `[documentation file]` 5. Verify the documentation builds successfully ``` ## Performance Optimization ### Optimize Database Queries ``` Optimize the database queries in `[file/module]`. Performance issues: - `[Specific query]` is slow (takes `[time]`) - `[Specific operation]` causes N+1 queries Please: 1. Analyze the query execution plans 2. Add appropriate indexes to `[table/column]` 3. Refactor queries to use joins instead of N+1 4. Benchmark before and after performance 5. Ensure all tests still pass 6. Document the performance improvements ``` ### Optimize Frontend Performance ``` Optimize the performance of `[component/page]`. Performance issues: - Slow initial load time - Large bundle size - Unnecessary re-renders Please: 1. Analyze the bundle size using `[bundle analyzer]` 2. Implement code splitting for `[large module]` 3. Add memoization where appropriate 4. Optimize images and assets 5. Lazy load components below the fold 6. Measure performance improvements using Lighthouse 7. Ensure functionality remains intact ``` ## Security ### Fix Security Vulnerability ``` Fix the security vulnerability identified in `[file/module]`. Vulnerability type: `[e.g., SQL injection, XSS, CSRF]` Severity: `[High/Medium/Low]` Please: 1. Review the security advisory: `[link to advisory]` 2. Implement the recommended fix 3. Add input validation and sanitization 4. Add a security test to prevent regression 5. Run the security audit: `[audit command]` 6. Ensure no other similar vulnerabilities exist ``` ### Add Security Headers ``` Add security headers to the `[application/API]`. Required headers: - `[Header 1]`: `[value]` - `[Header 2]`: `[value]` - `[Header 3]`: `[value]` Please: 1. Configure the headers in `[config file]` 2. Test that headers are set correctly using `[tool/method]` 3. Ensure existing functionality is not broken 4. Document the security improvements ``` ## Migration & Upgrades ### Upgrade Dependency ``` Upgrade `[package/library]` from version `[old version]` to version `[new version]`. Please: 1. Review the changelog for breaking changes: `[changelog link]` 2. Update the dependency in `[package.json/requirements.txt]` 3. Update any deprecated API usage 4. Run the migration script if applicable: `[migration command]` 5. Run all tests to ensure compatibility 6. Test the application manually 7. Update documentation if APIs changed ``` ### Migrate to New Service ``` Migrate from `[old service]` to `[new service]`. Reference documentation: `[link to new service docs]` Please: 1. Set up the new service following the documentation 2. Migrate existing data/configuration 3. Update all code to use the new service 4. Reference `[example file]` for implementation patterns 5. Run integration tests to verify functionality 6. Gradually roll out and monitor for issues 7. Decommission the old service after verification ``` ## Code Review ### Review a Pull Request ``` Review the pull request: `[PR link or number]` Focus areas: - Code quality and maintainability - Performance implications - Security considerations - Test coverage - Documentation Please: 1. Review each file changed 2. Leave specific, actionable comments 3. Verify the changes address the PR description 4. Check for edge cases and error handling 5. Ensure tests are adequate 6. Approve or request changes with clear feedback ``` ## General Purpose ### Research and Implement ``` I need to implement `[feature/functionality]` using `[technology/library]`. Please: 1. Research the best practices for `[technology/library]` 2. Find and review documentation: `[expected doc sources]` 3. Look at open-source examples if applicable 4. Propose an approach before implementing 5. Implement the solution following best practices 6. Add tests and documentation 7. Verify it works as expected ``` ### Debug and Fix ``` Something is wrong with `[feature/component]`. Symptoms: - `[Symptom 1]` - `[Symptom 2]` Please: 1. Investigate the issue in `[relevant files]` 2. Add logging/debugging statements as needed 3. Identify the root cause 4. Implement a fix 5. Test the fix thoroughly 6. Remove any temporary debugging code 7. Ensure no regressions ``` **Pro tip**: For recurring tasks, consider creating a [Playbook](/product-guides/creating-playbooks) with these templates so you can reuse them easily. # How does Devin fit into my existing SDLC? Source: https://docs.devinenterprise.com/essential-guidelines/sdlc-integration See how Devin supports software development lifecycle work, from code planning and testing through review, security, and deployment. ## Overview Devin integrates across the entire software development lifecycle—from understanding existing code and planning changes to testing, reviewing, and deploying updates. For details on Devin's built-in app deployment options and their limitations, see the [Devin app deployments guide](/product-guides/deployment-capabilities). ## Where Engineers Spend Their Time Research shows that less than 20% of an engineer's time is spent writing code ([1](https://www.software.com/reports/code-time-report), [2](https://www.microsoft.com/en-us/research/wp-content/uploads/2024/11/Time-Warp-Developer-Productivity-Study.pdf)). The majority of time is dedicated to understanding codebases, planning changes, reviewing work, and testing. Devin helps accelerate each of these phases while keeping human engineers in control. Devin Across the SDLC ## Working Within Existing Engineering Processes Devin contributes to existing codebases by creating Pull Requests containing its suggested code changes. Devin is subject to the exact same branch protections and SDLC policies as any human engineer. Human engineers review PRs created by Devin before choosing whether to merge the code changes. ## SDLC Integration Points ### Understanding Code & Planning Before writing any code, engineers need to understand existing systems and plan their approach. Devin accelerates this phase significantly: Use [DeepWiki](/work-with-devin/deepwiki) to navigate architecture and code with auto-generated documentation. DeepWiki provides conversational documentation for your repositories, making it faster to understand complex systems and dependencies. Use [Ask Devin](/work-with-devin/ask-devin) to query your codebase directly. Ask Devin can answer questions about code structure and dependencies, and help you scope and plan tasks before implementation. With advanced code search capabilities, Ask Devin produces detailed, accurate, and well-cited answers, reducing the time spent reverse-engineering and tracing dependencies. Devin can scope and plan tasks by analyzing requirements against your codebase. When integrated with [Jira](/integrations/jira) or [Linear](/integrations/linear), Devin automatically analyzes tickets and provides confidence scores to help prioritize work. Devin can triage alerts and backlog items, categorizing issues and suggesting approaches. This helps engineering teams prioritize effectively and reduces time spent on initial investigation. ### Development Devin handles development tasks asynchronously, allowing engineers to delegate work while focusing on higher-value activities: Delegate well-defined tasks to Devin asynchronously. Devin works in its own environment, preparing code changes and submitting PRs for review. This is particularly effective for repetitive tasks that can be parallelized across multiple Devin sessions. Devin excels at large-scale modernization projects. For example, customers have used Devin to migrate multi-million-line ETL monoliths to modular components, achieving 8x human time savings. Devin can execute end-to-end migrations across hundreds of repositories, including legacy stacks like COBOL. Devin prepares and submits PRs following your team's conventions. Devin automatically discovers [PR templates](/integrations/pr-templates) in your repository — including Devin-specific templates (`DEVIN_PR_TEMPLATE.md`) and standard GitHub/GitLab templates. You can customize the template Devin uses without changing your human-facing default. ### Testing Devin runs self-driven test loops in its own environment, improving test coverage and catching issues early: Devin writes tests from human-provided [playbooks](/product-guides/creating-playbooks), following your team's testing patterns and conventions. When Devin generates tests, coverage typically increases 1.5-2x, often reaching 90%+ coverage. Devin runs tests in its own environment, iterating on code until tests pass. This includes running your existing test suites, linting, and type checking before submitting PRs. ### Code Review Devin can provide automated first-pass reviews on pull requests: [Devin Review](/work-with-devin/devin-review) provides automated first-pass reviews on pull requests, checking for correctness and conformance with organizational best practices. You can enable it on all PRs or only Devin-authored PRs via your organization settings. With [Auto-Fix](/work-with-devin/devin-review#auto-fix) enabled, Devin automatically responds to code review comments, fixes flagged bugs, and iterates on CI failures — creating a closed loop where PRs iterate toward merge-ready quality without you in the loop. Devin checks PRs against your coding standards, style guides, and security requirements, flagging potential issues for human reviewers to address. ### Security and Compliance Devin integrates into CI/CD pipelines to address security findings automatically: Integrate Devin into your CI/CD pipeline to respond to findings from static analysis tools like SonarQube, Fortify, or Veracode. When these tools flag an issue, Devin can review and fix it automatically. Customers report approximately 70% of vulnerabilities are resolved automatically—clearing historical backlogs and reducing security risk. Devin can execute compliance-related changes across your codebase. For example, when new regulations require updates across hundreds of thousands of files, Devin can implement the changes systematically across all affected repositories. ## Getting Started To integrate Devin into your SDLC: 1. **Connect your repositories** via [GitHub](/integrations/gh), [GitHub Enterprise Server](/enterprise/integrations/github-enterprise-server), [GitLab](/integrations/gitlab), [Bitbucket](/integrations/bitbucket), or [Azure DevOps](/enterprise/integrations/azure-devops) 2. **Configure branch protections** to ensure Devin's PRs go through your standard review process 3. **Set up integrations** with [Jira](/integrations/jira) or [Linear](/integrations/linear) for ticket-based workflows, and [Slack](/integrations/slack) or [Microsoft Teams](/integrations/microsoft-teams) to chat and collaborate with Devin 4. **Create [playbooks](/product-guides/creating-playbooks) and [knowledge](/product-guides/knowledge)** to codify your team's patterns and standards for Devin to follow 5. **Connect MCPs** to extend Devin's capabilities with [custom tools and integrations](/work-with-devin/mcp) 6. **Configure CI/CD integration** to enable automated security remediation and testing # When to Use Devin Source: https://docs.devinenterprise.com/essential-guidelines/when-to-use-devin **TLDR:** Devin can handle the majority of engineering tasks, including medium and hard complexity work. The clearer and more specific your instructions, the higher the success rate — especially for complex tasks. For more comprehensive guidance on working effectively with coding agents, see our [Coding Agents 101 guide](https://devin.ai/agents101). ## Best Practices  **Scope tasks with [Ask Devin](/work-with-devin/ask-devin) before implementation:** * Explore your codebase with Ask Devin's advanced code search, scope the approach, and let Devin auto-generate a high-context prompt, all before a single line of code is written.  **Run multiple Devins in parallel:** * Carve out independent tasks and run them simultaneously. [Ask Devin to delegate to managed Devins](/work-with-devin/advanced-capabilities#managed-devins) to launch many sessions at once, or the [Devin API](/api-reference/overview) for programmatic orchestration. * Return to draft PRs waiting for review.  **Tag Devin on [Slack](/integrations/slack) or [Teams](/integrations/microsoft-teams):** * Start sessions directly from conversations about bugs, feature requests, or questions. Devin responds in-thread with updates.  **Let Devin close the loop:** * Enable [Devin Review](/work-with-devin/devin-review) with [Auto-Fix](/work-with-devin/devin-review#auto-fix) so Devin automatically responds to code review comments, fixes flagged bugs, and iterates on CI failures — without you needing to be in the loop. The result: PRs that are ready to merge by the time you look at them.  **Extend Devin's reach with [MCP integrations](/work-with-devin/mcp):** * Connect Devin to Datadog, Sentry, databases, Figma, Notion, Stripe, and hundreds of other tools via the MCP Marketplace. Devin can investigate production issues, query data, read designs, and more — all within a single session.  **Let Devin test its own work:** * Devin has a full desktop environment with a shell, IDE, and browser. It can spin up your app locally, click through the UI, take screenshots, record screen recordings, and QA its own changes before opening a PR.  **Automate recurring tasks with [Scheduled Sessions](/product-guides/scheduled-sessions):** * Set up daily or weekly sessions to triage Sentry errors, update dependencies, generate reports, or any other repeatable work.  **Use [Devin CLI](/cli) for local coding:** * Work with Devin directly from your terminal without leaving your editor. Perfect for quick fixes, code exploration, and tasks that benefit from your local environment context. Use [`/handoff`](/work-with-devin/devin-cli#handoff-to-cloud-devin) to seamlessly transfer work to a cloud Devin session when needed. Install with `curl -fsSL https://cli.devin.ai/install.sh | bash`. ## Evaluating Tasks for Devin When deciding if a task suits Devin, ask yourself: 1. **Can I describe clear success criteria?** Tasks with test suites, CI checks, or verifiable outcomes yield the best results. 2. **Is there enough context?** Provide relevant files, patterns, docs, or examples. The more context, the better. 3. **Would breaking this down help?** For very large projects, split the work into focused sessions that build on each other. You can run them in parallel with [managed Devins](/work-with-devin/advanced-capabilities#managed-devins). As a rule of thumb: if a task would take you three hours or less, Devin can most likely do it. For longer tasks, break them into smaller sessions. ## Pre-Task Checklist **Task Definition and Scope** * Good tasks have a clear start and end, plus explicit success criteria (e.g., passing tests, matching an existing pattern, CI green) * For complex tasks, use [Ask Devin](/work-with-devin/ask-devin) to collaboratively scope the work before starting a session. Ask Devin can help you investigate the codebase and outline your approach. **Available Context** * Are there examples or patterns for Devin to follow? * Can you provide prototypes, partial code, or existing patterns from the codebase or docs? * Are there links, filenames, or design files for Devin to reference? * Have you connected relevant [MCP integrations](/work-with-devin/mcp) (databases, monitoring, design tools)? **Success Validation** * Tasks with test suites, lint checks, or compilation steps yield better results * Devin can test its own work by launching your app and verifying behavior in the browser * Enable [Devin Review](/work-with-devin/devin-review) to catch bugs before you even look at the PR **Review Effort** * With [Auto-Fix](/work-with-devin/devin-review#auto-fix) enabled, Devin responds to review comments and CI failures automatically * Ideally, you just need to see that CI passes and the PR is approved **Task Size** * For large tasks, consider breaking them down into sub-tasks or [asking Devin to run them in parallel](/work-with-devin/advanced-capabilities#managed-devins) * Splitting large requests into smaller, manageable chunks helps Devin stay on track * Try to keep sessions focused (XS, S, or M as measured by [Session Insights](/product-guides/session-insights)) ## Post-Task Review **Monitor Session Trajectory** * Leverage [Session Insights](/product-guides/session-insights) to investigate the session timeline and identify actionable feedback for future sessions