github-search-cli 9.8.1 → 9.8.2

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
@@ -6,6 +6,69 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). Publish
6
6
 
7
7
  ---
8
8
 
9
+ ## [9.8.2] — 2026-09-28 (released)
10
+
11
+ ### Security
12
+
13
+ - **GitHub tokens no longer leak into crash reports.** An uncaught error
14
+ auto-built a GitHub issue URL from the raw `process.argv`, so a token passed
15
+ as `--token` ended up in a public URL. Every field is now redacted before it
16
+ reaches the URL, title, body or stack trace, and when a credential is
17
+ detected ghfind prints the URL to copy instead of opening a browser.
18
+ - **Your token is never sent to `raw.githubusercontent.com`** when fetching a
19
+ README. It is only attached to `api.github.com` requests, and only for a
20
+ repository marked private.
21
+ - **Untrusted skill sources are validated** before they can reach a shell
22
+ command or URL. A `source` or `skillId` containing shell metacharacters
23
+ (`;`, `$`, backticks, newlines, path traversal) is now dropped from
24
+ registry results instead of being interpolated into `npx skills add`.
25
+ - **The config file holding your token is written with `0600` permissions**
26
+ (effective on POSIX; on Windows the file still inherits the directory ACL).
27
+ - `--doctor` masks the token with `maskToken()` instead of printing a
28
+ raw 7-character prefix.
29
+
30
+ ### Fixed
31
+
32
+ - **Recoverable errors no longer open a bug-report tab.** The catch in
33
+ `src/cli.ts` tested `err.name === "SearchCliError"`, which is never true
34
+ because each subclass sets its own name, so rate-limit, network and
35
+ layout-change errors all fell through to the crash reporter. Routing now uses
36
+ `instanceof SearchCliError`.
37
+ - **`--compare` and the MCP tool `ghfind_compare_repos` resolve repos
38
+ exactly.** Both used a free-text search with no `repo:` qualifier and never
39
+ checked the returned `fullName`, so they could silently compare a different
40
+ repository. They now use the existing `resolveRepoFromRef()` seam
41
+ (`GET /repos/{owner}/{repo}`).
42
+ - **State files are written atomically.** Bookmarks, history, sessions, saved
43
+ searches, notifications and the update check were written straight to their
44
+ live path; a crash or a full disk left a truncated JSON file that was then
45
+ silently replaced with defaults, destroying user data. Writes now go to a
46
+ temp file and are renamed into place.
47
+ - **Notification IDs no longer restart** after "dismiss all" — the id counter
48
+ was recomputed from an already-empty list.
49
+ - **`ghfind history --delete` no longer removes every duplicate entry.** The
50
+ delete matched by value instead of by index.
51
+ - **An invalid `--sort` value is rejected** with the list of valid choices and
52
+ a non-zero exit code instead of silently degrading to the default.
53
+ - **A failed "load more" in the TUI no longer clears the results** already on
54
+ screen; the error goes to the status bar.
55
+ - **`--markdown` escapes `|` in cells**, matching `--csv`.
56
+ - Local skill scanning is memoised per process, so a search no longer re-walks
57
+ the skill roots on every keystroke.
58
+ - `MemoryCache.set` is a true LRU — a refreshed entry now moves to the end of
59
+ the insertion order.
60
+ - Skill ids and sources may contain `_` (e.g. `my_org/my_repo`), which
61
+ are common on GitHub and were wrongly rejected.
62
+
63
+ ### Changed
64
+
65
+ - **`postinstall` and the bundled agent skill are unchanged in behaviour**; the
66
+ skill now states that `--compare` resolves a repository exactly.
67
+ - Internal `--compare` resolution is now shared by the CLI and the MCP server
68
+ instead of duplicated in both.
69
+
70
+ ---
71
+
9
72
  ## [9.8.1] — 2026-09-26 (released)
10
73
 
11
74
  ### Added
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2026 search-cli contributors
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2026 search-cli contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -313,7 +313,7 @@ cd ghfind
313
313
  # With Bun (recommended for TUI)
314
314
  bun install
315
315
  bun start # TUI
316
- bun test # 414 tests
316
+ bun test # 482 tests
317
317
  bun run check # format check + tests — the green gate
318
318
  bun run build # build dist/
319
319
 
@@ -355,6 +355,16 @@ for the measurements and the remaining work.
355
355
 
356
356
  Recent releases (full history in [CHANGELOG.md](CHANGELOG.md)):
357
357
 
358
+ ### v9.8.2
359
+
360
+ - **Security: tokens no longer leak into crash reports** — an uncaught error auto-built a GitHub issue URL from raw `process.argv`, so a `--token` value ended up in a public URL; every field is redacted now, and ghfind prints the URL to copy instead of opening a browser when it finds a credential
361
+ - **Security: your token is never sent to `raw.githubusercontent.com`** when fetching a README, only to `api.github.com` and only for a private repo
362
+ - **Security: untrusted skill sources are validated** before reaching a shell command or URL, so a hostile skills.sh entry cannot inject into `npx skills add`
363
+ - **Recoverable errors no longer open a bug-report tab** — rate limits, network blips and layout changes print a short message and exit
364
+ - **`--compare` resolves repositories exactly** in both the CLI and the `ghfind_compare_repos` MCP tool; it used a free-text search that could silently compare the wrong repo
365
+ - **State files are written atomically** — a crash mid-write used to leave truncated JSON that was silently replaced with defaults, losing bookmarks and history
366
+ - Fixed notification IDs restarting after "dismiss all", `history --delete` removing every duplicate, an invalid `--sort` degrading silently, a failed "load more" clearing the TUI's results, `--markdown` not escaping `|`, and a not-quite-LRU memory cache
367
+
358
368
  ### v9.8.1
359
369
 
360
370
  - **`ghfind skill search <query>`** finds agent skills by keyword and prints why
@@ -376,13 +386,6 @@ Recent releases (full history in [CHANGELOG.md](CHANGELOG.md)):
376
386
  - **Images render inline — see [Known limitations](#known-limitations)** — relative and `/`-rooted paths resolve against the README's branch, `github.com/.../blob/...` links are rewritten to raw content, downloads are cached and size-capped, SVG and badge-service images are skipped, and anything unloadable falls back to an `🖼 alt` caption; press `i` in the viewer to toggle images
377
387
  - **No new dependencies** — the PNG decoder, image-to-cells rasteriser, and fetch cache are plain TypeScript, and images draw with truecolor half blocks, so they work on any truecolor terminal without image-protocol support
378
388
 
379
- ### v9.7.1
380
-
381
- - **In-app update actually works now** — it used to `bun install -g` into `~/.bun` while your running copy lives in an npm prefix, reporting success while nothing changed; it now detects which package manager owns the running install and updates it in place
382
- - **New `ghfind --doctor` check** — flags stale/PATH-shadowing global installs (multiple `ghfind` copies with different versions) and prints the exact uninstall command
383
- - **Windows URL fix** — links with query params were truncated at the first `&` by `cmd /c start`; every pre-filled crash-report/issue link now opens complete
384
- - Fixed `open-url` crashing under Node; CI now enforces lint + typecheck gates (first green Biome baseline)
385
-
386
389
  ## License
387
390
 
388
391
  MIT
@@ -1,55 +1,55 @@
1
- # ghfind bash completion
2
- # Source: source <(ghfind --completion bash)
3
-
4
- _ghfind() {
5
- local cur prev opts
6
- COMPREPLY=()
7
- cur="${COMP_WORDS[COMP_CWORD]}"
8
- prev="${COMP_WORDS[COMP_CWORD-1]}"
9
-
10
- opts="--json --csv --markdown --count --limit --sort --token --trending --language --since --pipe --format --registry --watch --interval --version --help --completion --remote --local --copy --raw --as pkg login init doctor org user mcp skill bookmarks history topics saved readme share trending deep-dive compare"
11
-
12
- case "${prev}" in
13
- --sort)
14
- COMPREPLY=( $(compgen -W "best-match stars updated forks" -- "${cur}") )
15
- return 0
16
- ;;
17
- --since)
18
- COMPREPLY=( $(compgen -W "daily weekly monthly" -- "${cur}") )
19
- return 0
20
- ;;
21
- --pipe)
22
- COMPREPLY=( $(compgen -W "clone open" -- "${cur}") )
23
- return 0
24
- ;;
25
- --format)
26
- COMPREPLY=( $(compgen -W "urls names ssh-urls clone-commands ids" -- "${cur}") )
27
- return 0
28
- ;;
29
- --completion)
30
- COMPREPLY=( $(compgen -W "bash zsh fish" -- "${cur}") )
31
- return 0
32
- ;;
33
- --as)
34
- COMPREPLY=( $(compgen -W "markdown plain gh-cli short" -- "${cur}") )
35
- return 0
36
- ;;
37
- --registry)
38
- COMPREPLY=( $(compgen -W "npm" -- "${cur}") )
39
- return 0
40
- ;;
41
- --language)
42
- COMPREPLY=( $(compgen -W "rust python typescript javascript go c c++ c# java ruby php swift kotlin zig" -- "${cur}") )
43
- return 0
44
- ;;
45
- --limit|--interval)
46
- return 0
47
- ;;
48
- *)
49
- ;;
50
- esac
51
-
52
- COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
53
- return 0
54
- }
55
- complete -F _ghfind ghfind
1
+ # ghfind bash completion
2
+ # Source: source <(ghfind --completion bash)
3
+
4
+ _ghfind() {
5
+ local cur prev opts
6
+ COMPREPLY=()
7
+ cur="${COMP_WORDS[COMP_CWORD]}"
8
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
9
+
10
+ opts="--json --csv --markdown --count --limit --sort --token --trending --language --since --pipe --format --registry --watch --interval --version --help --completion --remote --local --copy --raw --as pkg login init doctor org user mcp skill bookmarks history topics saved readme share trending deep-dive compare"
11
+
12
+ case "${prev}" in
13
+ --sort)
14
+ COMPREPLY=( $(compgen -W "best-match stars updated forks" -- "${cur}") )
15
+ return 0
16
+ ;;
17
+ --since)
18
+ COMPREPLY=( $(compgen -W "daily weekly monthly" -- "${cur}") )
19
+ return 0
20
+ ;;
21
+ --pipe)
22
+ COMPREPLY=( $(compgen -W "clone open" -- "${cur}") )
23
+ return 0
24
+ ;;
25
+ --format)
26
+ COMPREPLY=( $(compgen -W "urls names ssh-urls clone-commands ids" -- "${cur}") )
27
+ return 0
28
+ ;;
29
+ --completion)
30
+ COMPREPLY=( $(compgen -W "bash zsh fish" -- "${cur}") )
31
+ return 0
32
+ ;;
33
+ --as)
34
+ COMPREPLY=( $(compgen -W "markdown plain gh-cli short" -- "${cur}") )
35
+ return 0
36
+ ;;
37
+ --registry)
38
+ COMPREPLY=( $(compgen -W "npm" -- "${cur}") )
39
+ return 0
40
+ ;;
41
+ --language)
42
+ COMPREPLY=( $(compgen -W "rust python typescript javascript go c c++ c# java ruby php swift kotlin zig" -- "${cur}") )
43
+ return 0
44
+ ;;
45
+ --limit|--interval)
46
+ return 0
47
+ ;;
48
+ *)
49
+ ;;
50
+ esac
51
+
52
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
53
+ return 0
54
+ }
55
+ complete -F _ghfind ghfind
@@ -1,29 +1,29 @@
1
- # ghfind fish completion
2
- # Source: source (ghfind --completion fish | psub)
3
-
4
- complete -c ghfind -l json -d "JSON output"
5
- complete -c ghfind -l csv -d "CSV output"
6
- complete -c ghfind -l markdown -d "Markdown table output"
7
- complete -c ghfind -l count -d "Only result count"
8
- complete -c ghfind -l limit -d "Max results" -r
9
- complete -c ghfind -l sort -d "Sort strategy" -r -f -a "best-match stars updated forks"
10
- complete -c ghfind -l token -d "GitHub token" -r
11
- complete -c ghfind -l trending -d "Trending mode"
12
- complete -c ghfind -l language -d "Trending language filter" -r -f -a "rust python typescript javascript go c c++ c# java ruby php swift kotlin zig"
13
- complete -c ghfind -l since -d "Trending period" -r -f -a "daily weekly monthly"
14
- complete -c ghfind -l pipe -d "Pipe target" -r -f -a "clone open"
15
- complete -c ghfind -l format -d "Output format" -r -f -a "urls names ssh-urls clone-commands ids"
16
- complete -c ghfind -l registry -d "Registry for pkg" -r -f -a "npm"
17
-
18
- complete -c ghfind -l watch -d "Watch mode"
19
- complete -c ghfind -l interval -d "Watch interval seconds" -r
20
- complete -c ghfind -l version -d "Print version"
21
- complete -c ghfind -l help -d "Print help"
22
- complete -c ghfind -l completion -d "Shell" -r -f -a "bash zsh fish"
23
- complete -c ghfind -l as -d "Share format" -r -f -a "markdown plain gh-cli short"
24
- complete -c ghfind -l remote -d "Skill search: query skills.sh instead of this machine"
25
- complete -c ghfind -l local -d "Skill search: force the local scan (default)"
26
- complete -c ghfind -l copy -d "Share: also copy the snippet to the clipboard"
27
- complete -c ghfind -l raw -d "Readme: print the raw markdown with no header"
28
-
1
+ # ghfind fish completion
2
+ # Source: source (ghfind --completion fish | psub)
3
+
4
+ complete -c ghfind -l json -d "JSON output"
5
+ complete -c ghfind -l csv -d "CSV output"
6
+ complete -c ghfind -l markdown -d "Markdown table output"
7
+ complete -c ghfind -l count -d "Only result count"
8
+ complete -c ghfind -l limit -d "Max results" -r
9
+ complete -c ghfind -l sort -d "Sort strategy" -r -f -a "best-match stars updated forks"
10
+ complete -c ghfind -l token -d "GitHub token" -r
11
+ complete -c ghfind -l trending -d "Trending mode"
12
+ complete -c ghfind -l language -d "Trending language filter" -r -f -a "rust python typescript javascript go c c++ c# java ruby php swift kotlin zig"
13
+ complete -c ghfind -l since -d "Trending period" -r -f -a "daily weekly monthly"
14
+ complete -c ghfind -l pipe -d "Pipe target" -r -f -a "clone open"
15
+ complete -c ghfind -l format -d "Output format" -r -f -a "urls names ssh-urls clone-commands ids"
16
+ complete -c ghfind -l registry -d "Registry for pkg" -r -f -a "npm"
17
+
18
+ complete -c ghfind -l watch -d "Watch mode"
19
+ complete -c ghfind -l interval -d "Watch interval seconds" -r
20
+ complete -c ghfind -l version -d "Print version"
21
+ complete -c ghfind -l help -d "Print help"
22
+ complete -c ghfind -l completion -d "Shell" -r -f -a "bash zsh fish"
23
+ complete -c ghfind -l as -d "Share format" -r -f -a "markdown plain gh-cli short"
24
+ complete -c ghfind -l remote -d "Skill search: query skills.sh instead of this machine"
25
+ complete -c ghfind -l local -d "Skill search: force the local scan (default)"
26
+ complete -c ghfind -l copy -d "Share: also copy the snippet to the clipboard"
27
+ complete -c ghfind -l raw -d "Readme: print the raw markdown with no header"
28
+
29
29
  complete -c ghfind -f -a "login init doctor org user bookmarks history topics saved readme share pkg mcp skill trending deep-dive compare"
@@ -1,53 +1,53 @@
1
- # ghfind zsh completion
2
- # Source: source <(ghfind --completion zsh)
3
-
4
- _ghfind() {
5
- local -a opts
6
- opts=(
7
- '--json[JSON output]'
8
- '--csv[CSV output]'
9
- '--markdown[Markdown table output]'
10
- '--count[Only result count]'
11
- '--limit[Max results]:limit:'
12
- '--sort[Sort strategy]:(best-match stars updated forks)'
13
- '--token[GitHub token]:token:'
14
- '--trending[Trending mode]'
15
- '--language[Trending language filter]:language:'
16
- '--since[Trending period]:(daily weekly monthly)'
17
- '--pipe[Pipe target]:(clone open)'
18
- '--format[Output format]:(urls names ssh-urls clone-commands ids)'
19
- '--registry[Registry for pkg]:(npm)'
20
-
21
- '--watch[Watch mode]'
22
- '--interval[Watch interval seconds]:seconds:'
23
- '--version[Print version]'
24
- '--help[Print help]'
25
- '--completion[Shell]:(bash zsh fish)'
26
- '--as[Share format]:(markdown plain gh-cli short)'
27
- '--remote[Skill search: query skills.sh instead of this machine]'
28
- '--local[Skill search: force the local scan (default)]'
29
- '--copy[Share: also copy the snippet to the clipboard]'
30
- '--raw[Readme: print the raw markdown with no header]'
31
-
32
- 'login[Import a GitHub token from the gh CLI or paste one]'
33
- 'init[Run the setup wizard]'
34
- 'doctor[Environment diagnostics]'
35
- 'org[Org profile]:org name:'
36
- 'user[User profile]:user name:'
37
- 'bookmarks[List saved repos]:query:'
38
- 'history[List past searches]:query:'
39
- 'topics[Browse popular GitHub topics]'
40
- 'saved[List saved searches]'
41
- 'readme[Print a repository README]:owner/repo:'
42
- 'share[Print a share snippet]:owner/repo:'
43
- 'pkg[Search packages]:query:'
44
- 'trending[Trending repos, optionally by language]'
45
- 'deep-dive[Repo deep-dive: languages, contributors, README]:owner/repo:'
46
- 'mcp[Run the MCP server for AI agents (stdio)]'
47
- 'skill[Print an agent skill guide, or search with: skill search <query>]:skill name:'
48
- 'compare[Compare repositories]'
49
- )
50
- _arguments "${opts[@]}" '*:query:'
51
- }
52
-
1
+ # ghfind zsh completion
2
+ # Source: source <(ghfind --completion zsh)
3
+
4
+ _ghfind() {
5
+ local -a opts
6
+ opts=(
7
+ '--json[JSON output]'
8
+ '--csv[CSV output]'
9
+ '--markdown[Markdown table output]'
10
+ '--count[Only result count]'
11
+ '--limit[Max results]:limit:'
12
+ '--sort[Sort strategy]:(best-match stars updated forks)'
13
+ '--token[GitHub token]:token:'
14
+ '--trending[Trending mode]'
15
+ '--language[Trending language filter]:language:'
16
+ '--since[Trending period]:(daily weekly monthly)'
17
+ '--pipe[Pipe target]:(clone open)'
18
+ '--format[Output format]:(urls names ssh-urls clone-commands ids)'
19
+ '--registry[Registry for pkg]:(npm)'
20
+
21
+ '--watch[Watch mode]'
22
+ '--interval[Watch interval seconds]:seconds:'
23
+ '--version[Print version]'
24
+ '--help[Print help]'
25
+ '--completion[Shell]:(bash zsh fish)'
26
+ '--as[Share format]:(markdown plain gh-cli short)'
27
+ '--remote[Skill search: query skills.sh instead of this machine]'
28
+ '--local[Skill search: force the local scan (default)]'
29
+ '--copy[Share: also copy the snippet to the clipboard]'
30
+ '--raw[Readme: print the raw markdown with no header]'
31
+
32
+ 'login[Import a GitHub token from the gh CLI or paste one]'
33
+ 'init[Run the setup wizard]'
34
+ 'doctor[Environment diagnostics]'
35
+ 'org[Org profile]:org name:'
36
+ 'user[User profile]:user name:'
37
+ 'bookmarks[List saved repos]:query:'
38
+ 'history[List past searches]:query:'
39
+ 'topics[Browse popular GitHub topics]'
40
+ 'saved[List saved searches]'
41
+ 'readme[Print a repository README]:owner/repo:'
42
+ 'share[Print a share snippet]:owner/repo:'
43
+ 'pkg[Search packages]:query:'
44
+ 'trending[Trending repos, optionally by language]'
45
+ 'deep-dive[Repo deep-dive: languages, contributors, README]:owner/repo:'
46
+ 'mcp[Run the MCP server for AI agents (stdio)]'
47
+ 'skill[Print an agent skill guide, or search with: skill search <query>]:skill name:'
48
+ 'compare[Compare repositories]'
49
+ )
50
+ _arguments "${opts[@]}" '*:query:'
51
+ }
52
+
53
53
  compdef _ghfind ghfind
package/demo.svg CHANGED
@@ -1,71 +1,71 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 803" width="900" height="803">
3
- <defs>
4
- <style>
5
- @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&amp;display=swap');
6
- </style>
7
- <filter id="shadow" x="-5%" y="-5%" width="115%" height="115%">
8
- <feDropShadow dx="0" dy="4" stdDeviation="8" flood-color="#000" flood-opacity="0.4"/>
9
- </filter>
10
- </defs>
11
-
12
- <rect width="100%" height="100%" fill="#0d0d1a"/>
13
-
14
- <!-- Window -->
15
- <rect x="12" y="10" width="876" height="783" fill="#1a1b26" rx="8" filter="url(#shadow)"/>
16
- <rect x="12" y="10" width="876" height="36" fill="#16161e" rx="8"/>
17
- <rect x="12" y="46" width="876" height="2" fill="#24283b"/>
18
-
19
- <!-- Traffic lights -->
20
- <circle cx="24" cy="28" r="5" fill="#f7768e"/>
21
- <circle cx="42" cy="28" r="5" fill="#e0af68"/>
22
- <circle cx="60" cy="28" r="5" fill="#9ece6a"/>
23
- <text x="450" y="34" fill="#565f89" font-family="'JetBrains Mono','Fira Code',monospace" font-size="13" text-anchor="middle">ghfind — terminal GitHub browser</text>
24
-
25
- <g font-family="'JetBrains Mono','Fira Code','Cascadia Code',monospace" font-size="14">
26
- <text x="14" y="62" fill="#565f89" font-family="'JetBrains Mono','Fira Code','Cascadia Code',monospace" font-size="14">ghfind — GitHub repo browser [t]rending [/]search [g]raph [r]efresh [q]uit</text>
27
- <rect x="14" y="69" width="860" height="54.5" fill="#1a1b26" stroke="#7aa2f7" stroke-width="1" rx="3"/>
28
- <text x="22" y="88" fill="#7aa2f7" font-family="'JetBrains Mono','Fira Code','Cascadia Code',monospace" font-size="14">&gt; language:TypeScript stars:&gt;1000</text>
29
- <text x="14" y="150.2" fill="#565f89" font-family="'JetBrains Mono','Fira Code','Cascadia Code',monospace" font-size="14">sort: stars limit: 50 (s=cycle sort l=cycle limit)</text>
30
- <rect x="14" y="159.3" width="432" height="378" fill="#24283b" stroke="#1f2335" stroke-width="1"/>
31
- <!-- Search results list -->
32
- <rect x="14" y="159.3" width="432" height="19" fill="#7aa2f7" opacity="0.15"/>
33
- <text x="22" y="173" fill="#c0caf5">✓ facebook/react ★ 218k JavaScript</text>
34
- <text x="22" y="193" fill="#c0caf5">✓ vercel/next.js ★ 116k TypeScript</text>
35
- <text x="22" y="213" fill="#c0caf5">✓ microsoft/vscode ★ 158k TypeScript</text>
36
- <text x="22" y="233" fill="#c0caf5">✓ tanstack/router ★ 15k TypeScript</text>
37
- <text x="22" y="253" fill="#c0caf5">✓ tailwindlabs/tailwindcss ★ 81k TypeScript</text>
38
- <text x="22" y="273" fill="#c0caf5">✓ denoland/deno ★ 93k Rust</text>
39
- <text x="22" y="293" fill="#c0caf5">✓ oven-sh/bun ★ 65k TypeScript</text>
40
- <text x="22" y="313" fill="#c0caf5">✓ sagoie/open-tui ★ 3.2k TypeScript</text>
41
- <text x="22" y="333" fill="#e0af68">→ ghfind/cli ★ 4.8k TypeScript</text>
42
- <text x="22" y="353" fill="#c0caf5">✓ biomejs/biome ★ 28k Rust</text>
43
- <!-- ... more results ... -->
44
- <text x="14" y="525" fill="#565f89"> 10 of 847 results [Page 1/85]</text>
45
-
46
- <rect x="456" y="159.3" width="418" height="378" fill="#24283b" stroke="#1f2335" stroke-width="1"/>
47
- <!-- Right panel: repo info -->
48
- <text x="468" y="183" fill="#bb9af7" font-weight="bold">facebook/react</text>
49
- <text x="468" y="203" fill="#565f89">React is a JavaScript library for building user interfaces</text>
50
- <text x="468" y="228" fill="#e0af68">★ 218,847</text>
51
- <text x="540" y="228" fill="#565f89"> Forks: 46,231</text>
52
- <text x="468" y="248" fill="#9ece6a">License: MIT</text>
53
- <text x="468" y="268" fill="#7aa2f7">Language: JavaScript</text>
54
- <text x="468" y="293" fill="#c0caf5">Updated: today</text>
55
- <text x="468" y="318" fill="#565f89">Topics: react, javascript, ui, frontend, framework</text>
56
-
57
- <text x="468" y="348" fill="#7aa2f7" font-weight="bold">Description</text>
58
- <text x="468" y="368" fill="#c0caf5">A declarative, efficient, and flexible JavaScript library</text>
59
- <text x="468" y="383" fill="#c0caf5">for building user interfaces.</text>
60
-
61
- <text x="468" y="413" fill="#7aa2f7" font-weight="bold">README Preview</text>
62
- <text x="468" y="433" fill="#c0caf5"># React</text>
63
- <text x="468" y="453" fill="#565f89"> A JavaScript library for building user interfaces</text>
64
- <text x="468" y="478" fill="#565f89"> ──────────────────────────────────────────────────</text>
65
- <text x="468" y="503" fill="#c0caf5">React lets you build user interfaces out of individual</text>
66
- <text x="468" y="518" fill="#c0caf5">pieces called components.</text>
67
-
68
- <rect x="456" y="545" width="418" height="40" fill="#16161e" stroke="#1f2335"/>
69
- <text x="468" y="570" fill="#565f89"> [r]eadme [d]eepdive [→] open [h]elp [q]uit</text>
70
- </g>
71
- </svg>
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 803" width="900" height="803">
3
+ <defs>
4
+ <style>
5
+ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&amp;display=swap');
6
+ </style>
7
+ <filter id="shadow" x="-5%" y="-5%" width="115%" height="115%">
8
+ <feDropShadow dx="0" dy="4" stdDeviation="8" flood-color="#000" flood-opacity="0.4"/>
9
+ </filter>
10
+ </defs>
11
+
12
+ <rect width="100%" height="100%" fill="#0d0d1a"/>
13
+
14
+ <!-- Window -->
15
+ <rect x="12" y="10" width="876" height="783" fill="#1a1b26" rx="8" filter="url(#shadow)"/>
16
+ <rect x="12" y="10" width="876" height="36" fill="#16161e" rx="8"/>
17
+ <rect x="12" y="46" width="876" height="2" fill="#24283b"/>
18
+
19
+ <!-- Traffic lights -->
20
+ <circle cx="24" cy="28" r="5" fill="#f7768e"/>
21
+ <circle cx="42" cy="28" r="5" fill="#e0af68"/>
22
+ <circle cx="60" cy="28" r="5" fill="#9ece6a"/>
23
+ <text x="450" y="34" fill="#565f89" font-family="'JetBrains Mono','Fira Code',monospace" font-size="13" text-anchor="middle">ghfind — terminal GitHub browser</text>
24
+
25
+ <g font-family="'JetBrains Mono','Fira Code','Cascadia Code',monospace" font-size="14">
26
+ <text x="14" y="62" fill="#565f89" font-family="'JetBrains Mono','Fira Code','Cascadia Code',monospace" font-size="14">ghfind — GitHub repo browser [t]rending [/]search [g]raph [r]efresh [q]uit</text>
27
+ <rect x="14" y="69" width="860" height="54.5" fill="#1a1b26" stroke="#7aa2f7" stroke-width="1" rx="3"/>
28
+ <text x="22" y="88" fill="#7aa2f7" font-family="'JetBrains Mono','Fira Code','Cascadia Code',monospace" font-size="14">&gt; language:TypeScript stars:&gt;1000</text>
29
+ <text x="14" y="150.2" fill="#565f89" font-family="'JetBrains Mono','Fira Code','Cascadia Code',monospace" font-size="14">sort: stars limit: 50 (s=cycle sort l=cycle limit)</text>
30
+ <rect x="14" y="159.3" width="432" height="378" fill="#24283b" stroke="#1f2335" stroke-width="1"/>
31
+ <!-- Search results list -->
32
+ <rect x="14" y="159.3" width="432" height="19" fill="#7aa2f7" opacity="0.15"/>
33
+ <text x="22" y="173" fill="#c0caf5">✓ facebook/react ★ 218k JavaScript</text>
34
+ <text x="22" y="193" fill="#c0caf5">✓ vercel/next.js ★ 116k TypeScript</text>
35
+ <text x="22" y="213" fill="#c0caf5">✓ microsoft/vscode ★ 158k TypeScript</text>
36
+ <text x="22" y="233" fill="#c0caf5">✓ tanstack/router ★ 15k TypeScript</text>
37
+ <text x="22" y="253" fill="#c0caf5">✓ tailwindlabs/tailwindcss ★ 81k TypeScript</text>
38
+ <text x="22" y="273" fill="#c0caf5">✓ denoland/deno ★ 93k Rust</text>
39
+ <text x="22" y="293" fill="#c0caf5">✓ oven-sh/bun ★ 65k TypeScript</text>
40
+ <text x="22" y="313" fill="#c0caf5">✓ sagoie/open-tui ★ 3.2k TypeScript</text>
41
+ <text x="22" y="333" fill="#e0af68">→ ghfind/cli ★ 4.8k TypeScript</text>
42
+ <text x="22" y="353" fill="#c0caf5">✓ biomejs/biome ★ 28k Rust</text>
43
+ <!-- ... more results ... -->
44
+ <text x="14" y="525" fill="#565f89"> 10 of 847 results [Page 1/85]</text>
45
+
46
+ <rect x="456" y="159.3" width="418" height="378" fill="#24283b" stroke="#1f2335" stroke-width="1"/>
47
+ <!-- Right panel: repo info -->
48
+ <text x="468" y="183" fill="#bb9af7" font-weight="bold">facebook/react</text>
49
+ <text x="468" y="203" fill="#565f89">React is a JavaScript library for building user interfaces</text>
50
+ <text x="468" y="228" fill="#e0af68">★ 218,847</text>
51
+ <text x="540" y="228" fill="#565f89"> Forks: 46,231</text>
52
+ <text x="468" y="248" fill="#9ece6a">License: MIT</text>
53
+ <text x="468" y="268" fill="#7aa2f7">Language: JavaScript</text>
54
+ <text x="468" y="293" fill="#c0caf5">Updated: today</text>
55
+ <text x="468" y="318" fill="#565f89">Topics: react, javascript, ui, frontend, framework</text>
56
+
57
+ <text x="468" y="348" fill="#7aa2f7" font-weight="bold">Description</text>
58
+ <text x="468" y="368" fill="#c0caf5">A declarative, efficient, and flexible JavaScript library</text>
59
+ <text x="468" y="383" fill="#c0caf5">for building user interfaces.</text>
60
+
61
+ <text x="468" y="413" fill="#7aa2f7" font-weight="bold">README Preview</text>
62
+ <text x="468" y="433" fill="#c0caf5"># React</text>
63
+ <text x="468" y="453" fill="#565f89"> A JavaScript library for building user interfaces</text>
64
+ <text x="468" y="478" fill="#565f89"> ──────────────────────────────────────────────────</text>
65
+ <text x="468" y="503" fill="#c0caf5">React lets you build user interfaces out of individual</text>
66
+ <text x="468" y="518" fill="#c0caf5">pieces called components.</text>
67
+
68
+ <rect x="456" y="545" width="418" height="40" fill="#16161e" stroke="#1f2335"/>
69
+ <text x="468" y="570" fill="#565f89"> [r]eadme [d]eepdive [→] open [h]elp [q]uit</text>
70
+ </g>
71
+ </svg>