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

# listFilesWithMetadata()

> List all files in the repository at a specific ref, with per-file git metadata.

<CodeGroup>
  ```typescript TypeScript theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  // List files with metadata from the default branch
  const metadata = await repo.listFilesWithMetadata();
  console.log(metadata.files[0].lastCommitSha);
  console.log(metadata.commits[metadata.files[0].lastCommitSha].author);

  // List files with metadata from a specific branch or commit
  const branchMetadata = await repo.listFilesWithMetadata({
    ref: 'feature-branch', // branch name or commit SHA
  });
  console.log(`Files in ${branchMetadata.ref}:`, branchMetadata.files.length);

  // List files from the ephemeral namespace
  const ephemeralMetadata = await repo.listFilesWithMetadata({
    ref: 'feature/demo-work',
    ephemeral: true,
  });
  console.log(`Ephemeral files:`, ephemeralMetadata.files.length);

  const page = await repo.listFilesWithMetadata({
    path: 'src',
    limit: 100,
  });
  console.log(page.files[0].type, page.nextCursor);
  ```

  ```python Python theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  # List files with metadata from the default branch
  metadata = await repo.list_files_with_metadata()
  print(metadata["files"][0]["last_commit_sha"])
  print(metadata["commits"][metadata["files"][0]["last_commit_sha"]]["author"])

  # List files with metadata from a specific branch or commit
  branch_metadata = await repo.list_files_with_metadata(ref="feature-branch")
  print(f"Files in {branch_metadata['ref']}:", len(branch_metadata["files"]))

  # List files from the ephemeral namespace
  ephemeral_metadata = await repo.list_files_with_metadata(
      ref="feature/demo-work",
      ephemeral=True,
  )
  print("Ephemeral files:", len(ephemeral_metadata["files"]))

  page = await repo.list_files_with_metadata(
      path="src",
      limit=100,
  )
  print(page["files"][0].get("type"), page.get("next_cursor"))
  ```

  ```go Go theme={null} theme={"theme":{"light":"github-light","dark":"min-dark"}}
  // List files with metadata from the default branch
  metadata, err := repo.ListFilesWithMetadata(context.Background(), storage.ListFilesWithMetadataOptions{
  	Ref: "main",
  })
  fmt.Println(metadata.Files[0].LastCommitSHA)
  fmt.Println(metadata.Commits[metadata.Files[0].LastCommitSHA].Author)

  ephemeral := true
  // List files from the ephemeral namespace
  ephemeralMetadata, err := repo.ListFilesWithMetadata(context.Background(), storage.ListFilesWithMetadataOptions{
  	Ref:       "feature/demo-work",
  	Ephemeral: &ephemeral,
  })
  fmt.Println("Ephemeral files:", len(ephemeralMetadata.Files))

  page, err := repo.ListFilesWithMetadata(context.Background(), storage.ListFilesWithMetadataOptions{
  	Path:  "src",
  	Limit: 100,
  })
  fmt.Println(page.Files[0].Type, page.NextCursor)
  ```
</CodeGroup>

## Options

<ParamField path="ref" type="string">
  Branch name or commit SHA. Defaults to the default branch.
</ParamField>

<ParamField path="ephemeral" type="boolean">
  When `true`, resolves the ref under the ephemeral namespace.
</ParamField>

<ParamField path="path" type="string">
  Repository-relative file or subtree to list. An exact file path returns one metadata entry.
</ParamField>

<ParamField path="recursive" type="boolean">
  Accepted for symmetry with `listFiles`; metadata listings are always recursive.
</ParamField>

<ParamField path="cursor" type="string">
  Pagination cursor from a previous response.
</ParamField>

<ParamField path="limit" type="number">
  Maximum files to return.
</ParamField>

<ParamField path="ttl" type="number">
  Time-to-live in seconds for the JWT used in the request.
</ParamField>

## Response

<ResponseField name="files" type="array">
  One entry per file in the tree at the resolved ref.

  <Expandable title="file fields">
    <ResponseField name="files[].path" type="string">
      File path relative to the repository root.
    </ResponseField>

    <ResponseField name="files[].mode" type="string">
      Git file mode (e.g. `100644` for a regular file, `100755` for executable).
    </ResponseField>

    <ResponseField name="files[].size" type="number">
      File size in bytes.
    </ResponseField>

    <ResponseField name="files[].lastCommitSha" type="string">
      SHA of the most recent commit that modified this file. Use this key to look up the corresponding entry in `commits`.
      **Python**: `last_commit_sha` — **Go**: `LastCommitSHA`
    </ResponseField>

    <ResponseField name="files[].type" type="string">
      Entry type when returned by the API: `blob`, `tree`, `symlink`, or `submodule`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="commits" type="object">
  A map of commit SHA → commit metadata. Each SHA referenced by `files[].lastCommitSha` has exactly one entry here. The map is deduplicated — if many files share the same last-touching commit, that commit appears once.

  <Expandable title="commit fields">
    <ResponseField name="commits[sha].author" type="string">
      Commit author name.
    </ResponseField>

    <ResponseField name="commits[sha].date" type="Date | datetime | time.Time">
      Parsed commit timestamp.
    </ResponseField>

    <ResponseField name="commits[sha].rawDate" type="string">
      RFC 3339 timestamp string as returned by the server. Python: `raw_date`; Go: `RawDate`.
    </ResponseField>

    <ResponseField name="commits[sha].message" type="string">
      Full commit message.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="ref" type="string">
  The ref the server resolved and used, regardless of what was passed in options.
</ResponseField>

<ResponseField name="nextCursor" type="string">
  Cursor for the next page. Python: `next_cursor`; Go: `NextCursor`.
</ResponseField>

<ResponseField name="hasMore" type="boolean">
  Whether additional pages are available. Python: `has_more`; Go: `HasMore`.
</ResponseField>
