diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json
index 9934e36940c9..16a4e7baa413 100644
--- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json
+++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json
@@ -12289,6 +12289,14 @@
           "remotePluginId": {
             "type": "string"
           },
+          "remoteVersion": {
+            "default": null,
+            "description": "Version of the remote shared plugin release when available.",
+            "type": [
+              "string",
+              "null"
+            ]
+          },
           "sharePrincipals": {
             "items": {
               "$ref": "#/definitions/v2/PluginSharePrincipal"
@@ -12705,6 +12713,14 @@
             },
             "type": "array"
           },
+          "localVersion": {
+            "default": null,
+            "description": "Version of the locally materialized plugin package when available.",
+            "type": [
+              "string",
+              "null"
+            ]
+          },
           "name": {
             "type": "string"
           },
diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json
index 1926b22091b6..06b19a0af8dc 100644
--- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json
+++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json
@@ -8838,6 +8838,14 @@
         "remotePluginId": {
           "type": "string"
         },
+        "remoteVersion": {
+          "default": null,
+          "description": "Version of the remote shared plugin release when available.",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "sharePrincipals": {
           "items": {
             "$ref": "#/definitions/PluginSharePrincipal"
@@ -9254,6 +9262,14 @@
           },
           "type": "array"
         },
+        "localVersion": {
+          "default": null,
+          "description": "Version of the locally materialized plugin package when available.",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "name": {
           "type": "string"
         },
diff --git a/codex-rs/app-server-protocol/schema/json/v2/PluginListResponse.json b/codex-rs/app-server-protocol/schema/json/v2/PluginListResponse.json
index 72b1f7c9aae8..d756f61a6847 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/PluginListResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/PluginListResponse.json
@@ -259,6 +259,14 @@
         "remotePluginId": {
           "type": "string"
         },
+        "remoteVersion": {
+          "default": null,
+          "description": "Version of the remote shared plugin release when available.",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "sharePrincipals": {
           "items": {
             "$ref": "#/definitions/PluginSharePrincipal"
@@ -449,6 +457,14 @@
           },
           "type": "array"
         },
+        "localVersion": {
+          "default": null,
+          "description": "Version of the locally materialized plugin package when available.",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "name": {
           "type": "string"
         },
diff --git a/codex-rs/app-server-protocol/schema/json/v2/PluginReadResponse.json b/codex-rs/app-server-protocol/schema/json/v2/PluginReadResponse.json
index 945b4897cb74..0c9f897dc9f8 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/PluginReadResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/PluginReadResponse.json
@@ -313,6 +313,14 @@
         "remotePluginId": {
           "type": "string"
         },
+        "remoteVersion": {
+          "default": null,
+          "description": "Version of the remote shared plugin release when available.",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "sharePrincipals": {
           "items": {
             "$ref": "#/definitions/PluginSharePrincipal"
@@ -503,6 +511,14 @@
           },
           "type": "array"
         },
+        "localVersion": {
+          "default": null,
+          "description": "Version of the locally materialized plugin package when available.",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "name": {
           "type": "string"
         },
diff --git a/codex-rs/app-server-protocol/schema/json/v2/PluginShareListResponse.json b/codex-rs/app-server-protocol/schema/json/v2/PluginShareListResponse.json
index ed2beacada13..7cffdeab9aac 100644
--- a/codex-rs/app-server-protocol/schema/json/v2/PluginShareListResponse.json
+++ b/codex-rs/app-server-protocol/schema/json/v2/PluginShareListResponse.json
@@ -194,6 +194,14 @@
         "remotePluginId": {
           "type": "string"
         },
+        "remoteVersion": {
+          "default": null,
+          "description": "Version of the remote shared plugin release when available.",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "sharePrincipals": {
           "items": {
             "$ref": "#/definitions/PluginSharePrincipal"
@@ -405,6 +413,14 @@
           },
           "type": "array"
         },
+        "localVersion": {
+          "default": null,
+          "description": "Version of the locally materialized plugin package when available.",
+          "type": [
+            "string",
+            "null"
+          ]
+        },
         "name": {
           "type": "string"
         },
diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareContext.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareContext.ts
index 86d610bf5acb..99b8f46601af 100644
--- a/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareContext.ts
+++ b/codex-rs/app-server-protocol/schema/typescript/v2/PluginShareContext.ts
@@ -4,4 +4,8 @@
 import type { PluginShareDiscoverability } from "./PluginShareDiscoverability";
 import type { PluginSharePrincipal } from "./PluginSharePrincipal";
 
-export type PluginShareContext = { remotePluginId: string, discoverability: PluginShareDiscoverability | null, shareUrl: string | null, creatorAccountUserId: string | null, creatorName: string | null, sharePrincipals: Array<PluginSharePrincipal> | null, };
+export type PluginShareContext = { remotePluginId: string,
+/**
+ * Version of the remote shared plugin release when available.
+ */
+remoteVersion: string | null, discoverability: PluginShareDiscoverability | null, shareUrl: string | null, creatorAccountUserId: string | null, creatorName: string | null, sharePrincipals: Array<PluginSharePrincipal> | null, };
diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/PluginSummary.ts b/codex-rs/app-server-protocol/schema/typescript/v2/PluginSummary.ts
index 8fae7ae86507..268349cb9b81 100644
--- a/codex-rs/app-server-protocol/schema/typescript/v2/PluginSummary.ts
+++ b/codex-rs/app-server-protocol/schema/typescript/v2/PluginSummary.ts
@@ -12,7 +12,11 @@ export type PluginSummary = { id: string,
 /**
  * Backend remote plugin identifier when available.
  */
-remotePluginId: string | null, name: string,
+remotePluginId: string | null,
+/**
+ * Version of the locally materialized plugin package when available.
+ */
+localVersion: string | null, name: string,
 /**
  * Remote sharing context associated with this plugin when available.
  */
diff --git a/codex-rs/app-server-protocol/src/protocol/v2/plugin.rs b/codex-rs/app-server-protocol/src/protocol/v2/plugin.rs
index 82568446b79e..2349e8bc21f6 100644
--- a/codex-rs/app-server-protocol/src/protocol/v2/plugin.rs
+++ b/codex-rs/app-server-protocol/src/protocol/v2/plugin.rs
@@ -540,6 +540,9 @@ pub struct PluginSummary {
     pub id: String,
     /// Backend remote plugin identifier when available.
     pub remote_plugin_id: Option<String>,
+    /// Version of the locally materialized plugin package when available.
+    #[serde(default)]
+    pub local_version: Option<String>,
     pub name: String,
     /// Remote sharing context associated with this plugin when available.
     pub share_context: Option<PluginShareContext>,
@@ -561,6 +564,9 @@ pub struct PluginSummary {
 #[ts(export_to = "v2/")]
 pub struct PluginShareContext {
     pub remote_plugin_id: String,
+    /// Version of the remote shared plugin release when available.
+    #[serde(default)]
+    pub remote_version: Option<String>,
     pub discoverability: Option<PluginShareDiscoverability>,
     pub share_url: Option<String>,
     pub creator_account_user_id: Option<String>,
diff --git a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs
index 73b22cecb473..26cd2b005721 100644
--- a/codex-rs/app-server-protocol/src/protocol/v2/tests.rs
+++ b/codex-rs/app-server-protocol/src/protocol/v2/tests.rs
@@ -3007,6 +3007,7 @@ fn plugin_share_list_response_serializes_share_items() {
                     remote_plugin_id: Some(
                         "plugins~Plugin_00000000000000000000000000000000".to_string(),
                     ),
+                    local_version: None,
                     name: "gmail".to_string(),
                     share_context: None,
                     source: PluginSource::Remote,
@@ -3027,6 +3028,7 @@ fn plugin_share_list_response_serializes_share_items() {
                 "plugin": {
                     "id": "gmail@chatgpt-global",
                     "remotePluginId": "plugins~Plugin_00000000000000000000000000000000",
+                    "localVersion": null,
                     "name": "gmail",
                     "shareContext": null,
                     "source": { "type": "remote" },
@@ -3059,6 +3061,7 @@ fn plugin_summary_defaults_missing_availability_to_available() {
     .unwrap();
 
     assert_eq!(summary.availability, PluginAvailability::Available);
+    assert_eq!(summary.local_version, None);
     assert_eq!(summary.share_context, None);
 }
 
diff --git a/codex-rs/app-server/src/request_processors/plugins.rs b/codex-rs/app-server/src/request_processors/plugins.rs
index 125accad8215..61336aa713b8 100644
--- a/codex-rs/app-server/src/request_processors/plugins.rs
+++ b/codex-rs/app-server/src/request_processors/plugins.rs
@@ -111,6 +111,7 @@ fn share_context_for_source(
             .cloned()
             .map(|remote_plugin_id| PluginShareContext {
                 remote_plugin_id,
+                remote_version: None,
                 discoverability: None,
                 share_url: None,
                 creator_account_user_id: None,
@@ -483,6 +484,7 @@ impl PluginRequestProcessor {
                                     PluginSummary {
                                         id: plugin.id,
                                         remote_plugin_id: None,
+                                        local_version: plugin.local_version,
                                         installed: plugin.installed,
                                         enabled: plugin.enabled,
                                         name: plugin.name,
@@ -533,7 +535,9 @@ impl PluginRequestProcessor {
         if marketplace_kinds.contains(&PluginListMarketplaceKind::WorkspaceDirectory) {
             remote_sources.push(RemoteMarketplaceSource::WorkspaceDirectory);
         }
-        if marketplace_kinds.contains(&PluginListMarketplaceKind::SharedWithMe) {
+        if marketplace_kinds.contains(&PluginListMarketplaceKind::SharedWithMe)
+            && config.features.enabled(Feature::PluginSharing)
+        {
             remote_sources.push(RemoteMarketplaceSource::SharedWithMe);
         }
         if !remote_sources.is_empty() {
@@ -673,17 +677,21 @@ impl PluginRequestProcessor {
                         )
                         .await
                         {
-                            Ok(Some(remote_share_context))
-                                if remote_share_context.share_principals.is_some() =>
-                            {
-                                Some(remote_plugin_share_context_to_info(remote_share_context))
-                            }
-                            Ok(Some(_)) => {
-                                warn!(
-                                    remote_plugin_id = %context.remote_plugin_id,
-                                    "remote shared plugin detail did not include share principals; returning local share mapping context"
-                                );
-                                Some(context)
+                            Ok(Some(remote_share_context)) => {
+                                if remote_share_context.share_principals.is_some() {
+                                    Some(remote_plugin_share_context_to_info(remote_share_context))
+                                } else {
+                                    let remote_version = remote_share_context.remote_version;
+                                    let remote_plugin_id = context.remote_plugin_id.clone();
+                                    warn!(
+                                        remote_plugin_id = %remote_plugin_id,
+                                        "remote shared plugin detail did not include share principals; returning local share mapping context with remote version"
+                                    );
+                                    Some(PluginShareContext {
+                                        remote_version,
+                                        ..context
+                                    })
+                                }
                             }
                             Ok(None) => {
                                 warn!(
@@ -725,6 +733,7 @@ impl PluginRequestProcessor {
                     summary: PluginSummary {
                         id: outcome.plugin.id,
                         remote_plugin_id: None,
+                        local_version: outcome.plugin.local_version,
                         name: outcome.plugin.name,
                         share_context,
                         source: marketplace_plugin_source_to_info(outcome.plugin.source),
@@ -840,6 +849,9 @@ impl PluginRequestProcessor {
         params: PluginShareSaveParams,
     ) -> Result<PluginShareSaveResponse, JSONRPCErrorError> {
         let (config, auth) = self.load_plugin_share_config_and_auth().await?;
+        if !config.features.enabled(Feature::PluginSharing) {
+            return Err(invalid_request("plugin sharing is disabled"));
+        }
         let PluginShareSaveParams {
             plugin_path,
             remote_plugin_id,
@@ -1589,6 +1601,7 @@ fn remote_plugin_summary_to_info(summary: RemoteCatalogPluginSummary) -> PluginS
     PluginSummary {
         id: summary.id,
         remote_plugin_id: Some(summary.remote_plugin_id),
+        local_version: None,
         name: summary.name,
         share_context: summary
             .share_context
@@ -1609,6 +1622,7 @@ fn remote_plugin_share_context_to_info(
 ) -> PluginShareContext {
     PluginShareContext {
         remote_plugin_id: context.remote_plugin_id,
+        remote_version: context.remote_version,
         discoverability: Some(remote_plugin_share_discoverability_to_info(
             context.discoverability,
         )),
diff --git a/codex-rs/app-server/tests/suite/v2/plugin_list.rs b/codex-rs/app-server/tests/suite/v2/plugin_list.rs
index 6576ba87b982..6bcefbb58824 100644
--- a/codex-rs/app-server/tests/suite/v2/plugin_list.rs
+++ b/codex-rs/app-server/tests/suite/v2/plugin_list.rs
@@ -241,6 +241,7 @@ async fn plugin_list_keeps_valid_marketplaces_when_another_marketplace_fails_to_
             plugins: vec![PluginSummary {
                 id: "valid-plugin@valid-marketplace".to_string(),
                 remote_plugin_id: None,
+                local_version: None,
                 name: "valid-plugin".to_string(),
                 share_context: None,
                 source: PluginSource::Local {
@@ -531,6 +532,7 @@ async fn plugin_list_uses_alternate_discoverable_manifest_and_keeps_undiscoverab
                 PluginSummary {
                     id: "valid-plugin@alternate-marketplace".to_string(),
                     remote_plugin_id: None,
+                    local_version: None,
                     name: "valid-plugin".to_string(),
                     share_context: None,
                     source: PluginSource::Local {
@@ -565,6 +567,7 @@ async fn plugin_list_uses_alternate_discoverable_manifest_and_keeps_undiscoverab
                 PluginSummary {
                     id: "missing-plugin@alternate-marketplace".to_string(),
                     remote_plugin_id: None,
+                    local_version: None,
                     name: "missing-plugin".to_string(),
                     share_context: None,
                     source: PluginSource::Local {
@@ -660,7 +663,7 @@ async fn plugin_list_returns_share_context_for_shared_local_plugin() -> Result<(
     )?;
     std::fs::write(
         plugin_root.join(".codex-plugin/plugin.json"),
-        r#"{"name":"demo-plugin"}"#,
+        r#"{"name":"demo-plugin","version":"1.2.3"}"#,
     )?;
     write_plugin_share_local_path_mapping(
         codex_home.path(),
@@ -692,11 +695,13 @@ async fn plugin_list_returns_share_context_for_shared_local_plugin() -> Result<(
         .find(|plugin| plugin.name == "demo-plugin")
         .expect("expected demo-plugin entry");
     assert_eq!(plugin.remote_plugin_id, None);
+    assert_eq!(plugin.local_version.as_deref(), Some("1.2.3"));
     let share_context = plugin
         .share_context
         .as_ref()
         .expect("expected share context");
     assert_eq!(share_context.remote_plugin_id, "plugins_123");
+    assert_eq!(share_context.remote_version, None);
     assert_eq!(share_context.discoverability, None);
     assert_eq!(share_context.share_url, None);
     assert_eq!(share_context.creator_account_user_id, None);
@@ -1873,6 +1878,7 @@ async fn plugin_list_fetches_shared_with_me_kind() -> Result<()> {
         share_context.remote_plugin_id,
         "plugins~Plugin_22222222222222222222222222222222"
     );
+    assert_eq!(share_context.remote_version.as_deref(), Some("1.2.3"));
     assert_eq!(
         share_context.discoverability,
         Some(PluginShareDiscoverability::Private)
@@ -1891,6 +1897,65 @@ async fn plugin_list_fetches_shared_with_me_kind() -> Result<()> {
     Ok(())
 }
 
+#[tokio::test]
+async fn plugin_list_omits_shared_with_me_kind_when_plugin_sharing_disabled() -> Result<()> {
+    let codex_home = TempDir::new()?;
+    let server = MockServer::start().await;
+    std::fs::write(
+        codex_home.path().join("config.toml"),
+        format!(
+            r#"chatgpt_base_url = "{}/backend-api/"
+
+[features]
+plugins = true
+plugin_sharing = false
+"#,
+            server.uri()
+        ),
+    )?;
+    write_chatgpt_auth(
+        codex_home.path(),
+        ChatGptAuthFixture::new("chatgpt-token")
+            .account_id("account-123")
+            .chatgpt_user_id("user-123")
+            .chatgpt_account_id("account-123"),
+        AuthCredentialsStoreMode::File,
+    )?;
+
+    let mut mcp = McpProcess::new(codex_home.path()).await?;
+    timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
+
+    let request_id = mcp
+        .send_plugin_list_request(PluginListParams {
+            cwds: None,
+            marketplace_kinds: Some(vec![PluginListMarketplaceKind::SharedWithMe]),
+        })
+        .await?;
+
+    let response: JSONRPCResponse = timeout(
+        DEFAULT_TIMEOUT,
+        mcp.read_stream_until_response_message(RequestId::Integer(request_id)),
+    )
+    .await??;
+    let response: PluginListResponse = to_response(response)?;
+
+    assert_eq!(
+        response,
+        PluginListResponse {
+            marketplaces: Vec::new(),
+            marketplace_load_errors: Vec::new(),
+            featured_plugin_ids: Vec::new(),
+        }
+    );
+    wait_for_remote_plugin_request_count(
+        &server,
+        "/ps/plugins/workspace/shared",
+        /*expected_count*/ 0,
+    )
+    .await?;
+    Ok(())
+}
+
 #[tokio::test]
 async fn plugin_list_marks_remote_plugin_disabled_by_admin() -> Result<()> {
     let codex_home = TempDir::new()?;
@@ -2434,6 +2499,7 @@ fn workspace_remote_plugin_page_body(
         }}
       ],
       "release": {{
+        "version": "1.2.3",
         "display_name": "{display_name}",
         "description": "Track work",
         "app_ids": [],
diff --git a/codex-rs/app-server/tests/suite/v2/plugin_read.rs b/codex-rs/app-server/tests/suite/v2/plugin_read.rs
index 62294b2f9539..7c93ac5d8adf 100644
--- a/codex-rs/app-server/tests/suite/v2/plugin_read.rs
+++ b/codex-rs/app-server/tests/suite/v2/plugin_read.rs
@@ -262,6 +262,7 @@ async fn plugin_read_returns_share_context_for_shared_remote_plugin() -> Result<
   "installation_policy": "AVAILABLE",
   "authentication_policy": "ON_USE",
   "release": {
+    "version": "2.3.4",
     "display_name": "Shared Linear",
     "description": "Track shared work",
     "app_ids": [],
@@ -330,6 +331,7 @@ async fn plugin_read_returns_share_context_for_shared_remote_plugin() -> Result<
         share_context.remote_plugin_id,
         "plugins~Plugin_11111111111111111111111111111111"
     );
+    assert_eq!(share_context.remote_version.as_deref(), Some("2.3.4"));
     assert_eq!(
         share_context.discoverability,
         Some(PluginShareDiscoverability::Private)
@@ -800,7 +802,7 @@ async fn plugin_read_returns_share_context_for_shared_local_plugin() -> Result<(
         repo_root
             .path()
             .join("demo-plugin/.codex-plugin/plugin.json"),
-        r#"{"name":"demo-plugin"}"#,
+        r#"{"name":"demo-plugin","version":"1.2.3"}"#,
     )?;
     let plugin_path = AbsolutePathBuf::try_from(repo_root.path().join("demo-plugin"))?;
     write_plugin_share_local_path_mapping(codex_home.path(), "plugins_123", &plugin_path)?;
@@ -833,6 +835,7 @@ async fn plugin_read_returns_share_context_for_shared_local_plugin() -> Result<(
             "installation_policy": "AVAILABLE",
             "authentication_policy": "ON_USE",
             "release": {
+                "version": "1.2.4",
                 "display_name": "Demo Plugin",
                 "description": "Shared local plugin",
                 "app_ids": [],
@@ -865,6 +868,10 @@ async fn plugin_read_returns_share_context_for_shared_local_plugin() -> Result<(
     let response: PluginReadResponse = to_response(response)?;
 
     assert_eq!(response.plugin.summary.remote_plugin_id, None);
+    assert_eq!(
+        response.plugin.summary.local_version.as_deref(),
+        Some("1.2.3")
+    );
     let share_context = response
         .plugin
         .summary
@@ -872,6 +879,7 @@ async fn plugin_read_returns_share_context_for_shared_local_plugin() -> Result<(
         .as_ref()
         .expect("expected share context");
     assert_eq!(share_context.remote_plugin_id, "plugins_123");
+    assert_eq!(share_context.remote_version.as_deref(), Some("1.2.4"));
     assert_eq!(
         share_context.discoverability,
         Some(PluginShareDiscoverability::Unlisted)
@@ -905,6 +913,107 @@ async fn plugin_read_returns_share_context_for_shared_local_plugin() -> Result<(
     Ok(())
 }
 
+#[tokio::test]
+async fn plugin_read_keeps_remote_version_when_share_principals_are_missing() -> Result<()> {
+    let codex_home = TempDir::new()?;
+    let repo_root = TempDir::new()?;
+    let server = MockServer::start().await;
+    write_remote_plugin_catalog_config(
+        codex_home.path(),
+        &format!("{}/backend-api/", server.uri()),
+    )?;
+    write_chatgpt_auth(
+        codex_home.path(),
+        ChatGptAuthFixture::new("chatgpt-token")
+            .account_id("account-123")
+            .chatgpt_user_id("user-123")
+            .chatgpt_account_id("account-123"),
+        AuthCredentialsStoreMode::File,
+    )?;
+    write_plugin_marketplace(
+        repo_root.path(),
+        "codex-curated",
+        "demo-plugin",
+        "./demo-plugin",
+    )?;
+    std::fs::create_dir_all(repo_root.path().join("demo-plugin/.codex-plugin"))?;
+    std::fs::write(
+        repo_root
+            .path()
+            .join("demo-plugin/.codex-plugin/plugin.json"),
+        r#"{"name":"demo-plugin","version":"1.2.3"}"#,
+    )?;
+    let plugin_path = AbsolutePathBuf::try_from(repo_root.path().join("demo-plugin"))?;
+    write_plugin_share_local_path_mapping(codex_home.path(), "plugins_123", &plugin_path)?;
+    Mock::given(method("GET"))
+        .and(path("/backend-api/ps/plugins/plugins_123"))
+        .and(header("authorization", "Bearer chatgpt-token"))
+        .and(header("chatgpt-account-id", "account-123"))
+        .respond_with(ResponseTemplate::new(200).set_body_json(json!({
+            "id": "plugins_123",
+            "name": "demo-plugin",
+            "scope": "WORKSPACE",
+            "discoverability": "UNLISTED",
+            "creator_account_user_id": "user-owner__account-123",
+            "creator_name": "Owner",
+            "share_url": "https://chatgpt.example/plugins/share/share-key-1",
+            "share_principals": null,
+            "installation_policy": "AVAILABLE",
+            "authentication_policy": "ON_USE",
+            "release": {
+                "version": "1.2.4",
+                "display_name": "Demo Plugin",
+                "description": "Shared local plugin",
+                "app_ids": [],
+                "keywords": [],
+                "interface": {},
+                "skills": []
+            }
+        })))
+        .expect(1)
+        .mount(&server)
+        .await;
+    let mut mcp = McpProcess::new(codex_home.path()).await?;
+    timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
+
+    let request_id = mcp
+        .send_plugin_read_request(PluginReadParams {
+            marketplace_path: Some(AbsolutePathBuf::try_from(
+                repo_root.path().join(".agents/plugins/marketplace.json"),
+            )?),
+            remote_marketplace_name: None,
+            plugin_name: "demo-plugin".to_string(),
+        })
+        .await?;
+
+    let response: JSONRPCResponse = timeout(
+        DEFAULT_TIMEOUT,
+        mcp.read_stream_until_response_message(RequestId::Integer(request_id)),
+    )
+    .await??;
+    let response: PluginReadResponse = to_response(response)?;
+
+    assert_eq!(response.plugin.summary.remote_plugin_id, None);
+    assert_eq!(
+        response.plugin.summary.local_version.as_deref(),
+        Some("1.2.3")
+    );
+    let share_context = response
+        .plugin
+        .summary
+        .share_context
+        .as_ref()
+        .expect("expected share context");
+    assert_eq!(share_context.remote_plugin_id, "plugins_123");
+    assert_eq!(share_context.remote_version.as_deref(), Some("1.2.4"));
+    assert_eq!(share_context.discoverability, None);
+    assert_eq!(share_context.share_url, None);
+    assert_eq!(share_context.creator_account_user_id, None);
+    assert_eq!(share_context.creator_name, None);
+    assert_eq!(share_context.share_principals, None);
+    Ok(())
+}
+
 #[tokio::test]
 async fn plugin_read_falls_back_to_local_share_context_without_remote_auth() -> Result<()> {
     let codex_home = TempDir::new()?;
@@ -941,6 +1050,7 @@ async fn plugin_read_falls_back_to_local_share_context_without_remote_auth() ->
     let response: PluginReadResponse = to_response(response)?;
 
     assert_eq!(response.plugin.summary.remote_plugin_id, None);
+    assert_eq!(response.plugin.summary.local_version, None);
     let share_context = response
         .plugin
         .summary
@@ -948,6 +1058,7 @@ async fn plugin_read_falls_back_to_local_share_context_without_remote_auth() ->
         .as_ref()
         .expect("expected share context");
     assert_eq!(share_context.remote_plugin_id, "plugins_123");
+    assert_eq!(share_context.remote_version, None);
     assert_eq!(share_context.discoverability, None);
     assert_eq!(share_context.share_url, None);
     assert_eq!(share_context.creator_account_user_id, None);
diff --git a/codex-rs/app-server/tests/suite/v2/plugin_share.rs b/codex-rs/app-server/tests/suite/v2/plugin_share.rs
index 46f3dceb5e08..299c1eff253b 100644
--- a/codex-rs/app-server/tests/suite/v2/plugin_share.rs
+++ b/codex-rs/app-server/tests/suite/v2/plugin_share.rs
@@ -164,6 +164,7 @@ async fn plugin_share_save_uploads_local_plugin() -> Result<()> {
                 plugin: PluginSummary {
                     id: "demo-plugin@shared-with-me".to_string(),
                     remote_plugin_id: Some("plugins_123".to_string()),
+                    local_version: None,
                     name: "demo-plugin".to_string(),
                     share_context: Some(expected_share_context("plugins_123")),
                     source: PluginSource::Remote,
@@ -322,6 +323,64 @@ async fn plugin_share_save_rejects_listed_discoverability() -> Result<()> {
     Ok(())
 }
 
+#[tokio::test]
+async fn plugin_share_save_rejects_when_plugin_sharing_disabled() -> Result<()> {
+    let codex_home = TempDir::new()?;
+    let plugin_root = TempDir::new()?;
+    let plugin_path = write_test_plugin(plugin_root.path(), "demo-plugin")?;
+    let server = MockServer::start().await;
+    std::fs::write(
+        codex_home.path().join("config.toml"),
+        format!(
+            r#"
+chatgpt_base_url = "{}/backend-api"
+
+[features]
+plugins = true
+remote_plugin = true
+plugin_sharing = false
+"#,
+            server.uri()
+        ),
+    )?;
+    write_chatgpt_auth(
+        codex_home.path(),
+        ChatGptAuthFixture::new("chatgpt-token")
+            .account_id("account-123")
+            .chatgpt_user_id("user-123")
+            .chatgpt_account_id("account-123"),
+        AuthCredentialsStoreMode::File,
+    )?;
+
+    let mut mcp = McpProcess::new(codex_home.path()).await?;
+    timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
+    let request_id = mcp
+        .send_raw_request(
+            "plugin/share/save",
+            Some(json!({
+                "pluginPath": AbsolutePathBuf::try_from(plugin_path)?,
+            })),
+        )
+        .await?;
+
+    let error: JSONRPCError = timeout(
+        DEFAULT_TIMEOUT,
+        mcp.read_stream_until_error_message(RequestId::Integer(request_id)),
+    )
+    .await??;
+
+    assert_eq!(error.error.code, -32600);
+    assert_eq!(error.error.message, "plugin sharing is disabled");
+    assert!(
+        server
+            .received_requests()
+            .await
+            .expect("wiremock should record requests")
+            .is_empty()
+    );
+    Ok(())
+}
+
 #[tokio::test]
 async fn plugin_share_rejects_workspace_targets_from_client() -> Result<()> {
     let codex_home = TempDir::new()?;
@@ -509,6 +568,7 @@ async fn plugin_share_list_returns_created_workspace_plugins() -> Result<()> {
                 plugin: PluginSummary {
                     id: "demo-plugin@shared-with-me".to_string(),
                     remote_plugin_id: Some("plugins_123".to_string()),
+                    local_version: None,
                     name: "demo-plugin".to_string(),
                     share_context: Some(expected_share_context("plugins_123")),
                     source: PluginSource::Remote,
@@ -729,6 +789,7 @@ async fn plugin_share_delete_removes_created_workspace_plugin() -> Result<()> {
                 plugin: PluginSummary {
                     id: "demo-plugin@shared-with-me".to_string(),
                     remote_plugin_id: Some("plugins_123".to_string()),
+                    local_version: None,
                     name: "demo-plugin".to_string(),
                     share_context: Some(expected_share_context("plugins_123")),
                     source: PluginSource::Remote,
@@ -786,6 +847,7 @@ fn remote_plugin_json(plugin_id: &str) -> serde_json::Value {
         "installation_policy": "AVAILABLE",
         "authentication_policy": "ON_USE",
         "release": {
+            "version": "0.1.0",
             "display_name": "Demo Plugin",
             "description": "Demo plugin description",
             "interface": {
@@ -838,6 +900,7 @@ fn expected_plugin_interface() -> PluginInterface {
 fn expected_share_context(plugin_id: &str) -> PluginShareContext {
     PluginShareContext {
         remote_plugin_id: plugin_id.to_string(),
+        remote_version: Some("0.1.0".to_string()),
         discoverability: Some(PluginShareDiscoverability::Private),
         share_url: Some("https://chatgpt.example/plugins/share/share-key-1".to_string()),
         creator_account_user_id: None,
diff --git a/codex-rs/core-plugins/src/manager.rs b/codex-rs/core-plugins/src/manager.rs
index 42f5ac73db40..2df35b401f3b 100644
--- a/codex-rs/core-plugins/src/manager.rs
+++ b/codex-rs/core-plugins/src/manager.rs
@@ -222,6 +222,7 @@ pub struct PluginReadOutcome {
 pub struct PluginDetail {
     pub id: String,
     pub name: String,
+    pub local_version: Option<String>,
     pub description: Option<String>,
     pub source: MarketplacePluginSource,
     pub policy: MarketplacePluginPolicy,
@@ -260,6 +261,7 @@ pub struct ConfiguredMarketplace {
 pub struct ConfiguredMarketplacePlugin {
     pub id: String,
     pub name: String,
+    pub local_version: Option<String>,
     pub source: MarketplacePluginSource,
     pub policy: MarketplacePluginPolicy,
     pub interface: Option<PluginManifestInterface>,
@@ -1199,6 +1201,7 @@ impl PluginsManager {
                         let installed = installed_plugins.contains(&plugin_key);
                         let enabled = enabled_plugins.contains(&plugin_key);
                         let mut interface = plugin.interface;
+                        let mut local_version = plugin.local_version;
                         if installed
                             && matches!(&plugin.source, MarketplacePluginSource::Git { .. })
                             && let Ok(plugin_id) =
@@ -1206,6 +1209,7 @@ impl PluginsManager {
                             && let Some(plugin_root) = self.store.active_plugin_root(&plugin_id)
                             && let Some(manifest) = load_plugin_manifest(plugin_root.as_path())
                         {
+                            local_version = manifest.version.clone();
                             let marketplace_category = interface
                                 .as_ref()
                                 .and_then(|interface| interface.category.clone());
@@ -1223,6 +1227,7 @@ impl PluginsManager {
                             installed,
                             enabled,
                             name: plugin.name,
+                            local_version,
                             source: plugin.source,
                             policy: plugin.policy,
                             keywords: plugin.keywords,
@@ -1273,6 +1278,10 @@ impl PluginsManager {
                 ConfiguredMarketplacePlugin {
                     id: plugin_key.clone(),
                     name: plugin.plugin_id.plugin_name,
+                    local_version: plugin
+                        .manifest
+                        .as_ref()
+                        .and_then(|manifest| manifest.version.clone()),
                     source: plugin.source,
                     policy: plugin.policy,
                     interface: plugin.interface,
@@ -1319,6 +1328,7 @@ impl PluginsManager {
             return Ok(PluginDetail {
                 id: plugin_key,
                 name: plugin.name,
+                local_version: None,
                 description: Some(description),
                 source: plugin.source,
                 policy: plugin.policy,
@@ -1411,6 +1421,7 @@ impl PluginsManager {
         Ok(PluginDetail {
             id: plugin.id,
             name: plugin.name,
+            local_version: manifest.version.clone(),
             description,
             source: plugin.source,
             policy: plugin.policy,
diff --git a/codex-rs/core-plugins/src/manager_tests.rs b/codex-rs/core-plugins/src/manager_tests.rs
index e1c0f1b12156..d04852ea1317 100644
--- a/codex-rs/core-plugins/src/manager_tests.rs
+++ b/codex-rs/core-plugins/src/manager_tests.rs
@@ -1541,6 +1541,7 @@ enabled = false
                 ConfiguredMarketplacePlugin {
                     id: "enabled-plugin@debug".to_string(),
                     name: "enabled-plugin".to_string(),
+                    local_version: None,
                     source: MarketplacePluginSource::Local {
                         path: AbsolutePathBuf::try_from(tmp.path().join("repo/enabled-plugin"))
                             .unwrap(),
@@ -1558,6 +1559,7 @@ enabled = false
                 ConfiguredMarketplacePlugin {
                     id: "disabled-plugin@debug".to_string(),
                     name: "disabled-plugin".to_string(),
+                    local_version: None,
                     source: MarketplacePluginSource::Local {
                         path: AbsolutePathBuf::try_from(tmp.path().join("repo/disabled-plugin"),)
                             .unwrap(),
@@ -1678,6 +1680,7 @@ plugins = true
         vec![ConfiguredMarketplacePlugin {
             id: "default-plugin@debug".to_string(),
             name: "default-plugin".to_string(),
+            local_version: None,
             source: MarketplacePluginSource::Local {
                 path: AbsolutePathBuf::try_from(tmp.path().join("repo/default-plugin")).unwrap(),
             },
@@ -2109,6 +2112,7 @@ enabled = true
         vec![ConfiguredMarketplacePlugin {
             id: "toolkit@debug".to_string(),
             name: "toolkit".to_string(),
+            local_version: None,
             source: MarketplacePluginSource::Git {
                 url: missing_remote_repo_url,
                 path: Some("plugins/toolkit".to_string()),
@@ -2225,6 +2229,7 @@ plugins = true
             plugins: vec![ConfiguredMarketplacePlugin {
                 id: "linear@openai-curated".to_string(),
                 name: "linear".to_string(),
+                local_version: None,
                 source: MarketplacePluginSource::Local {
                     path: AbsolutePathBuf::try_from(curated_root.join("plugins/linear")).unwrap(),
                 },
@@ -2519,6 +2524,7 @@ enabled = false
         vec![ConfiguredMarketplacePlugin {
             id: "dup-plugin@debug".to_string(),
             name: "dup-plugin".to_string(),
+            local_version: None,
             source: MarketplacePluginSource::Local {
                 path: AbsolutePathBuf::try_from(tmp.path().join("repo-a/from-a")).unwrap(),
             },
@@ -2549,6 +2555,7 @@ enabled = false
         vec![ConfiguredMarketplacePlugin {
             id: "b-only-plugin@debug".to_string(),
             name: "b-only-plugin".to_string(),
+            local_version: None,
             source: MarketplacePluginSource::Local {
                 path: AbsolutePathBuf::try_from(tmp.path().join("repo-b/from-b-only")).unwrap(),
             },
@@ -2633,6 +2640,7 @@ enabled = true
             plugins: vec![ConfiguredMarketplacePlugin {
                 id: "sample-plugin@debug".to_string(),
                 name: "sample-plugin".to_string(),
+                local_version: None,
                 source: MarketplacePluginSource::Local {
                     path: AbsolutePathBuf::try_from(tmp.path().join("repo/sample-plugin")).unwrap(),
                 },
diff --git a/codex-rs/core-plugins/src/marketplace.rs b/codex-rs/core-plugins/src/marketplace.rs
index f66b5d1b227c..15959a7b559d 100644
--- a/codex-rs/core-plugins/src/marketplace.rs
+++ b/codex-rs/core-plugins/src/marketplace.rs
@@ -59,6 +59,7 @@ pub struct MarketplaceInterface {
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct MarketplacePlugin {
     pub name: String,
+    pub local_version: Option<String>,
     pub source: MarketplacePluginSource,
     pub policy: MarketplacePluginPolicy,
     pub interface: Option<PluginManifestInterface>,
@@ -289,15 +290,22 @@ pub fn load_marketplace(path: &AbsolutePathBuf) -> Result<Marketplace, Marketpla
             Err(err) => return Err(err),
         };
 
+        let local_version = plugin
+            .manifest
+            .as_ref()
+            .and_then(|manifest| manifest.version.clone());
+        let keywords = plugin
+            .manifest
+            .map(|manifest| manifest.keywords)
+            .unwrap_or_default();
+
         plugins.push(MarketplacePlugin {
             name: plugin.plugin_id.plugin_name,
+            local_version,
             source: plugin.source,
             policy: plugin.policy,
             interface: plugin.interface,
-            keywords: plugin
-                .manifest
-                .map(|manifest| manifest.keywords)
-                .unwrap_or_default(),
+            keywords,
         });
     }
 
diff --git a/codex-rs/core-plugins/src/marketplace_tests.rs b/codex-rs/core-plugins/src/marketplace_tests.rs
index 2e93df375ae2..e13415717723 100644
--- a/codex-rs/core-plugins/src/marketplace_tests.rs
+++ b/codex-rs/core-plugins/src/marketplace_tests.rs
@@ -388,6 +388,7 @@ fn list_marketplaces_supports_alternate_manifest_layout() {
             interface: None,
             plugins: vec![MarketplacePlugin {
                 name: "string-source-plugin".to_string(),
+                local_version: None,
                 source: MarketplacePluginSource::Local {
                     path: AbsolutePathBuf::try_from(repo_root.join("plugins/string-source-plugin"))
                         .unwrap(),
@@ -453,6 +454,7 @@ fn list_marketplaces_includes_plugins_without_discoverable_manifest() {
             interface: None,
             plugins: vec![MarketplacePlugin {
                 name: "missing-plugin".to_string(),
+                local_version: None,
                 source: MarketplacePluginSource::Local {
                     path: AbsolutePathBuf::try_from(repo_root.join("plugins/missing-plugin"),)
                         .unwrap(),
@@ -595,6 +597,7 @@ fn list_marketplaces_returns_home_and_repo_marketplaces() {
                 plugins: vec![
                     MarketplacePlugin {
                         name: "shared-plugin".to_string(),
+                        local_version: None,
                         source: MarketplacePluginSource::Local {
                             path: AbsolutePathBuf::try_from(home_root.join("home-shared")).unwrap(),
                         },
@@ -608,6 +611,7 @@ fn list_marketplaces_returns_home_and_repo_marketplaces() {
                     },
                     MarketplacePlugin {
                         name: "home-only".to_string(),
+                        local_version: None,
                         source: MarketplacePluginSource::Local {
                             path: AbsolutePathBuf::try_from(home_root.join("home-only")).unwrap(),
                         },
@@ -630,6 +634,7 @@ fn list_marketplaces_returns_home_and_repo_marketplaces() {
                 plugins: vec![
                     MarketplacePlugin {
                         name: "shared-plugin".to_string(),
+                        local_version: None,
                         source: MarketplacePluginSource::Local {
                             path: AbsolutePathBuf::try_from(repo_root.join("repo-shared")).unwrap(),
                         },
@@ -643,6 +648,7 @@ fn list_marketplaces_returns_home_and_repo_marketplaces() {
                     },
                     MarketplacePlugin {
                         name: "repo-only".to_string(),
+                        local_version: None,
                         source: MarketplacePluginSource::Local {
                             path: AbsolutePathBuf::try_from(repo_root.join("repo-only")).unwrap(),
                         },
@@ -721,6 +727,7 @@ fn list_marketplaces_keeps_distinct_entries_for_same_name() {
                 interface: None,
                 plugins: vec![MarketplacePlugin {
                     name: "local-plugin".to_string(),
+                    local_version: None,
                     source: MarketplacePluginSource::Local {
                         path: AbsolutePathBuf::try_from(home_root.join("home-plugin")).unwrap(),
                     },
@@ -739,6 +746,7 @@ fn list_marketplaces_keeps_distinct_entries_for_same_name() {
                 interface: None,
                 plugins: vec![MarketplacePlugin {
                     name: "local-plugin".to_string(),
+                    local_version: None,
                     source: MarketplacePluginSource::Local {
                         path: AbsolutePathBuf::try_from(repo_root.join("repo-plugin")).unwrap(),
                     },
@@ -813,6 +821,7 @@ fn list_marketplaces_dedupes_multiple_roots_in_same_repo() {
             interface: None,
             plugins: vec![MarketplacePlugin {
                 name: "local-plugin".to_string(),
+                local_version: None,
                 source: MarketplacePluginSource::Local {
                     path: AbsolutePathBuf::try_from(repo_root.join("plugin")).unwrap(),
                 },
@@ -976,6 +985,7 @@ fn list_marketplaces_skips_plugins_with_invalid_names_but_keeps_marketplace() {
             interface: None,
             plugins: vec![MarketplacePlugin {
                 name: "valid-plugin".to_string(),
+                local_version: None,
                 source: MarketplacePluginSource::Local {
                     path: AbsolutePathBuf::try_from(repo_root.join("valid-plugin")).unwrap(),
                 },
@@ -1093,6 +1103,7 @@ fn list_marketplaces_keeps_remote_and_local_plugin_sources() {
         vec![
             MarketplacePlugin {
                 name: "local-plugin".to_string(),
+                local_version: None,
                 source: MarketplacePluginSource::Local {
                     path: AbsolutePathBuf::try_from(repo_root.join("plugins/local-plugin"))
                         .unwrap(),
@@ -1107,6 +1118,7 @@ fn list_marketplaces_keeps_remote_and_local_plugin_sources() {
             },
             MarketplacePlugin {
                 name: "url-plugin".to_string(),
+                local_version: None,
                 source: MarketplacePluginSource::Git {
                     url: "https://github.com/example/plugin.git".to_string(),
                     path: None,
@@ -1123,6 +1135,7 @@ fn list_marketplaces_keeps_remote_and_local_plugin_sources() {
             },
             MarketplacePlugin {
                 name: "git-subdir-plugin".to_string(),
+                local_version: None,
                 source: MarketplacePluginSource::Git {
                     url: "https://github.com/owner/repo.git".to_string(),
                     path: Some("plugins/example".to_string()),
diff --git a/codex-rs/core-plugins/src/remote.rs b/codex-rs/core-plugins/src/remote.rs
index bb0e13a79da4..6822e6e19785 100644
--- a/codex-rs/core-plugins/src/remote.rs
+++ b/codex-rs/core-plugins/src/remote.rs
@@ -102,6 +102,7 @@ pub struct RemotePluginSummary {
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct RemotePluginShareContext {
     pub remote_plugin_id: String,
+    pub remote_version: Option<String>,
     pub discoverability: RemotePluginShareDiscoverability,
     pub share_url: Option<String>,
     pub creator_account_user_id: Option<String>,
@@ -897,6 +898,7 @@ fn remote_plugin_share_context(
             let discoverability = workspace_plugin_discoverability(plugin)?;
             Ok(Some(RemotePluginShareContext {
                 remote_plugin_id: plugin.id.clone(),
+                remote_version: plugin.release.version.clone(),
                 discoverability,
                 share_url: plugin.share_url.clone(),
                 creator_account_user_id: plugin.creator_account_user_id.clone(),
diff --git a/codex-rs/core-plugins/src/remote/share/tests.rs b/codex-rs/core-plugins/src/remote/share/tests.rs
index 8b27b28c3f08..23bcfbfb06a0 100644
--- a/codex-rs/core-plugins/src/remote/share/tests.rs
+++ b/codex-rs/core-plugins/src/remote/share/tests.rs
@@ -97,6 +97,7 @@ fn remote_plugin_json(plugin_id: &str) -> serde_json::Value {
         "installation_policy": "AVAILABLE",
         "authentication_policy": "ON_USE",
         "release": {
+            "version": "0.1.0",
             "display_name": "Demo Plugin",
             "description": "Demo plugin description",
             "interface": {
@@ -590,6 +591,7 @@ async fn list_remote_plugin_shares_fetches_created_workspace_plugins() {
                     name: "demo-plugin".to_string(),
                     share_context: Some(RemotePluginShareContext {
                         remote_plugin_id: "plugins_123".to_string(),
+                        remote_version: Some("0.1.0".to_string()),
                         discoverability: RemotePluginShareDiscoverability::Private,
                         share_url: Some(
                             "https://chatgpt.example/plugins/share/share-key-1".to_string(),
@@ -628,6 +630,7 @@ async fn list_remote_plugin_shares_fetches_created_workspace_plugins() {
                     name: "demo-plugin".to_string(),
                     share_context: Some(RemotePluginShareContext {
                         remote_plugin_id: "plugins_456".to_string(),
+                        remote_version: Some("0.1.0".to_string()),
                         discoverability: RemotePluginShareDiscoverability::Private,
                         share_url: None,
                         creator_account_user_id: None,
diff --git a/codex-rs/core/config.schema.json b/codex-rs/core/config.schema.json
index 5af6b7435b3d..dfd88164c36e 100644
--- a/codex-rs/core/config.schema.json
+++ b/codex-rs/core/config.schema.json
@@ -496,6 +496,9 @@
             "plugin_hooks": {
               "type": "boolean"
             },
+            "plugin_sharing": {
+              "type": "boolean"
+            },
             "plugins": {
               "type": "boolean"
             },
@@ -4170,6 +4173,9 @@
         "plugin_hooks": {
           "type": "boolean"
         },
+        "plugin_sharing": {
+          "type": "boolean"
+        },
         "plugins": {
           "type": "boolean"
         },
diff --git a/codex-rs/features/src/lib.rs b/codex-rs/features/src/lib.rs
index 955ae44c003f..7f268fb53a4d 100644
--- a/codex-rs/features/src/lib.rs
+++ b/codex-rs/features/src/lib.rs
@@ -188,6 +188,8 @@ pub enum Feature {
     ComputerUse,
     /// Temporary internal-only flag for PS-backed remote plugin catalog development.
     RemotePlugin,
+    /// Enable remote plugin sharing flows.
+    PluginSharing,
     /// Show the startup prompt for migrating external agent config into Codex.
     ExternalMigration,
     /// Allow the model to invoke the built-in image generation tool.
@@ -1006,6 +1008,12 @@ pub const FEATURES: &[FeatureSpec] = &[
         stage: Stage::UnderDevelopment,
         default_enabled: false,
     },
+    FeatureSpec {
+        id: Feature::PluginSharing,
+        key: "plugin_sharing",
+        stage: Stage::Stable,
+        default_enabled: true,
+    },
     FeatureSpec {
         id: Feature::ExternalMigration,
         key: "external_migration",
diff --git a/codex-rs/tui/src/chatwidget/tests/helpers.rs b/codex-rs/tui/src/chatwidget/tests/helpers.rs
index f5007e3fafcf..28ed69139b9f 100644
--- a/codex-rs/tui/src/chatwidget/tests/helpers.rs
+++ b/codex-rs/tui/src/chatwidget/tests/helpers.rs
@@ -1315,6 +1315,7 @@ pub(super) fn plugins_test_summary(
     PluginSummary {
         id: id.to_string(),
         remote_plugin_id: None,
+        local_version: None,
         name: name.to_string(),
         share_context: None,
         source: PluginSource::Local {
