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

# Bring existing resources under management

> Turn resources that already exist in your cloud into formae-managed code, without recreating anything.

You have resources created through the console, a CLI, or another tool, and you
want formae to manage them: change them, tag them, evolve them through code.
formae [discovers](/documentation/concepts/discovery) them, then lets you extract
them as Pkl and bring them under management without touching or recreating
anything.

<Note>
  **Before you start:** discovery has to have run on a discoverable target. If you
  haven't set one up yet, do [Create a target](/documentation/guides/create-a-target)
  first. The examples below adopt AWS internet gateways; use the equivalent types
  for your own resources.
</Note>

<Tabs>
  <Tab title="CLI">
    <Steps>
      <Step title="Find the unmanaged resources">
        Discovery records the resources formae doesn't manage yet. List what it
        found in your inventory:

        ```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
        formae inventory resources --query="managed:false"
        ```

        The query matches resources by attribute, so add filters to home in on
        exactly what you want. Here, only the internet gateways:

        ```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
        formae inventory resources --query="managed:false type:AWS::EC2::InternetGateway"
        ```

        <div className="fa-term">
          <div className="fa-term-body">  <span style={{fontWeight:'600'}} /><span style={{color:'rgb(232,232,232)',fontWeight:'600'}}>formae</span> <span style={{fontWeight:'600'}} /><span style={{color:'rgb(255,133,51)',fontWeight:'600'}}>inventory</span><br /><span style={{color:'rgb(85,85,102)'}}>────────────────────────────────────────────────────────────────────────────────────────────────────────────────────</span><br /><span style={{color:'rgb(85,85,102)'}} /> <span style={{color:'rgb(129,209,219)'}}>╭─────────────╮</span><br /> <span style={{color:'rgb(129,209,219)'}}>│</span><span style={{color:'rgb(129,209,219)',fontWeight:'600'}}> 1 Resources </span><span style={{color:'rgb(129,209,219)'}}>│</span>  <span style={{color:'rgb(170,170,170)'}}> 2 Targets </span>  <span style={{color:'rgb(170,170,170)'}}> 3 Stacks </span>  <span style={{color:'rgb(170,170,170)'}}> 4 Policies </span><br /><span style={{color:'rgb(129,209,219)'}}>─╯             ╰────────────────────────────────────────────────────────────────────────────────────────────────────</span><br /><span style={{color:'rgb(129,209,219)'}} /><br /><span style={{color:'rgb(129,209,219)'}} /><span style={{color:'rgb(129,209,219)',fontWeight:'600'}} /><span style={{color:'rgb(232,232,232)',fontWeight:'600'}}>Label ▲                   </span><span style={{color:'rgb(170,170,170)',fontWeight:'600'}}>Stack            Type                          NativeID                           </span><br /><span style={{color:'rgb(85,85,102)'}}>────────────────────────────────────────────────────────────────────────────────────────────────────────────</span><br /><span style={{color:'rgb(232,232,232)'}} /><span style={{color:'rgb(232,232,232)'}}>formae-auto-recon-inline-1</span><span style={{color:'rgb(232,232,232)',fontWeight:'600'}} /><span style={{color:'rgb(248,113,113)',fontWeight:'600'}}>⚠ unmanaged</span>      <span style={{color:'rgb(232,232,232)'}}>AWS::EC2::InternetGateway     igw-037caa5c87583128e              </span><br /><span style={{color:'rgb(232,232,232)'}} /><span style={{color:'rgb(232,232,232)'}}>formae-auto-recon-standal…</span><span style={{color:'rgb(232,232,232)',fontWeight:'600'}} /><span style={{color:'rgb(248,113,113)',fontWeight:'600'}}>⚠ unmanaged</span>      <span style={{color:'rgb(232,232,232)'}}>AWS::EC2::InternetGateway     igw-0555aa2884ab0d7a8              </span><br /><span style={{color:'rgb(232,232,232)'}}>formae-lgtm-igw           </span><span style={{color:'rgb(232,232,232)',fontWeight:'600'}} /><span style={{color:'rgb(248,113,113)',fontWeight:'600'}}>⚠ unmanaged</span>      <span style={{color:'rgb(232,232,232)'}}>AWS::EC2::InternetGateway     igw-0ec4e39eb6bf0a348              </span><br /><span style={{color:'rgb(232,232,232)'}}>igw-00fda294a8aa7d0ce     </span><span style={{color:'rgb(232,232,232)',fontWeight:'600'}} /><span style={{color:'rgb(248,113,113)',fontWeight:'600'}}>⚠ unmanaged</span>      <span style={{color:'rgb(232,232,232)'}}>AWS::EC2::InternetGateway     igw-00fda294a8aa7d0ce              </span><br /><span style={{color:'rgb(232,232,232)'}}>igw-03ff9cdf7e484fcbe-2   </span><span style={{color:'rgb(232,232,232)',fontWeight:'600'}} /><span style={{color:'rgb(248,113,113)',fontWeight:'600'}}>⚠ unmanaged</span>      <span style={{color:'rgb(232,232,232)'}}>AWS::EC2::InternetGateway     igw-03ff9cdf7e484fcbe              </span><br /><span style={{color:'rgb(232,232,232)'}}>igw-06c867a1939f44327     </span><span style={{color:'rgb(232,232,232)',fontWeight:'600'}} /><span style={{color:'rgb(248,113,113)',fontWeight:'600'}}>⚠ unmanaged</span>      <span style={{color:'rgb(232,232,232)'}}>AWS::EC2::InternetGateway     igw-06c867a1939f44327              </span><br /><span style={{color:'rgb(232,232,232)'}}>igw-0e65d7a67d98849cf     </span><span style={{color:'rgb(232,232,232)',fontWeight:'600'}} /><span style={{color:'rgb(248,113,113)',fontWeight:'600'}}>⚠ unmanaged</span>      <span style={{color:'rgb(232,232,232)'}}>AWS::EC2::InternetGateway     igw-0e65d7a67d98849cf              </span><br /><span style={{color:'rgb(232,232,232)'}}>lifeline-1558-igw-2       </span><span style={{color:'rgb(232,232,232)',fontWeight:'600'}} /><span style={{color:'rgb(248,113,113)',fontWeight:'600'}}>⚠ unmanaged</span>      <span style={{color:'rgb(232,232,232)'}}>AWS::EC2::InternetGateway     igw-03c849fb5154f7715              </span><br /><span style={{color:'rgb(232,232,232)'}}>lifeline-abc1-igw-1       </span><span style={{color:'rgb(232,232,232)',fontWeight:'600'}} /><span style={{color:'rgb(248,113,113)',fontWeight:'600'}}>⚠ unmanaged</span>      <span style={{color:'rgb(232,232,232)'}}>AWS::EC2::InternetGateway     igw-0b9e65ff163e1b5ff              </span><br /><br />Showing 9 of 9 resources (filtered)<br /><span style={{color:'rgb(85,85,102)'}}>────────────────────────────────────────────────────────────────────────────────────────────────────────────────────</span><br /><span style={{color:'rgb(85,85,102)'}} />  <span style={{color:'rgb(129,209,219)'}}>/</span> <span style={{color:'rgb(170,170,170)'}}>managed:false type:AWS::EC2::InternetGateway</span>                                                     <span style={{color:'rgb(153,153,153)'}}>/: edit query</span><br /><span style={{color:'rgb(85,85,102)'}}>────────────────────────────────────────────────────────────────────────────────────────────────────────────────────</span></div>
        </div>

        You can filter by attributes like `type`, `label`, and `target`, and use
        `*` wildcards. See the [CLI reference](/documentation/reference/cli) for
        the full query syntax.
      </Step>

      <Step title="Extract the ones you want">
        Pull the resources you want into a forma:

        ```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
        formae extract --query="managed:false type:AWS::EC2::InternetGateway" networking.pkl
        ```

        <div className="fa-term">
          <div className="fa-term-body">Initialized new Pkl project at .<br /><span style={{color:'rgb(181,181,91)'}}>Initialized pkl project at '.'</span><br /><span style={{color:'rgb(232,232,232)'}}>Extracted 9 resources to networking.pkl</span><br /><br />  <span style={{color:'rgb(129,209,219)'}}>formae-auto-recon-inline-1</span> (<span style={{color:'rgb(170,170,170)'}}>AWS::EC2::InternetGateway</span>) on stack <span style={{color:'rgb(232,232,232)'}}>$unmanaged</span><br/>&nbsp;&nbsp;<span style={{color:'rgb(129,209,219)'}}>formae-auto-recon-standalone-1</span>&nbsp;(<span style={{color:'rgb(170,170,170)'}}>AWS::EC2::InternetGateway</span>)&nbsp;on&nbsp;stack&nbsp;<span style={{color:'rgb(232,232,232)'}}>$unmanaged</span><br />  <span style={{color:'rgb(129,209,219)'}}>formae-lgtm-igw</span> (<span style={{color:'rgb(170,170,170)'}}>AWS::EC2::InternetGateway</span>) on stack <span style={{color:'rgb(232,232,232)'}}>$unmanaged</span><br/>&nbsp;&nbsp;<span style={{color:'rgb(129,209,219)'}}>igw-00fda294a8aa7d0ce</span>&nbsp;(<span style={{color:'rgb(170,170,170)'}}>AWS::EC2::InternetGateway</span>)&nbsp;on&nbsp;stack&nbsp;<span style={{color:'rgb(232,232,232)'}}>$unmanaged</span><br />  <span style={{color:'rgb(129,209,219)'}}>igw-03ff9cdf7e484fcbe-2</span> (<span style={{color:'rgb(170,170,170)'}}>AWS::EC2::InternetGateway</span>) on stack <span style={{color:'rgb(232,232,232)'}}>$unmanaged</span><br/>&nbsp;&nbsp;<span style={{color:'rgb(129,209,219)'}}>igw-06c867a1939f44327</span>&nbsp;(<span style={{color:'rgb(170,170,170)'}}>AWS::EC2::InternetGateway</span>)&nbsp;on&nbsp;stack&nbsp;<span style={{color:'rgb(232,232,232)'}}>$unmanaged</span><br />  <span style={{color:'rgb(129,209,219)'}}>igw-0e65d7a67d98849cf</span> (<span style={{color:'rgb(170,170,170)'}}>AWS::EC2::InternetGateway</span>) on stack <span style={{color:'rgb(232,232,232)'}}>$unmanaged</span><br/>&nbsp;&nbsp;<span style={{color:'rgb(129,209,219)'}}>lifeline-1558-igw-2</span>&nbsp;(<span style={{color:'rgb(170,170,170)'}}>AWS::EC2::InternetGateway</span>)&nbsp;on&nbsp;stack&nbsp;<span style={{color:'rgb(232,232,232)'}}>$unmanaged</span><br />  <span style={{color:'rgb(129,209,219)'}}>lifeline-abc1-igw-1</span> (<span style={{color:'rgb(170,170,170)'}}>AWS::EC2::InternetGateway</span>) on stack <span style={{color:'rgb(232,232,232)'}}>\$unmanaged</span></div>
        </div>

        This writes `networking.pkl` with the resources you selected. formae
        creates a `PklProject` only when there is none anywhere in the directory
        hierarchy where you extract. Run `extract` in a fresh, empty directory and
        it scaffolds a starter project (a `PklProject` pinning the formae and
        provider schema packages the resources need, plus a `main.pkl`) and prints
        an "Initialized new Pkl project" line. Run it inside a directory already
        covered by a `PklProject` and formae writes just `networking.pkl`, reusing
        the dependencies already declared there.

        Usually you extract straight into your existing formae project. When you
        do, make sure the new file is reachable: either import `networking.pkl`
        somewhere in your `main.pkl` include hierarchy, or copy the extracted
        resources into a file that is already included. A forma file that nothing
        imports is written to disk but never applied.

        <Note>
          Extracted files need formae `0.88.0` or greater (they use
          `extends "@formae/forma.pkl"`). If your project's `PklProject` pins an
          older version, extract still writes the file but prints a notice to bump
          the formae dependency and run `pkl project resolve`. See
          [Schema version compatibility](/documentation/reference/cli/extract#schema-version-compatibility).
        </Note>
      </Step>

      <Step title="Move them onto a managed stack">
        Discovered resources sit on formae's built-in `unmanaged` stack, so
        `extract` comments the stack label out and leaves you a prompt. Uncomment
        it and give the resources a stack of your own (the description comes
        pre-filled by `extract`; keep it or change it):

        ```kotlin theme={"languages":{"custom":["/languages/pkl.json"]}}
        local myStack = new formae.Stack {
          // Please provide a stack to bring the resources in this Forma under management
          label = "imported-networking"
          description = "Resources imported with formae extract"
        }
        ```

        Applying moves them off the `unmanaged` stack and onto
        `imported-networking`, where formae manages them.
      </Step>

      <Step title="Apply, then verify">
        ```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
        formae apply --mode reconcile networking.pkl
        ```

        formae recognizes these as the resources discovery already found, so
        nothing is recreated. It puts each one under management, moving them off
        the `unmanaged` stack and onto `imported-networking`. Confirm:

        ```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
        formae inventory resources --query="stack:imported-networking"
        ```
      </Step>
    </Steps>
  </Tab>

  <Tab title="AI assistants">
    With the [formae MCP plugin](/documentation/guides/ai-coding-assistants)
    connected, you drive the same flow as a conversation. Ask what discovery
    turned up, name what you want to adopt, and let the assistant's
    `formae-import` skill extract, simulate, and apply:

    <div className="fa-convo">
      <div className="fa-convo-head">Conversation</div>
      <div className="fa-turn fa-you"><div className="fa-tag">You</div><div className="fa-body">Do we have any unmanaged resources?</div></div>
      <div className="fa-turn fa-bot"><div className="fa-tag">Assistant</div><div className="fa-body">Discovery has six unmanaged internet gateways on the <code>unmanaged</code> stack: <code>legacy-igw-inline</code>, <code>legacy-igw-standalone</code>, <code>igw-0a1b2c3d4e5f6a7b8</code>, <code>igw-0f9e8d7c6b5a4f3e2</code>, <code>webapp-1558-igw-1</code>, and <code>webapp-abc1-igw</code>. Want me to bring them under management?</div></div>
      <div className="fa-turn fa-you"><div className="fa-tag">You</div><div className="fa-body">Bring the internet gateways under management.</div></div>
      <div className="fa-turn fa-bot"><div className="fa-tag">Assistant</div><div className="fa-body">I'll extract the six into a new <code>imported-networking</code> stack and simulate first. The simulation creates the stack and moves 6 resources from <code>unmanaged</code> to <code>imported-networking</code>, putting them under management with nothing recreated. Apply it?</div></div>
      <div className="fa-turn fa-you"><div className="fa-tag">You</div><div className="fa-body">Yes.</div></div>
      <div className="fa-turn fa-bot"><div className="fa-tag">Assistant</div><div className="fa-body">Applied. The six internet gateways are now managed on <code>imported-networking</code>, and nothing was recreated.</div></div>
    </div>

    The assistant always simulates and confirms before applying, so you see
    exactly what will happen first. Narrow the request however you like ("just
    the internet gateways", "the ones whose name starts with `webapp-`") or name
    the target stack yourself.
  </Tab>
</Tabs>

## See also

* [Discovery](/documentation/concepts/discovery): how formae finds unmanaged resources.
* [Resources](/documentation/concepts/resources): managed versus unmanaged.
* [Apply modes](/documentation/concepts/apply-modes): what reconcile does when you apply.
