diff --git a/actions/setup/js/close_pull_request.cjs b/actions/setup/js/close_pull_request.cjs
index a0f2d400040..1271c775930 100644
--- a/actions/setup/js/close_pull_request.cjs
+++ b/actions/setup/js/close_pull_request.cjs
@@ -80,8 +80,10 @@ async function main(config = {}) {
   const requiredTitlePrefix = config.required_title_prefix || "";
   const { defaultTargetRepo, allowedRepos } = resolveTargetRepoConfig(config);
   const githubClient = await createAuthenticatedGitHubClient(config);
+  const configuredTargetRepo = config["target-repo"] || "";
 
   core.info(`Close pull request configuration: max=${config.max || 10}`);
+  core.info(`Configured target repo: ${configuredTargetRepo || "(unset)"}`);
   core.info(`Default target repo: ${defaultTargetRepo}`);
   if (allowedRepos.size > 0) {
     core.info(`Allowed repos: ${Array.from(allowedRepos).join(", ")}`);
@@ -143,7 +145,7 @@ async function main(config = {}) {
       addComment: addPullRequestComment,
 
       closeEntity(github, owner, repo, prNumber) {
-        core.info(`Closing PR #${prNumber}`);
+        core.info(`Closing PR #${prNumber} in ${owner}/${repo}`);
         return closePullRequest(github, owner, repo, prNumber);
       },
 
diff --git a/actions/setup/js/close_pull_request.test.cjs b/actions/setup/js/close_pull_request.test.cjs
index 895a28cee78..3ff92a49f7b 100644
--- a/actions/setup/js/close_pull_request.test.cjs
+++ b/actions/setup/js/close_pull_request.test.cjs
@@ -107,6 +107,16 @@ describe("close_pull_request", () => {
       expect(mockCore.infos.some(msg => msg.includes("bug, automated"))).toBe(true);
       expect(mockCore.infos.some(msg => msg.includes("[bot]"))).toBe(true);
     });
+
+    it("should log configured and effective target repo on initialization", async () => {
+      await main({
+        max: 3,
+        "target-repo": "external-org/external-repo",
+      });
+
+      expect(mockCore.infos).toContain("Configured target repo: external-org/external-repo");
+      expect(mockCore.infos).toContain("Default target repo: external-org/external-repo");
+    });
   });
 
   describe("handleClosePullRequest", () => {
@@ -446,5 +456,190 @@ describe("close_pull_request", () => {
       expect(result.success).toBe(false);
       expect(result.error.includes("API Error")).toBe(true);
     });
+
+    it("should support target-repo from config", async () => {
+      const handler = await main({
+        max: 10,
+        "target-repo": "external-org/external-repo",
+      });
+      const updateCalls = [];
+
+      mockGithub.rest.pulls.get = async params => ({
+        data: {
+          number: params.pull_number,
+          title: "Test PR",
+          labels: [],
+          html_url: `https://github.com/${params.owner}/${params.repo}/pull/${params.pull_number}`,
+          state: "open",
+        },
+      });
+
+      mockGithub.rest.pulls.update = async params => {
+        updateCalls.push(params);
+        return {
+          data: {
+            number: params.pull_number,
+            title: "Test PR",
+            html_url: `https://github.com/${params.owner}/${params.repo}/pull/${params.pull_number}`,
+          },
+        };
+      };
+
+      const result = await handler({ pull_request_number: 100, body: "Closing" }, {});
+
+      expect(result.success).toBe(true);
+      expect(updateCalls[0].owner).toBe("external-org");
+      expect(updateCalls[0].repo).toBe("external-repo");
+      expect(mockCore.infos).toContain("Target repository: external-org/external-repo");
+      expect(mockCore.infos).toContain("Closing PR #100 in external-org/external-repo");
+    });
+
+    it("should support repo field in message for cross-repository operations", async () => {
+      const handler = await main({
+        max: 10,
+        "target-repo": "default-org/default-repo",
+        allowed_repos: ["cross-org/cross-repo"],
+      });
+      const updateCalls = [];
+
+      mockGithub.rest.pulls.get = async params => ({
+        data: {
+          number: params.pull_number,
+          title: "Test PR",
+          labels: [],
+          html_url: `https://github.com/${params.owner}/${params.repo}/pull/${params.pull_number}`,
+          state: "open",
+        },
+      });
+
+      mockGithub.rest.pulls.update = async params => {
+        updateCalls.push(params);
+        return {
+          data: {
+            number: params.pull_number,
+            title: "Test PR",
+            html_url: `https://github.com/${params.owner}/${params.repo}/pull/${params.pull_number}`,
+          },
+        };
+      };
+
+      const result = await handler(
+        {
+          pull_request_number: 456,
+          repo: "cross-org/cross-repo",
+          body: "Closing cross-repo PR",
+        },
+        {}
+      );
+
+      expect(result.success).toBe(true);
+      expect(updateCalls[0].owner).toBe("cross-org");
+      expect(updateCalls[0].repo).toBe("cross-repo");
+    });
+
+    it("should reject repo not in allowed-repos list", async () => {
+      const handler = await main({
+        max: 10,
+        "target-repo": "default-org/default-repo",
+        allowed_repos: ["allowed-org/allowed-repo"],
+      });
+
+      const result = await handler(
+        {
+          pull_request_number: 100,
+          repo: "unauthorized-org/unauthorized-repo",
+          body: "Trying to close",
+        },
+        {}
+      );
+
+      expect(result.success).toBe(false);
+      expect(result.error).toContain("not in the allowed-repos list");
+    });
+
+    it("should qualify bare repo name with default repo org", async () => {
+      const handler = await main({
+        max: 10,
+        "target-repo": "github/default-repo",
+        allowed_repos: ["github/gh-aw"],
+      });
+      const updateCalls = [];
+
+      mockGithub.rest.pulls.get = async params => ({
+        data: {
+          number: params.pull_number,
+          title: "Test PR",
+          labels: [],
+          html_url: `https://github.com/${params.owner}/${params.repo}/pull/${params.pull_number}`,
+          state: "open",
+        },
+      });
+
+      mockGithub.rest.pulls.update = async params => {
+        updateCalls.push(params);
+        return {
+          data: {
+            number: params.pull_number,
+            title: "Test PR",
+            html_url: `https://github.com/${params.owner}/${params.repo}/pull/${params.pull_number}`,
+          },
+        };
+      };
+
+      const result = await handler(
+        {
+          pull_request_number: 100,
+          repo: "gh-aw",
+          body: "Closing",
+        },
+        {}
+      );
+
+      expect(result.success).toBe(true);
+      expect(updateCalls[0].owner).toBe("github");
+      expect(updateCalls[0].repo).toBe("gh-aw");
+    });
+
+    it("should close a pull request in any repo when target-repo is wildcard *", async () => {
+      const handler = await main({
+        max: 10,
+        "target-repo": "*",
+      });
+      const updateCalls = [];
+
+      mockGithub.rest.pulls.get = async params => ({
+        data: {
+          number: params.pull_number,
+          title: "Test PR",
+          labels: [],
+          html_url: `https://github.com/${params.owner}/${params.repo}/pull/${params.pull_number}`,
+          state: "open",
+        },
+      });
+
+      mockGithub.rest.pulls.update = async params => {
+        updateCalls.push(params);
+        return {
+          data: {
+            number: params.pull_number,
+            title: "Test PR",
+            html_url: `https://github.com/${params.owner}/${params.repo}/pull/${params.pull_number}`,
+          },
+        };
+      };
+
+      const result = await handler(
+        {
+          pull_request_number: 200,
+          repo: "any-org/any-repo",
+          body: "Closing",
+        },
+        {}
+      );
+
+      expect(result.success).toBe(true);
+      expect(updateCalls[0].owner).toBe("any-org");
+      expect(updateCalls[0].repo).toBe("any-repo");
+    });
   });
 });
diff --git a/pkg/workflow/compiler_safe_outputs_config_test.go b/pkg/workflow/compiler_safe_outputs_config_test.go
index 0ac4f6ac765..69c46ac0cb8 100644
--- a/pkg/workflow/compiler_safe_outputs_config_test.go
+++ b/pkg/workflow/compiler_safe_outputs_config_test.go
@@ -1419,6 +1419,54 @@ func TestHandlerConfigTargetRepo(t *testing.T) {
 	}
 }
 
+func TestHandlerConfigClosePullRequestTargetRepo(t *testing.T) {
+	compiler := NewCompiler()
+
+	workflowData := &WorkflowData{
+		Name: "Test Workflow",
+		SafeOutputs: &SafeOutputsConfig{
+			ClosePullRequests: &ClosePullRequestsConfig{
+				BaseSafeOutputConfig: BaseSafeOutputConfig{
+					Max: strPtr("1"),
+				},
+				SafeOutputTargetConfig: SafeOutputTargetConfig{
+					Target:         "*",
+					TargetRepoSlug: "${{ needs.input_parser.outputs.repo }}",
+				},
+			},
+		},
+	}
+
+	var steps []string
+	compiler.addHandlerManagerConfigEnvVar(&steps, workflowData)
+
+	for _, step := range steps {
+		if strings.Contains(step, "GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG") {
+			parts := strings.Split(step, "GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: ")
+			if len(parts) == 2 {
+				jsonStr := strings.TrimSpace(parts[1])
+				jsonStr = strings.Trim(jsonStr, "\"")
+				jsonStr = strings.ReplaceAll(jsonStr, "\\\"", "\"")
+
+				var config map[string]map[string]any
+				err := json.Unmarshal([]byte(jsonStr), &config)
+				require.NoError(t, err)
+
+				closePRConfig, ok := config["close_pull_request"]
+				require.True(t, ok)
+
+				targetRepo, ok := closePRConfig["target-repo"]
+				require.True(t, ok)
+				assert.Equal(t, "${{ needs.input_parser.outputs.repo }}", targetRepo)
+
+				target, ok := closePRConfig["target"]
+				require.True(t, ok)
+				assert.Equal(t, "*", target)
+			}
+		}
+	}
+}
+
 // TestHandlerConfigPatchSize tests max patch size configuration
 func TestHandlerConfigPatchSize(t *testing.T) {
 	tests := []struct {
diff --git a/pkg/workflow/safe_outputs_tools_generation_test.go b/pkg/workflow/safe_outputs_tools_generation_test.go
index 7fa070fc0b3..01a605df0a9 100644
--- a/pkg/workflow/safe_outputs_tools_generation_test.go
+++ b/pkg/workflow/safe_outputs_tools_generation_test.go
@@ -201,6 +201,37 @@ func TestAddRepoParameterIfNeededSpecificTargetRepoNoAllowedRepos(t *testing.T)
 	assert.False(t, hasRepo, "repo parameter should NOT be added when target-repo is specific and no allowed-repos")
 }
 
+func TestAddRepoParameterIfNeededClosePullRequestWithAllowedRepos(t *testing.T) {
+	tool := map[string]any{
+		"name": "close_pull_request",
+		"inputSchema": map[string]any{
+			"type": "object",
+			"properties": map[string]any{
+				"body": map[string]any{"type": "string"},
+			},
+		},
+	}
+
+	safeOutputs := &SafeOutputsConfig{
+		ClosePullRequests: &ClosePullRequestsConfig{
+			SafeOutputTargetConfig: SafeOutputTargetConfig{
+				TargetRepoSlug: "org/default-repo",
+				AllowedRepos:   []string{"org/other-repo"},
+			},
+		},
+	}
+
+	addRepoParameterIfNeeded(tool, "close_pull_request", safeOutputs)
+
+	inputSchema := tool["inputSchema"].(map[string]any)
+	properties := inputSchema["properties"].(map[string]any)
+
+	repoProp, ok := properties["repo"].(map[string]any)
+	require.True(t, ok, "repo property should be added")
+	assert.Equal(t, "string", repoProp["type"], "repo type should be string")
+	assert.Contains(t, repoProp["description"].(string), "org/default-repo", "description should include default repo")
+}
+
 func TestParseUpdateIssuesConfigWithWildcardTargetRepo(t *testing.T) {
 	compiler := &Compiler{}
 	outputMap := map[string]any{
