gh-manager-cli 1.44.0 → 1.45.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,9 +1,16 @@
1
- # [1.44.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.43.0...v1.44.0) (2026-06-05)
1
+ ## [1.45.1](https://github.com/wiiiimm/gh-manager-cli/compare/v1.45.0...v1.45.1) (2026-06-07)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * ignore modal input while async actions are in flight, add guard tests (SWR-368) [semantic pr title] ([#64](https://github.com/wiiiimm/gh-manager-cli/issues/64)) ([97d2e4e](https://github.com/wiiiimm/gh-manager-cli/commit/97d2e4e25fc5d10cd2305ffb3f594b3f0b094e20)), closes [#65](https://github.com/wiiiimm/gh-manager-cli/issues/65)
7
+
8
+ # [1.45.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.44.0...v1.45.0) (2026-06-07)
2
9
 
3
10
 
4
11
  ### Features
5
12
 
6
- * theme-aware selected-row highlight with better contrast (SWR-364) ([#59](https://github.com/wiiiimm/gh-manager-cli/issues/59)) ([1b71cb2](https://github.com/wiiiimm/gh-manager-cli/commit/1b71cb2144b0773bb0d9538e3f30141e53346890)), closes [#1f4a57](https://github.com/wiiiimm/gh-manager-cli/issues/1f4a57) [#11294d](https://github.com/wiiiimm/gh-manager-cli/issues/11294d) [#14391f](https://github.com/wiiiimm/gh-manager-cli/issues/14391f) [#333333](https://github.com/wiiiimm/gh-manager-cli/issues/333333)
13
+ * add repository creation (Ctrl+N) and transfer (Shift+M) ([#60](https://github.com/wiiiimm/gh-manager-cli/issues/60)) ([2e9c271](https://github.com/wiiiimm/gh-manager-cli/commit/2e9c2711b985be9373a94483e0bd0b420dc48aec))
7
14
 
8
15
  # [1.43.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.42.0...v1.43.0) (2026-06-05)
9
16
 
package/README.md CHANGED
@@ -84,7 +84,9 @@ On first run, you'll be prompted to authenticate with GitHub (OAuth recommended)
84
84
  - View detailed info (`I`) - Shows repository metadata, language, size, and timestamps
85
85
  - Open in browser (Enter/`O`) — for forks a chooser lets you open this repo or the upstream
86
86
  - Jump to upstream (`P`) — moves cursor to the parent if loaded; otherwise fetches and shows it
87
+ - Create new repository (`Ctrl+N`) — prompts for a name (with the personal/organisation slug shown in front), choose visibility with `Tab`, and surfaces GitHub errors inline
87
88
  - Rename repository (`Ctrl+R`) with inline validation and automatic cache update
89
+ - Transfer repository to another owner (`Shift+M`) — prompts for the destination owner, requires a verification code, shows a final confirmation, and surfaces GitHub errors inline
88
90
  - Copy repository URL to clipboard (`C`) with SSH/HTTPS options
89
91
  - Delete repository (`Del` or `Backspace`) with secure two-step confirmation
90
92
  - Archive/unarchive repositories (`Ctrl+A`) with confirmation prompts
@@ -288,6 +290,10 @@ Launch the app, then use the keys below:
288
290
  - **Quit**: `Q`
289
291
 
290
292
  ### Repository Actions
293
+ - **Create repository**: `Ctrl+N` to create a new repository in the current context (personal or organisation)
294
+ - Prompts for a name with the owner slug (`owner/`) shown in front
295
+ - `Tab` cycles visibility (Private/Public, plus Internal for enterprise organisations)
296
+ - Enter to create; GitHub errors (e.g. name already exists) are shown inline
291
297
  - **Repository info**: `I` to view detailed metadata (size, language, timestamps)
292
298
  - **Cache info**: `K` to inspect Apollo cache status
293
299
  - **Archive/Unarchive**: `Ctrl+A` with confirmation prompt
@@ -298,6 +304,10 @@ Launch the app, then use the keys below:
298
304
  - **Star/Unstar**: `Ctrl+S` to toggle star status for any repository
299
305
  - **Sync fork**: `Ctrl+F` (for forks only, shows ahead/behind counts and handles conflicts)
300
306
  - **Rename repository**: `Ctrl+R` with inline validation
307
+ - **Transfer repository**: `Shift+M` (Move) to transfer ownership to another user or organisation
308
+ - Prompts for the destination owner (`new-owner/<repo>` preview)
309
+ - Requires typing a randomly generated verification code (like delete), then a final confirmation before transferring
310
+ - GitHub errors (e.g. insufficient permissions) are shown inline
301
311
  - **Copy URL**: `C` to copy repository URL to clipboard (SSH/HTTPS options)
302
312
 
303
313
  ### General
@@ -811,6 +811,85 @@ async function deleteRepositoryRest(token, owner, repo) {
811
811
  });
812
812
  throw new Error(msg);
813
813
  }
814
+ async function parseGitHubRestError(res, defaultMessage) {
815
+ let msg = defaultMessage;
816
+ try {
817
+ const errBody = await res.json();
818
+ if (errBody?.message) msg = errBody.message;
819
+ if (Array.isArray(errBody?.errors) && errBody.errors.length > 0) {
820
+ const details = errBody.errors.map((e) => e.message || (e.field ? `${e.field}: ${e.code}` : e.code)).filter(Boolean).join("; ");
821
+ if (details) msg += ` (${details})`;
822
+ }
823
+ } catch {
824
+ }
825
+ return msg;
826
+ }
827
+ async function createRepositoryRest(token, options) {
828
+ const { name, visibility, description, org } = options;
829
+ const url = org ? `https://api.github.com/orgs/${org}/repos` : `https://api.github.com/user/repos`;
830
+ const body = { name };
831
+ if (visibility === "INTERNAL") {
832
+ body.visibility = "internal";
833
+ } else {
834
+ body.private = visibility === "PRIVATE";
835
+ }
836
+ if (description) body.description = description;
837
+ logger.info("Creating repository", { name, visibility, org: org ?? null, url });
838
+ let res;
839
+ try {
840
+ res = await fetch(url, {
841
+ method: "POST",
842
+ headers: {
843
+ "Authorization": `token ${token}`,
844
+ "Accept": "application/vnd.github+json",
845
+ "Content-Type": "application/json",
846
+ "User-Agent": "gh-manager-cli"
847
+ },
848
+ body: JSON.stringify(body)
849
+ });
850
+ } catch (networkError) {
851
+ logger.error("Network error during repository creation", { error: networkError.message, name, org: org ?? null });
852
+ throw new Error(`Network error whilst creating repository: ${networkError.message}`);
853
+ }
854
+ if (res.status === 201) {
855
+ const data = await res.json();
856
+ logger.info("Successfully created repository", {
857
+ nameWithOwner: data.full_name,
858
+ url: data.html_url
859
+ });
860
+ return { nameWithOwner: data.full_name, url: data.html_url };
861
+ }
862
+ const msg = await parseGitHubRestError(res, `Failed to create repository (status ${res.status})`);
863
+ logger.error("Failed to create repository", { status: res.status, error: msg, name, org: org ?? null });
864
+ throw new Error(msg);
865
+ }
866
+ async function transferRepositoryRest(token, owner, repo, newOwner) {
867
+ const url = `https://api.github.com/repos/${owner}/${repo}/transfer`;
868
+ logger.info("Transferring repository", { owner, repo, newOwner, url });
869
+ let res;
870
+ try {
871
+ res = await fetch(url, {
872
+ method: "POST",
873
+ headers: {
874
+ "Authorization": `token ${token}`,
875
+ "Accept": "application/vnd.github+json",
876
+ "Content-Type": "application/json",
877
+ "User-Agent": "gh-manager-cli"
878
+ },
879
+ body: JSON.stringify({ new_owner: newOwner })
880
+ });
881
+ } catch (networkError) {
882
+ logger.error("Network error during repository transfer", { error: networkError.message, owner, repo, newOwner });
883
+ throw new Error(`Network error whilst transferring repository: ${networkError.message}`);
884
+ }
885
+ if (res.status === 202 || res.status === 200) {
886
+ logger.info("Successfully initiated repository transfer", { owner, repo, newOwner, status: res.status });
887
+ return;
888
+ }
889
+ const msg = await parseGitHubRestError(res, `Failed to transfer repository (status ${res.status})`);
890
+ logger.error("Failed to transfer repository", { status: res.status, error: msg, owner, repo, newOwner });
891
+ throw new Error(msg);
892
+ }
814
893
  async function getStarredRepositories(client, first, after) {
815
894
  logger.info("Fetching starred repositories", {
816
895
  first,
@@ -1607,6 +1686,8 @@ export {
1607
1686
  fetchViewerReposPageUnified,
1608
1687
  searchRepositoriesUnified,
1609
1688
  deleteRepositoryRest,
1689
+ createRepositoryRest,
1690
+ transferRepositoryRest,
1610
1691
  getStarredRepositories,
1611
1692
  starRepository,
1612
1693
  unstarRepository,
@@ -3,6 +3,7 @@ import {
3
3
  archiveRepositoryById,
4
4
  changeRepositoryVisibility,
5
5
  checkOrganizationIsEnterprise,
6
+ createRepositoryRest,
6
7
  deleteRepositoryRest,
7
8
  enrichForksWithAheadBehind,
8
9
  fetchRepositoryById,
@@ -21,6 +22,7 @@ import {
21
22
  searchRepositoriesUnified,
22
23
  starRepository,
23
24
  syncForkWithUpstream,
25
+ transferRepositoryRest,
24
26
  unarchiveRepositoryById,
25
27
  unstarRepository,
26
28
  updateCacheAfterArchive,
@@ -28,11 +30,12 @@ import {
28
30
  updateCacheAfterRename,
29
31
  updateCacheAfterVisibilityChange,
30
32
  updateCacheWithRepository
31
- } from "./chunk-MKIUBPVD.js";
33
+ } from "./chunk-WHX6IOTW.js";
32
34
  export {
33
35
  archiveRepositoryById,
34
36
  changeRepositoryVisibility,
35
37
  checkOrganizationIsEnterprise,
38
+ createRepositoryRest,
36
39
  deleteRepositoryRest,
37
40
  enrichForksWithAheadBehind,
38
41
  fetchRepositoryById,
@@ -51,6 +54,7 @@ export {
51
54
  searchRepositoriesUnified,
52
55
  starRepository,
53
56
  syncForkWithUpstream,
57
+ transferRepositoryRest,
54
58
  unarchiveRepositoryById,
55
59
  unstarRepository,
56
60
  updateCacheAfterArchive,