# `Codex.Plugins`
[🔗](https://github.com/nshkrdotcom/codex_sdk/blob/v0.16.1/lib/codex/plugins.ex#L1)

Local plugin authoring helpers for manifests, marketplaces, and scaffold flows.

This namespace is intentionally separate from the app-server runtime APIs on
`Codex.AppServer`. Use `Codex.Plugins.*` to author files locally with normal
Elixir file IO. Use `Codex.AppServer.plugin_*` only when you want runtime
discovery, read, install, or uninstall verification against a running Codex
app-server.

# `scaffold_error`

```elixir
@type scaffold_error() ::
  {:plugin_io, %{action: atom(), path: String.t(), reason: term()}}
  | {:invalid_plugin_json,
     %{path: String.t(), reason: String.t(), raw_reason: term()}}
  | {:plugin_file_exists, %{path: String.t()}}
  | {:repo_root_not_found, %{cwd: String.t()}}
  | {:invalid_plugin_scope, %{scope: term()}}
  | {:invalid_plugin_name, %{name: term(), message: String.t()}}
  | {:invalid_plugin_root, %{path: String.t(), message: String.t()}}
  | {:invalid_marketplace_path, %{path: String.t(), message: String.t()}}
  | {:invalid_marketplace_source_path,
     %{path: String.t(), source_path: String.t(), message: String.t()}}
  | {:plugin_conflict, %{path: String.t(), plugin_name: String.t()}}
  | {:invalid_plugin_manifest, CliSubprocessCore.Schema.error_detail()}
  | {:invalid_plugin_marketplace, CliSubprocessCore.Schema.error_detail()}
  | {:invalid_plugin_marketplace_plugin,
     CliSubprocessCore.Schema.error_detail()}
```

# `scaffold_result`

```elixir
@type scaffold_result() :: %{
  scope: Codex.Plugins.Paths.scope(),
  plugin_name: String.t(),
  plugin_root: String.t(),
  manifest_path: String.t(),
  manifest: Codex.Plugins.Manifest.t(),
  skill_paths: [String.t()],
  marketplace_path: String.t() | nil,
  marketplace: Codex.Plugins.Marketplace.t() | nil,
  created_paths: [String.t()]
}
```

# `add_marketplace_plugin`

```elixir
@spec add_marketplace_plugin(Path.t(), map() | keyword(), keyword()) ::
  {:ok, map()} | {:error, term()}
```

Safely appends or replaces one marketplace entry without erasing unrelated entries.

# `new_manifest`

```elixir
@spec new_manifest(map() | keyword() | Codex.Plugins.Manifest.t()) ::
  {:ok, Codex.Plugins.Manifest.t()} | {:error, term()}
```

Builds and validates a manifest struct.

# `new_marketplace`

```elixir
@spec new_marketplace(map() | keyword() | Codex.Plugins.Marketplace.t()) ::
  {:ok, Codex.Plugins.Marketplace.t()} | {:error, term()}
```

Builds and validates a marketplace struct.

# `read_manifest`

```elixir
@spec read_manifest(Path.t()) :: {:ok, Codex.Plugins.Manifest.t()} | {:error, term()}
```

Reads and validates a local plugin manifest.

# `read_marketplace`

```elixir
@spec read_marketplace(Path.t()) ::
  {:ok, Codex.Plugins.Marketplace.t()} | {:error, term()}
```

Reads and validates a local marketplace file.

# `scaffold`

```elixir
@spec scaffold(keyword()) :: {:ok, scaffold_result()} | {:error, scaffold_error()}
```

Scaffolds a minimal local plugin tree.

# `validate_manifest`

```elixir
@spec validate_manifest(map() | keyword() | Codex.Plugins.Manifest.t()) ::
  :ok | {:error, [map()]}
```

Validates manifest data and returns normalized issues on failure.

# `validate_marketplace`

```elixir
@spec validate_marketplace(map() | keyword() | Codex.Plugins.Marketplace.t()) ::
  :ok | {:error, [map()]}
```

Validates marketplace data and returns normalized issues on failure.

# `write_manifest`

```elixir
@spec write_manifest(
  Path.t(),
  map() | keyword() | Codex.Plugins.Manifest.t(),
  keyword()
) ::
  :ok | {:error, term()}
```

Writes a manifest deterministically using local file IO.

# `write_marketplace`

```elixir
@spec write_marketplace(
  Path.t(),
  map() | keyword() | Codex.Plugins.Marketplace.t(),
  keyword()
) ::
  :ok | {:error, term()}
```

Writes a marketplace deterministically using local file IO.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
