# Attach custom metadata to files (/docs/filesystem/metadata)

<!-- agent-signals: reading_time_min: 2 · est_tokens: 1176 · updated: 2026-07-30 -->
Related: [Download data from sandbox](/docs/filesystem/download.md), [Get information about a file or directory](/docs/filesystem/info.md), [Read & write files](/docs/filesystem/read-write.md), [Upload data to sandbox](/docs/filesystem/upload.md), [Watch sandbox directory for changes](/docs/filesystem/watch.md)

You can attach custom key-value metadata to files when writing them to the sandbox using the `metadata` option.
The metadata is persisted with the file and returned by `files.getInfo()` / `files.get_info()`, `files.list()`, and `files.rename()`.

## Prerequisites [#prerequisites]

Custom file metadata requires templates with envd version `v0.6.2` or above. If you are using a custom template created before envd `v0.6.2`, you need to rebuild it.

You can check the template envd version using the `e2b template list` command or by viewing the templates list on the dashboard.

## Writing a file with metadata [#writing-a-file-with-metadata]

<CodeGroup>
  <CodeBlockTabs defaultValue="JavaScript & TypeScript" groupId="javascript-typescript+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="JavaScript & TypeScript">
        JavaScript & TypeScript
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="JavaScript & TypeScript">
      ```js  
      import { Sandbox } from 'e2b'

      const sandbox = await Sandbox.create()

      const info = await sandbox.files.write('report.txt', 'hello', {
        metadata: { author: 'alice', purpose: 'demo' },
      })
      console.log(info.metadata) // { author: 'alice', purpose: 'demo' }
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Python">
      ```python  
      from e2b import Sandbox

      sandbox = Sandbox.create()

      info = sandbox.files.write("report.txt", "hello", metadata={"author": "alice", "purpose": "demo"})
      print(info.metadata)  # {"author": "alice", "purpose": "demo"}
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

## Writing multiple files with metadata [#writing-multiple-files-with-metadata]

When writing multiple files, the same metadata is applied to every file in the upload.

<CodeGroup>
  <CodeBlockTabs defaultValue="JavaScript & TypeScript" groupId="javascript-typescript+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="JavaScript & TypeScript">
        JavaScript & TypeScript
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="JavaScript & TypeScript">
      ```js  
      import { Sandbox } from 'e2b'

      const sandbox = await Sandbox.create()

      await sandbox.files.writeFiles(
        [
          { path: 'a.txt', data: 'A' },
          { path: 'b.txt', data: 'B' },
        ],
        { metadata: { source: 'import' } }
      )
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Python">
      ```python  
      from e2b import Sandbox

      sandbox = Sandbox.create()

      sandbox.files.write_files(
          [
              { "path": "a.txt", "data": "A" },
              { "path": "b.txt", "data": "B" },
          ],
          metadata={"source": "import"},
      )
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

## Reading metadata back [#reading-metadata-back]

<CodeGroup>
  <CodeBlockTabs defaultValue="JavaScript & TypeScript" groupId="javascript-typescript+python">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="JavaScript & TypeScript">
        JavaScript & TypeScript
      </CodeBlockTabsTrigger>

      <CodeBlockTabsTrigger value="Python">
        Python
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="JavaScript & TypeScript">
      ```js  
      import { Sandbox } from 'e2b'

      const sandbox = await Sandbox.create()

      await sandbox.files.write('report.txt', 'hello', {
        metadata: { author: 'alice' },
      })

      const info = await sandbox.files.getInfo('report.txt')
      console.log(info.metadata) // { author: 'alice' }
      ```
    </CodeBlockTab>

    <CodeBlockTab value="Python">
      ```python  
      from e2b import Sandbox

      sandbox = Sandbox.create()

      sandbox.files.write("report.txt", "hello", metadata={"author": "alice"})

      info = sandbox.files.get_info("report.txt")
      print(info.metadata)  # {"author": "alice"}
      ```
    </CodeBlockTab>
  </CodeBlockTabs>
</CodeGroup>

## Limitations [#limitations]

* Metadata keys and values must be printable US-ASCII characters.
* Keys are lowercased by the sandbox, so they may differ in case when read back.
* Overwriting a file replaces its metadata — metadata from the previous write is not preserved.
* Metadata is stored as `user.e2b.*` extended attributes on the file inside the sandbox, so you can also read or set it from within the sandbox using standard tools like `getfattr` and `setfattr`.
