gh-manager-cli 1.37.0 → 1.38.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 +14 -0
- package/README.md +7 -3
- package/dist/index.js +60 -20
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
## [1.38.1](https://github.com/wiiiimm/gh-manager-cli/compare/v1.38.0...v1.38.1) (2026-06-05)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* add archive filter toggle for repositories [semantic pr title] ([#43](https://github.com/wiiiimm/gh-manager-cli/issues/43)) ([3b717a3](https://github.com/wiiiimm/gh-manager-cli/commit/3b717a345c6104a6b59e530eb7688bac9d8276ee))
|
|
7
|
+
|
|
8
|
+
# [1.38.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.37.0...v1.38.0) (2025-09-09)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add GitHub Sponsors integration ([b73a8c2](https://github.com/wiiiimm/gh-manager-cli/commit/b73a8c244aa6a336b249bc573a019c307b56bfc5))
|
|
14
|
+
|
|
1
15
|
# [1.37.0](https://github.com/wiiiimm/gh-manager-cli/compare/v1.36.0...v1.37.0) (2025-09-09)
|
|
2
16
|
|
|
3
17
|
|
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
[](https://opensource.org/licenses/MIT)
|
|
8
8
|
[](https://nodejs.org)
|
|
9
9
|
[](https://github.com/wiiiimm/gh-manager-cli/stargazers)
|
|
10
|
+
[](https://github.com/sponsors/wiiiimm)
|
|
10
11
|
[](https://www.anthropic.com)
|
|
11
12
|
[](https://openai.com)
|
|
12
13
|
|
|
@@ -75,7 +76,8 @@ On first run, you'll be prompted to authenticate with GitHub (OAuth recommended)
|
|
|
75
76
|
- **Live Pagination**: Infinite scroll with automatic page prefetching
|
|
76
77
|
- **Interactive Sorting**: Modal-based sort selection (updated, pushed, name, stars) with modal-based direction selection
|
|
77
78
|
- **Smart Search**: Server-side search through repository names and descriptions (3+ characters)
|
|
78
|
-
- **Visibility
|
|
79
|
+
- **Visibility Filter**: Modal-based visibility filter (All, Public, Private/Internal for enterprise) with smart filtering
|
|
80
|
+
- **Archive Filter**: Toggle-based archive filter (`A` key cycles All → Unarchived → Archived) for quick filtering by archive status
|
|
79
81
|
- **Fork Status Tracking**: Always shows commits behind upstream for forked repositories
|
|
80
82
|
- **Stars Mode**: View and manage starred repositories (personal account only)
|
|
81
83
|
- **Repository Actions**:
|
|
@@ -101,7 +103,7 @@ On first run, you'll be prompted to authenticate with GitHub (OAuth recommended)
|
|
|
101
103
|
- **Rate Limit Monitoring**: Dual API rate limit display (GraphQL & REST) with real-time usage deltas and visual warnings
|
|
102
104
|
|
|
103
105
|
### Technical Features
|
|
104
|
-
- **Preference Persistence**: UI settings (sort, density, visibility filter, fork tracking) saved between sessions
|
|
106
|
+
- **Preference Persistence**: UI settings (sort, density, visibility filter, archive filter, fork tracking) saved between sessions
|
|
105
107
|
- **Server-side Filtering**: Visibility filtering performed at GitHub API level for accurate pagination
|
|
106
108
|
- **Cross-platform**: Works on macOS, Linux, and Windows
|
|
107
109
|
- **Secure Storage**: Token stored with proper file permissions (0600)
|
|
@@ -270,6 +272,7 @@ Launch the app, then use the keys below:
|
|
|
270
272
|
- **Display Density**: `T` to toggle compact/cozy/comfy
|
|
271
273
|
- **Fork Status**: Always enabled - shows commits behind upstream for all forks
|
|
272
274
|
- **Visibility Filter**: `V` opens modal (All, Public, Private/Internal for enterprise)
|
|
275
|
+
- **Archive Filter**: `A` toggles archive filter (All → Unarchived → Archived)
|
|
273
276
|
- **Stars Mode**: `Shift+S` (personal account only) to view starred repositories
|
|
274
277
|
|
|
275
278
|
### Navigation & Account
|
|
@@ -529,7 +532,8 @@ Highlights on deck:
|
|
|
529
532
|
|
|
530
533
|
If you find gh-manager-cli useful, consider supporting its development:
|
|
531
534
|
|
|
532
|
-
|
|
535
|
+
💖 **[GitHub Sponsors](https://github.com/sponsors/wiiiimm)** - Support directly through GitHub
|
|
536
|
+
☕ **[Buy Me a Coffee](https://buymeacoffee.com/wiiiimm)** - One-time coffee donations
|
|
533
537
|
|
|
534
538
|
Your support helps maintain and improve this project. Thank you! 🙏
|
|
535
539
|
|
package/dist/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var require_package = __commonJS({
|
|
|
34
34
|
"package.json"(exports, module) {
|
|
35
35
|
module.exports = {
|
|
36
36
|
name: "gh-manager-cli",
|
|
37
|
-
version: "1.
|
|
37
|
+
version: "1.38.1",
|
|
38
38
|
private: false,
|
|
39
39
|
description: "TUI terminal app to manage GitHub repos. Clean up your account in 5 minutes. Archive, delete, rename repos with keyboard shortcuts. Alternative to clicking through github.com",
|
|
40
40
|
license: "MIT",
|
|
@@ -115,7 +115,7 @@ var require_package = __commonJS({
|
|
|
115
115
|
"semantic-release": "^24.2.7",
|
|
116
116
|
tsup: "^8.5.0",
|
|
117
117
|
typescript: "^5.9.2",
|
|
118
|
-
vitest: "^
|
|
118
|
+
vitest: "^4.1.0"
|
|
119
119
|
},
|
|
120
120
|
repository: {
|
|
121
121
|
type: "git",
|
|
@@ -1819,6 +1819,7 @@ function RepoListHeader({
|
|
|
1819
1819
|
searchActive,
|
|
1820
1820
|
searchLoading,
|
|
1821
1821
|
visibilityFilter = "all",
|
|
1822
|
+
archiveFilter = "all",
|
|
1822
1823
|
isEnterprise = false,
|
|
1823
1824
|
starsMode = false
|
|
1824
1825
|
}) {
|
|
@@ -1841,6 +1842,10 @@ function RepoListHeader({
|
|
|
1841
1842
|
"Visibility: ",
|
|
1842
1843
|
visibilityLabel
|
|
1843
1844
|
] }),
|
|
1845
|
+
archiveFilter !== "all" && /* @__PURE__ */ jsxs17(Text18, { color: "cyan", children: [
|
|
1846
|
+
"Archive: ",
|
|
1847
|
+
archiveFilter === "archived" ? "Archived" : "Unarchived"
|
|
1848
|
+
] }),
|
|
1844
1849
|
filter && !searchActive && /* @__PURE__ */ jsxs17(Text18, { color: "cyan", children: [
|
|
1845
1850
|
'Filter: "',
|
|
1846
1851
|
filter,
|
|
@@ -2362,6 +2367,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2362
2367
|
const [forkTracking, setForkTracking] = useState15(true);
|
|
2363
2368
|
const [visibilityFilter, setVisibilityFilter] = useState15("all");
|
|
2364
2369
|
const previousVisibilityFilter = useRef("all");
|
|
2370
|
+
const [archiveFilter, setArchiveFilter] = useState15("all");
|
|
2365
2371
|
const sortFieldMap = {
|
|
2366
2372
|
"updated": "UPDATED_AT",
|
|
2367
2373
|
"pushed": "PUSHED_AT",
|
|
@@ -2534,6 +2540,9 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
2534
2540
|
if (ui.visibilityFilter && ["all", "public", "private", "internal"].includes(ui.visibilityFilter)) {
|
|
2535
2541
|
setVisibilityFilter(ui.visibilityFilter);
|
|
2536
2542
|
}
|
|
2543
|
+
if (ui.archiveFilter && ["all", "unarchived", "archived"].includes(ui.archiveFilter)) {
|
|
2544
|
+
setArchiveFilter(ui.archiveFilter);
|
|
2545
|
+
}
|
|
2537
2546
|
if (ui.ownerContext) {
|
|
2538
2547
|
setOwnerContext(ui.ownerContext);
|
|
2539
2548
|
if (onOrgContextChange) {
|
|
@@ -3064,6 +3073,15 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
3064
3073
|
});
|
|
3065
3074
|
return;
|
|
3066
3075
|
}
|
|
3076
|
+
if (input && input.toUpperCase() === "A" && !key.ctrl) {
|
|
3077
|
+
setArchiveFilter((f) => {
|
|
3078
|
+
const next = f === "all" ? "unarchived" : f === "unarchived" ? "archived" : "all";
|
|
3079
|
+
storeUIPrefs({ archiveFilter: next });
|
|
3080
|
+
return next;
|
|
3081
|
+
});
|
|
3082
|
+
setCursor(0);
|
|
3083
|
+
return;
|
|
3084
|
+
}
|
|
3067
3085
|
if (input && input.toUpperCase() === "V") {
|
|
3068
3086
|
if (!starsMode) {
|
|
3069
3087
|
setVisibilityMode(true);
|
|
@@ -3076,6 +3094,11 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
3076
3094
|
if (visibilityFilter === "private") {
|
|
3077
3095
|
result = result.filter((r) => r.visibility === "PRIVATE" || r.visibility === "INTERNAL");
|
|
3078
3096
|
}
|
|
3097
|
+
if (archiveFilter === "archived") {
|
|
3098
|
+
result = result.filter((r) => r.isArchived);
|
|
3099
|
+
} else if (archiveFilter === "unarchived") {
|
|
3100
|
+
result = result.filter((r) => !r.isArchived);
|
|
3101
|
+
}
|
|
3079
3102
|
const q = filter.trim().toLowerCase();
|
|
3080
3103
|
if (q) {
|
|
3081
3104
|
result = result.filter(
|
|
@@ -3083,7 +3106,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
3083
3106
|
);
|
|
3084
3107
|
}
|
|
3085
3108
|
return result;
|
|
3086
|
-
}, [items, filter, visibilityFilter]);
|
|
3109
|
+
}, [items, filter, visibilityFilter, archiveFilter]);
|
|
3087
3110
|
const filteredAndSorted = useMemo(() => {
|
|
3088
3111
|
const arr = [...filtered];
|
|
3089
3112
|
const dir = sortDir === "asc" ? 1 : -1;
|
|
@@ -3112,15 +3135,28 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
3112
3135
|
} else if (visibilityFilter === "public") {
|
|
3113
3136
|
result = result.filter((r) => r.visibility === "PUBLIC");
|
|
3114
3137
|
}
|
|
3138
|
+
if (archiveFilter === "archived") {
|
|
3139
|
+
result = result.filter((r) => r.isArchived);
|
|
3140
|
+
} else if (archiveFilter === "unarchived") {
|
|
3141
|
+
result = result.filter((r) => !r.isArchived);
|
|
3142
|
+
}
|
|
3115
3143
|
return result;
|
|
3116
|
-
}, [searchItems, visibilityFilter]);
|
|
3144
|
+
}, [searchItems, visibilityFilter, archiveFilter]);
|
|
3117
3145
|
const filteredStarredItems = useMemo(() => {
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3146
|
+
let result = starredItems;
|
|
3147
|
+
if (filter && filter.trim().length > 0) {
|
|
3148
|
+
const lowerFilter = filter.toLowerCase();
|
|
3149
|
+
result = result.filter(
|
|
3150
|
+
(repo) => repo.nameWithOwner.toLowerCase().includes(lowerFilter) || repo.description && repo.description.toLowerCase().includes(lowerFilter)
|
|
3151
|
+
);
|
|
3152
|
+
}
|
|
3153
|
+
if (archiveFilter === "archived") {
|
|
3154
|
+
result = result.filter((r) => r.isArchived);
|
|
3155
|
+
} else if (archiveFilter === "unarchived") {
|
|
3156
|
+
result = result.filter((r) => !r.isArchived);
|
|
3157
|
+
}
|
|
3158
|
+
return result;
|
|
3159
|
+
}, [starredItems, filter, archiveFilter]);
|
|
3124
3160
|
const visibleItems = starsMode ? filteredStarredItems : searchActive ? filteredSearchItems : filteredAndSorted;
|
|
3125
3161
|
useEffect11(() => {
|
|
3126
3162
|
if (searchActive) {
|
|
@@ -3151,23 +3187,26 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
3151
3187
|
useEffect11(() => {
|
|
3152
3188
|
const prefetchThreshold = Math.floor(visibleItems.length * 0.8);
|
|
3153
3189
|
const nearEnd = visibleItems.length > 0 && cursor >= prefetchThreshold;
|
|
3190
|
+
const rawItemsLength = starsMode ? starredItems.length : searchActive ? searchItems.length : items.length;
|
|
3191
|
+
const filterDrainedPage = visibleItems.length === 0 && archiveFilter !== "all" && rawItemsLength > 0;
|
|
3192
|
+
const shouldFetch = nearEnd || filterDrainedPage;
|
|
3154
3193
|
if (starsMode) {
|
|
3155
|
-
if (!starredLoading && starredHasNextPage &&
|
|
3194
|
+
if (!starredLoading && starredHasNextPage && shouldFetch) {
|
|
3156
3195
|
addDebugMessage(`[Infinite Scroll] Prefetching starred repos at ${cursor}/${visibleItems.length} (80% threshold: ${prefetchThreshold})`);
|
|
3157
3196
|
fetchStarredRepositories(starredEndCursor);
|
|
3158
3197
|
}
|
|
3159
3198
|
} else if (searchActive) {
|
|
3160
|
-
if (!searchLoading && searchHasNextPage &&
|
|
3199
|
+
if (!searchLoading && searchHasNextPage && shouldFetch) {
|
|
3161
3200
|
addDebugMessage(`[Infinite Scroll] Prefetching search results at ${cursor}/${visibleItems.length} (80% threshold: ${prefetchThreshold})`);
|
|
3162
3201
|
fetchSearchPage(searchEndCursor);
|
|
3163
3202
|
}
|
|
3164
3203
|
} else {
|
|
3165
|
-
if (!loading && !loadingMore && hasNextPage &&
|
|
3204
|
+
if (!loading && !loadingMore && hasNextPage && shouldFetch) {
|
|
3166
3205
|
addDebugMessage(`[Infinite Scroll] Prefetching repos at ${cursor}/${visibleItems.length} (80% threshold: ${prefetchThreshold})`);
|
|
3167
3206
|
fetchPage(endCursor);
|
|
3168
3207
|
}
|
|
3169
3208
|
}
|
|
3170
|
-
}, [cursor, visibleItems.length, starsMode, starredLoading, starredHasNextPage, starredEndCursor, searchActive, searchLoading, searchHasNextPage, searchEndCursor, loading, loadingMore, hasNextPage, endCursor]);
|
|
3209
|
+
}, [cursor, visibleItems.length, archiveFilter, items.length, starredItems.length, searchItems.length, starsMode, starredLoading, starredHasNextPage, starredEndCursor, searchActive, searchLoading, searchHasNextPage, searchEndCursor, loading, loadingMore, hasNextPage, endCursor]);
|
|
3171
3210
|
function openInBrowser(url) {
|
|
3172
3211
|
const platform = process.platform;
|
|
3173
3212
|
const cmd = platform === "darwin" ? `open "${url}"` : platform === "win32" ? `start "" "${url}"` : `xdg-open "${url}"`;
|
|
@@ -3237,7 +3276,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
3237
3276
|
showSponsorReminder && /* @__PURE__ */ jsx19(Box18, { marginX: 1, marginBottom: 1, children: /* @__PURE__ */ jsx19(Box18, { borderStyle: "single", borderColor: "yellow", paddingX: 2, paddingY: 1, children: /* @__PURE__ */ jsxs18(Box18, { flexDirection: "column", alignItems: "center", children: [
|
|
3238
3277
|
/* @__PURE__ */ jsx19(Text19, { color: "yellow", children: "\u{1F49A} Thanks for using gh-manager-cli!" }),
|
|
3239
3278
|
/* @__PURE__ */ jsx19(Text19, { color: "gray", children: "Your support helps craft more open-source tools" }),
|
|
3240
|
-
/* @__PURE__ */ jsx19(Text19, { color: "cyan", children: "\
|
|
3279
|
+
/* @__PURE__ */ jsx19(Text19, { color: "cyan", children: "\u{1F496} github.com/sponsors/wiiiimm" })
|
|
3241
3280
|
] }) }) }),
|
|
3242
3281
|
/* @__PURE__ */ jsx19(Box18, { borderStyle: "single", borderColor: modalOpen ? "gray" : "yellow", paddingX: 1, paddingY: 1, marginX: 1, height: contentHeight + containerPadding + 2, flexDirection: "column", children: deleteMode && deleteTarget ? (
|
|
3243
3282
|
// Centered modal; hide list content while modal is open
|
|
@@ -3646,6 +3685,7 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
3646
3685
|
searchActive,
|
|
3647
3686
|
searchLoading,
|
|
3648
3687
|
visibilityFilter,
|
|
3688
|
+
archiveFilter,
|
|
3649
3689
|
isEnterprise: isEnterpriseOrg,
|
|
3650
3690
|
starsMode
|
|
3651
3691
|
}
|
|
@@ -3719,13 +3759,13 @@ function RepoList({ token, maxVisibleRows, onLogout, viewerLogin, onOrgContextCh
|
|
|
3719
3759
|
/* @__PURE__ */ jsxs18(Box18, { marginTop: 1, paddingX: 1, flexDirection: "column", children: [
|
|
3720
3760
|
/* @__PURE__ */ jsx19(Box18, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx19(Text19, { color: "gray", dimColor: modalOpen ? true : void 0, children: "\u2191\u2193 Navigate \u2022 Ctrl+G Top \u2022 G Bottom \u2022 \u23CE/O Open \u2022 R Refresh" }) }),
|
|
3721
3761
|
/* @__PURE__ */ jsx19(Box18, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsxs18(Text19, { color: "gray", dimColor: modalOpen ? true : void 0, children: [
|
|
3722
|
-
"/ Search \u2022 S Sort \u2022 D Direction \u2022 T Density",
|
|
3723
|
-
!starsMode && " \u2022 V Visibility",
|
|
3762
|
+
"/ Search \u2022 S Sort \u2022 D Direction \u2022 T Density \u2022 A Archive",
|
|
3763
|
+
!starsMode && " \u2022 V Visibility Filter",
|
|
3724
3764
|
ownerContext === "personal" && " \u2022 Shift+S Stars"
|
|
3725
3765
|
] }) }),
|
|
3726
3766
|
/* @__PURE__ */ jsx19(Box18, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx19(Text19, { color: "gray", dimColor: modalOpen ? true : void 0, children: starsMode ? "I Info \u2022 C Copy URL \u2022 U Unstar Repository" : "I Info \u2022 C Copy URL \u2022 Ctrl+S Un/Star \u2022 Ctrl+R Rename \u2022 Ctrl+A Un/Archive \u2022 Ctrl+V Change Visibility \u2022 Ctrl+F Sync Fork" }) }),
|
|
3727
3767
|
/* @__PURE__ */ jsx19(Box18, { width: terminalWidth, justifyContent: "center", children: /* @__PURE__ */ jsx19(Text19, { color: "gray", dimColor: modalOpen ? true : void 0, children: "K Cache Info \u2022 W Org Switch \u2022 Del/Backspace Delete \u2022 Ctrl+L Logout \u2022 Q Quit" }) }),
|
|
3728
|
-
/* @__PURE__ */ jsx19(Box18, { width: terminalWidth, justifyContent: "center", marginTop: 1, children: /* @__PURE__ */ jsx19(Text19, { color: "yellow", dimColor: modalOpen ? true : void 0, children: "\u{
|
|
3768
|
+
/* @__PURE__ */ jsx19(Box18, { width: terminalWidth, justifyContent: "center", marginTop: 1, children: /* @__PURE__ */ jsx19(Text19, { color: "yellow", dimColor: modalOpen ? true : void 0, children: "\u{1F496} Sponsor on GitHub: github.com/sponsors/wiiiimm" }) })
|
|
3729
3769
|
] }),
|
|
3730
3770
|
process.env.GH_MANAGER_DEBUG === "1" && /* @__PURE__ */ jsxs18(Box18, { marginTop: 1, borderStyle: "single", borderColor: "yellow", paddingX: 1, flexDirection: "column", children: [
|
|
3731
3771
|
/* @__PURE__ */ jsx19(Text19, { bold: true, color: "yellow", children: "Debug Messages:" }),
|
|
@@ -4348,10 +4388,10 @@ var showSponsorshipMessage = () => {
|
|
|
4348
4388
|
console.log("\n\u{1F49A} Thank you for using gh-manager-cli!\n");
|
|
4349
4389
|
console.log("If this app saved you time, please consider supporting");
|
|
4350
4390
|
console.log("the development of more open-source projects like this:\n");
|
|
4351
|
-
console.log(" \
|
|
4391
|
+
console.log(" \u{1F496} Sponsor on GitHub: https://github.com/sponsors/wiiiimm");
|
|
4352
4392
|
console.log(" \u{1F680} Visit my site: https://wiiiimm.codes");
|
|
4353
4393
|
console.log(" \u{1F4AC} Leave feedback: https://github.com/wiiiimm/gh-manager-cli");
|
|
4354
|
-
console.log("\nYour support
|
|
4394
|
+
console.log("\nYour support keeps this project alive! \u{1F64F}\n");
|
|
4355
4395
|
console.log("\u2500".repeat(60) + "\n");
|
|
4356
4396
|
};
|
|
4357
4397
|
process.on("SIGINT", () => handleShutdown("SIGINT"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gh-manager-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.38.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "TUI terminal app to manage GitHub repos. Clean up your account in 5 minutes. Archive, delete, rename repos with keyboard shortcuts. Alternative to clicking through github.com",
|
|
6
6
|
"license": "MIT",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"semantic-release": "^24.2.7",
|
|
82
82
|
"tsup": "^8.5.0",
|
|
83
83
|
"typescript": "^5.9.2",
|
|
84
|
-
"vitest": "^
|
|
84
|
+
"vitest": "^4.1.0"
|
|
85
85
|
},
|
|
86
86
|
"repository": {
|
|
87
87
|
"type": "git",
|