github-search-cli 9.5.0 → 9.6.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "github-search-cli",
3
- "version": "9.5.0",
3
+ "version": "9.6.0",
4
4
  "description": "Search GitHub from your terminal — repo search, trending repos, npm package search, bookmarks, deep-dive, compare, export. Keyboard-driven TUI + pipeable CLI.",
5
5
  "type": "module",
6
6
  "packageManager": "bun@1",
@@ -0,0 +1,36 @@
1
+ # What's New in ghfind 9.5.1
2
+
3
+ Two TUI bugs in the landing menu and the update panel, plus test-isolation work.
4
+
5
+ ### Fixed
6
+
7
+ **Landing-screen keys no longer leak into the main view**
8
+
9
+ - Pressing `/` on the landing menu focused the search input on top of it
10
+ - `Space`, `t`, `c`, `?`, and `q` all double-fired through the second key
11
+ listener — help opened and instantly closed, quit ran cleanup twice
12
+ - The landing handler now claims its keys with `stopPropagation()` via the
13
+ `landingKeysActive` / `landingConsumesKey` seam, and the global handler
14
+ ignores everything while the landing menu owns the screen
15
+ - Also fixed while routing keys: `b` on the landing screen opens bookmarks
16
+ (hint bar updated), and overlays opened from landing hide the menu instead
17
+ of drawing on top of it
18
+
19
+ **Update panel no longer clips the changelog**
20
+
21
+ - The modal was hard-capped at 16 rows with the release notes in a single
22
+ unsized text block, so anything past the first ~10 lines was invisible
23
+ - The notes area is now a scrollable region (same mechanics as the
24
+ README/org viewers): `↑↓`/`j`/`k` move a fifth of a page,
25
+ `PageUp`/`PageDown` and `Home`/`End` jump, and a scrollbar appears when
26
+ content overflows
27
+ - The panel is taller (24 rows), scroll position resets each time it opens,
28
+ and notes render at the panel's real width so wrapped lines don't clip
29
+ horizontally on narrow terminals
30
+
31
+ ### Internal
32
+
33
+ - Seven test suites built temp dirs from a `Date.now()` stamp
34
+ (`tmpdir()/<name>-<ms>`), a name two concurrent `bun test` processes can
35
+ collide on. They now use `mkdtempSync`, and the login
36
+ `readGhCliToken` / `persistToken` dirs are cleaned up after use
@@ -0,0 +1,67 @@
1
+ # What's New in ghfind 9.6.0
2
+
3
+ ghfind now speaks the Model Context Protocol — your coding agent can search
4
+ GitHub through it — plus a curl installer and quieter output for `NO_COLOR`
5
+ users.
6
+
7
+ ### Added
8
+
9
+ **MCP server (beta) (`ghfind mcp`)** — ghfind as a tool server for coding agents
10
+
11
+ - Any MCP client (Claude Code, Cursor, Codex, …) can call GitHub search as
12
+ tools over stdio; zero new dependencies, a small JSON-RPC 2.0 layer over
13
+ the existing modules
14
+ - Nine tools: `ghfind_search_repos`, `ghfind_trending`, `ghfind_npm_packages`,
15
+ `ghfind_org_profile`, `ghfind_user_profile`, `ghfind_compare_repos`,
16
+ `ghfind_deep_dive`, `ghfind_bookmarked_releases`, `ghfind_skill`
17
+ - Implements the 2025-06-18 lifecycle (initialize → initialized notification →
18
+ operation); also speaks 2025-03-26 and 2024-11-05
19
+ - Tool failures report as `isError` results per spec — the agent sees the
20
+ error, not a hang
21
+ - Agent searches land in the TUI history like your own searches
22
+ - `ghfind mcp --token <t>` pins a token; otherwise config / `GITHUB_TOKEN`
23
+ applies as usual
24
+
25
+ **`ghfind skill [name]` (beta)** — a token-efficient usage guide for coding agents
26
+
27
+ - Search syntax, flags, rate limits, and token-efficiency tips, so agents
28
+ stop guessing from `--help`
29
+ - Bare `ghfind skill` lists the catalog; the registry (`src/agent-skill.ts`)
30
+ is generic, so third parties can register their own skills alongside the
31
+ built-in `ghfind-cli` one
32
+
33
+ **Trending language filter** — `ghfind trending` accepts a language slug
34
+ (`rust`, `python`, …), validated against the known language list; unknown
35
+ slugs are dropped instead of scraping an error page. Also exposed to agents
36
+ via the `ghfind_trending` MCP tool. _(The MCP server and agent skill are
37
+ beta — surface may still shift in 9.6.x patch releases.)_
38
+
39
+ **curl installer** — no Node.js needed
40
+
41
+ ```sh
42
+ curl -fsSL https://raw.githubusercontent.com/codersdfs/search-cli/main/scripts/install.sh | sh
43
+ ```
44
+
45
+ - Detects OS and arch, downloads the standalone `ghfind` binary from GitHub
46
+ Releases, verifies it against the release's `SHA256SUMS.txt`, and installs
47
+ to `~/.local/bin` (or `/usr/local/bin`, overridable with
48
+ `GHFIND_INSTALL_DIR`) — never needs sudo, prints a PATH hint if needed
49
+ - Every release now ships a merged `SHA256SUMS.txt` alongside the binaries,
50
+ so package maintainers can verify the same way
51
+
52
+ **`NO_COLOR` support** — `ghfind --doctor` stops emitting ANSI color codes
53
+ when `NO_COLOR` is set (any value, per no-color.org) or when stdout is not a
54
+ TTY. Piping `--doctor` into a file or CI log no longer drags escape codes
55
+ along.
56
+
57
+ ### Fixed
58
+
59
+ - **`scripts/brew.rb` was stale and broken** — pointed at the wrong repo
60
+ (`frank/search-cli`), version 0.1.0, and `search-cli-*` asset names that
61
+ never matched the release artifacts. Now targets `codersdfs/search-cli`
62
+ releases with the correct `ghfind-*` names (plus linux-arm64), a livecheck
63
+ block, and a version-pinning test.
64
+ - **Community health files** — `SECURITY.md` (private vulnerability
65
+ reporting), `CODE_OF_CONDUCT.md` (Contributor Covenant 2.1), and
66
+ `SUPPORT.md` (routes you to `--doctor` first) now exist, so security
67
+ reports and "it doesn't work" issues have proper homes.
package/scripts/brew.rb CHANGED
@@ -1,32 +1,53 @@
1
1
  # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
- class SearchCli < Formula
5
- desc "Interactive GitHub repository browser for the terminal"
6
- homepage "https://github.com/frank/search-cli"
7
- version "0.1.0"
4
+ # Homebrew formula for ghfind.
5
+ #
6
+ # NOTE: this file is a template, kept in-tree for a future homebrew tap.
7
+ # Before use:
8
+ # 1. Replace VERSION with the released version tag.
9
+ # 2. Fill SHA256 placeholders from the SHA256SUMS.txt asset attached to
10
+ # the GitHub Release (the release workflow generates it).
11
+ # 3. Host it in a tap repo (e.g. codersdfs/tap) at Formula/ghfind.rb,
12
+ # then: brew install codersdfs/tap/ghfind
13
+ # See marketing/README.md (Track B) for the rollout order.
14
+
15
+ class Ghfind < Formula
16
+ desc "Search GitHub repos from your terminal — trending, bookmarks, deep-dive"
17
+ homepage "https://github.com/codersdfs/search-cli"
18
+ version "9.5.1"
8
19
  license "MIT"
9
20
 
21
+ livecheck do
22
+ url :stable
23
+ regex(/^v?(\d+(?:\.\d+)+)$/i)
24
+ end
25
+
10
26
  on_macos do
11
27
  if Hardware::CPU.arm?
12
- url "https://github.com/frank/search-cli/releases/download/v#{version}/search-cli-darwin-arm64"
28
+ url "https://github.com/codersdfs/search-cli/releases/download/v#{version}/ghfind-darwin-arm64"
13
29
  sha256 "SHA256_PLACEHOLDER"
14
30
  else
15
- url "https://github.com/frank/search-cli/releases/download/v#{version}/search-cli-darwin-x64"
31
+ url "https://github.com/codersdfs/search-cli/releases/download/v#{version}/ghfind-darwin-x64"
16
32
  sha256 "SHA256_PLACEHOLDER"
17
33
  end
18
34
  end
19
35
 
20
36
  on_linux do
21
- url "https://github.com/frank/search-cli/releases/download/v#{version}/search-cli-linux-x64"
22
- sha256 "SHA256_PLACEHOLDER"
37
+ if Hardware::CPU.arm? && Hardware::CPU.is_64_bit?
38
+ url "https://github.com/codersdfs/search-cli/releases/download/v#{version}/ghfind-linux-arm64"
39
+ sha256 "SHA256_PLACEHOLDER"
40
+ else
41
+ url "https://github.com/codersdfs/search-cli/releases/download/v#{version}/ghfind-linux-x64"
42
+ sha256 "SHA256_PLACEHOLDER"
43
+ end
23
44
  end
24
45
 
25
46
  def install
26
- bin.install "search-cli"
47
+ bin.install "ghfind" => "ghfind"
27
48
  end
28
49
 
29
50
  test do
30
- assert_match "search-cli", shell_output("#{bin}/search-cli --version")
51
+ assert_match version.to_s, shell_output("#{bin}/ghfind --version")
31
52
  end
32
53
  end
@@ -0,0 +1,118 @@
1
+ #!/bin/sh
2
+ # ghfind installer — https://github.com/codersdfs/search-cli
3
+ #
4
+ # Usage:
5
+ # curl -fsSL https://raw.githubusercontent.com/codersdfs/search-cli/main/scripts/install.sh | sh
6
+ #
7
+ # Downloads the standalone ghfind binary for your platform from GitHub
8
+ # Releases (no Node.js or Bun needed) into ~/.local/bin, /usr/local/bin,
9
+ # or a directory of your choice via GHFIND_INSTALL_DIR.
10
+ #
11
+ # Options via environment:
12
+ # GHFIND_VERSION a release tag without the leading v (default: latest)
13
+ # GHFIND_INSTALL_DIR target dir (default: ~/.local/bin if writable)
14
+ #
15
+ # The script never needs sudo: if the default dir is not writable it falls
16
+ # back to ~/.local/bin and prints a PATH reminder.
17
+
18
+ set -eu
19
+
20
+ REPO="codersdfs/search-cli"
21
+
22
+ printf '\n' # cosmetic spacing when piped
23
+
24
+ # ── Detect platform ────────────────────────────────────────────────────
25
+ os=$(uname -s)
26
+ arch=$(uname -m)
27
+
28
+ case "$os" in
29
+ Linux) plat="linux" ;;
30
+ Darwin) plat="darwin" ;;
31
+ *)
32
+ printf 'ghfind install: unsupported OS "%s".\n' "$os"
33
+ printf 'Windows: install with npm (npm i -g github-search-cli) or scoop/winget once listed.\n' >&2
34
+ exit 1
35
+ ;;
36
+ esac
37
+
38
+ case "$arch" in
39
+ x86_64 | amd64) arch="x64" ;;
40
+ aarch64 | arm64) arch="arm64" ;;
41
+ *)
42
+ printf 'ghfind install: unsupported architecture "%s".\n' "$arch" >&2
43
+ exit 1
44
+ ;;
45
+ esac
46
+
47
+ asset="ghfind-${plat}-${arch}"
48
+
49
+ # ── Resolve version ────────────────────────────────────────────────────
50
+ if [ -n "${GHFIND_VERSION:-}" ]; then
51
+ version="$GHFIND_VERSION"
52
+ else
53
+ # Latest release tag, following redirects; avoids a jq dependency.
54
+ version=$(curl -fsSLI -o /dev/null -w '%{url_effective}' \
55
+ "https://github.com/${REPO}/releases/latest" | sed 's|.*/tag/v||')
56
+ if [ -z "$version" ] || [ "$version" = "latest" ]; then
57
+ printf 'ghfind install: could not resolve the latest release version.\n' >&2
58
+ exit 1
59
+ fi
60
+ fi
61
+
62
+ base_url="https://github.com/${REPO}/releases/download/v${version}"
63
+
64
+ # ── Pick install dir (never requires sudo) ─────────────────────────────
65
+ if [ -n "${GHFIND_INSTALL_DIR:-}" ]; then
66
+ install_dir="$GHFIND_INSTALL_DIR"
67
+ elif [ -w /usr/local/bin ] 2>/dev/null; then
68
+ install_dir="/usr/local/bin"
69
+ else
70
+ install_dir="${HOME}/.local/bin"
71
+ fi
72
+
73
+ mkdir -p "$install_dir"
74
+
75
+ # ── Download binary + checksum ─────────────────────────────────────────
76
+ tmp=$(mktemp -d)
77
+ trap 'rm -rf "$tmp"' EXIT
78
+
79
+ printf 'Installing ghfind %s (%s) -> %s\n' "$version" "$asset" "$install_dir"
80
+
81
+ curl -fsSL --retry 3 -o "$tmp/ghfind" "${base_url}/${asset}"
82
+ curl -fsSL --retry 3 -o "$tmp/SHA256SUMS.txt" "${base_url}/SHA256SUMS.txt" ||
83
+ printf 'warning: could not download SHA256SUMS.txt; skipping checksum verification\n'
84
+
85
+ # ── Verify checksum when we have the sums file ─────────────────────────
86
+ if [ -f "$tmp/SHA256SUMS.txt" ]; then
87
+ expected=$(grep " ${asset}\$" "$tmp/SHA256SUMS.txt" | awk '{print $1}')
88
+ if [ -n "$expected" ]; then
89
+ if command -v sha256sum >/dev/null 2>&1; then
90
+ actual=$(sha256sum "$tmp/ghfind" | awk '{print $1}')
91
+ elif command -v shasum >/dev/null 2>&1; then
92
+ actual=$(shasum -a 256 "$tmp/ghfind" | awk '{print $1}')
93
+ else
94
+ actual=""
95
+ printf 'warning: no sha256sum/shasum found; skipping checksum verification\n'
96
+ fi
97
+ if [ -n "$actual" ] && [ "$actual" != "$expected" ]; then
98
+ printf 'ghfind install: checksum mismatch!\n expected %s\n actual %s\n' "$expected" "$actual" >&2
99
+ exit 1
100
+ fi
101
+ [ -n "$actual" ] && printf 'Checksum OK (%s)\n' "$actual"
102
+ fi
103
+ fi
104
+
105
+ # ── Install ────────────────────────────────────────────────────────────
106
+ mv "$tmp/ghfind" "${install_dir}/ghfind"
107
+ chmod +x "${install_dir}/ghfind"
108
+
109
+ # ── PATH hint ──────────────────────────────────────────────────────────
110
+ case ":$PATH:" in
111
+ *":${install_dir}:"*) ;;
112
+ *)
113
+ printf '\nNOTE: %s is not in your PATH.\n' "$install_dir"
114
+ printf 'Add it, e.g.:\n echo '"'"'export PATH="%s:$PATH"'"'"' >> ~/.bashrc # or ~/.zshrc\n' "$install_dir"
115
+ ;;
116
+ esac
117
+
118
+ printf 'Done. Run: ghfind --version\n'
@@ -0,0 +1,140 @@
1
+ /**
2
+ * agent-skill.ts — `ghfind skill`: a compact, token-efficient usage guide for
3
+ * AI coding agents, and the module that owns the skill registry.
4
+ *
5
+ * Coding agents (Claude Code, Cursor, Codex, ...) burn tokens reading
6
+ * `--help` output, most of which explains the interactive TUI they cannot
7
+ * drive. `ghfind skill` prints a distilled, agent-shaped guide covering only
8
+ * the non-interactive surface, so an agent gets everything it needs in ~2 KB.
9
+ *
10
+ * The registry is deliberately generic: the built-in ghfind skill is the
11
+ * seed, and third parties can register their own skills alongside it
12
+ * (`registerSkill`) — the foundation of ghfind-as-an-agent-ecosystem.
13
+ */
14
+ import { getVersion } from "./version";
15
+
16
+ /** One invocable skill in the registry. */
17
+ export interface Skill {
18
+ /** Unique id, e.g. "ghfind-cli". Also the `ghfind skill <id>` selector. */
19
+ name: string;
20
+ /** Human-readable display name. */
21
+ title: string;
22
+ /** When the agent should reach for this skill. */
23
+ description: string;
24
+ /** The full skill body, printed to stdout by `ghfind skill <name>`. */
25
+ content: string;
26
+ /** Registrations that are not the built-in ghfind skill. */
27
+ builtin?: boolean;
28
+ }
29
+
30
+ /** Build the built-in ghfind CLI skill. A function so the version is read lazily. */
31
+ function buildGhfindSkill(): Skill {
32
+ return {
33
+ name: "ghfind-cli",
34
+ title: "ghfind CLI for agents",
35
+ description:
36
+ "Search GitHub (repos, trending, npm packages, org/user profiles) from the terminal via the `ghfind` command. Use when the user asks to find, compare, or track GitHub repositories or npm packages.",
37
+ builtin: true,
38
+ content: `# ghfind — GitHub search for agents
39
+
40
+ ghfind searches GitHub from the terminal: repositories, trending, npm
41
+ packages, org/user profiles. This guide covers the non-interactive surface
42
+ only — ignore anything about a TUI in other docs; agents cannot drive it.
43
+
44
+ ## Search GitHub repositories
45
+
46
+ ghfind "QUERY" --json [--limit N] [--sort best-match|stars|updated|forks]
47
+
48
+ Query language (GitHub search qualifiers):
49
+ language:Rust stars:>1000 topic:cli org:vercel user:torvalds
50
+ repo:facebook/react pushed:>2026-01-01 license:mit archived:false
51
+ "exact phrase" -language:JavaScript # quotes, negation
52
+
53
+ Formats: --json | --csv | --markdown | --count | --format urls|names|ssh-urls|clone-commands|ids
54
+
55
+ ## Trending repositories
56
+
57
+ ghfind --trending --json [--since daily|weekly|monthly]
58
+
59
+ ## npm packages
60
+
61
+ ghfind pkg "QUERY" --json [--limit N] [--sort best-match|score|downloads|name]
62
+
63
+ ## Org & user profiles
64
+
65
+ ghfind org vercel --json
66
+ ghfind user torvalds --json
67
+
68
+ ## Compare repositories
69
+
70
+ ghfind --compare owner/a owner/b [--json]
71
+ Compare is text-only; there is no JSON formatter for it yet.
72
+
73
+ ## Deep-dive a repo (languages, contributors, README)
74
+
75
+ Not exposed on the CLI. Fetch directly instead:
76
+ curl -s https://api.github.com/repos/OWNER/REPO/languages
77
+ curl -s https://raw.githubusercontent.com/OWNER/REPO/main/README.md
78
+
79
+ ## Rate limits
80
+
81
+ 60 req/hr unauthenticated, 5,000 with GITHUB_TOKEN (env var or \`ghfind login\`).
82
+ Responses are cached ~5 min, so repeated identical queries are cheap.
83
+
84
+ ## Bookmarking & release tracking
85
+
86
+ Bookmarks live in ghfind's local state, not GitHub. An agent can read the
87
+ release feed with:
88
+ ghfind --releases --json
89
+ Marking releases seen and editing bookmarks is a TUI action; skip it.
90
+
91
+ ## Token efficiency
92
+
93
+ Prefer --count when only the number of results matters, --format names when
94
+ you only need fullNames, and --limit to cap payload size (default 50, max 100).
95
+ `,
96
+ };
97
+ }
98
+
99
+ // ─── Registry ───────────────────────────────────────────────────────────
100
+
101
+ const registry = new Map<string, Skill>();
102
+
103
+ /** Register a skill. Overwrites an existing skill with the same name. */
104
+ export function registerSkill(skill: Skill): void {
105
+ registry.set(skill.name, skill);
106
+ }
107
+
108
+ /** Get a skill by name, or undefined. */
109
+ export function getSkill(name: string): Skill | undefined {
110
+ return registry.get(name);
111
+ }
112
+
113
+ /** All registered skills, built-ins first, then alphabetical. */
114
+ export function listSkills(): Skill[] {
115
+ return [...registry.values()].sort((a, b) => {
116
+ if (a.builtin !== b.builtin) return a.builtin ? -1 : 1;
117
+ return a.name.localeCompare(b.name);
118
+ });
119
+ }
120
+
121
+ /** Load the built-in ghfind skill into the registry (idempotent). */
122
+ export function ensureBuiltinSkill(): void {
123
+ if (!registry.has("ghfind-cli")) {
124
+ registerSkill(buildGhfindSkill());
125
+ }
126
+ }
127
+
128
+ /** Print the skill catalog (one line per skill) for `ghfind skill` with no id. */
129
+ export function formatSkillCatalog(): string {
130
+ ensureBuiltinSkill();
131
+ const lines = listSkills().map(
132
+ (s) => ` ${s.name.padEnd(16)} ${s.description}`,
133
+ );
134
+ return [
135
+ "Available agent skills:",
136
+ ...lines,
137
+ "",
138
+ `Run \`ghfind skill <name>\` to print one (ghfind v${getVersion()}).`,
139
+ ].join("\n");
140
+ }
package/src/cli.ts CHANGED
@@ -53,6 +53,13 @@ import { join, dirname } from "path";
53
53
  import { fileURLToPath } from "url";
54
54
  import { launchBrowser } from "./tui";
55
55
  import { getVersion } from "./version";
56
+ import { runMcpServer } from "./mcp-server";
57
+ import {
58
+ ensureBuiltinSkill,
59
+ formatSkillCatalog,
60
+ getSkill,
61
+ listSkills,
62
+ } from "./agent-skill";
56
63
  import type { SearchOptions } from "./types";
57
64
  import { SearchCliError } from "./errors";
58
65
 
@@ -87,6 +94,8 @@ interface CLIFlags {
87
94
  doctor: boolean;
88
95
  org?: string; // org profile lookup (ghfind org <name>)
89
96
  user?: string; // user profile lookup (ghfind user <name>)
97
+ mcp: boolean; // run the MCP server (ghfind mcp)
98
+ skill?: string; // agent skill guide (ghfind skill [name])
90
99
  }
91
100
 
92
101
  function parseArgs(args: string[]): CLIFlags {
@@ -112,6 +121,7 @@ function parseArgs(args: string[]): CLIFlags {
112
121
  registry: "npm",
113
122
  compare: [],
114
123
  doctor: false,
124
+ mcp: false,
115
125
  };
116
126
 
117
127
  let queryParts: string[] = [];
@@ -191,6 +201,20 @@ function parseArgs(args: string[]): CLIFlags {
191
201
  case "--completion":
192
202
  flags.completion = args[++i];
193
203
  break;
204
+ case "mcp":
205
+ flags.mcp = true;
206
+ break;
207
+ case "skill": {
208
+ // Optional skill id (ids contain no spaces); a following flag means none.
209
+ const next = args[i + 1];
210
+ if (next && !next.startsWith("-")) {
211
+ flags.skill = next;
212
+ i++;
213
+ } else {
214
+ flags.skill = "";
215
+ }
216
+ break;
217
+ }
194
218
  case "org": {
195
219
  // Collect org name until next flag (single token — GitHub org logins
196
220
  // contain no spaces; a quoted multi-word name is an error)
@@ -261,12 +285,13 @@ Usage:
261
285
  ghfind <query> --pipe <target> Pipe to clone/open
262
286
  ghfind --trending --json Trending repos as JSON
263
287
  ghfind --releases Check bookmarks for new releases
264
- ghfind --compare <repo1> <repo2> Compare two+ repos side-by-side
288
+ ghfind --compare <r1> <r2> Compare two+ repos side-by-side
265
289
  ghfind org <name> --json Org profile: repos, stars, top languages
266
290
  ghfind user <name> --json User profile: repos, stars, top languages
267
- ghfind user <name> --json User profile: repos, stars, top languages
268
- ghfind pkg <query> --json Search npm packages, output JSON
269
- ghfind pkg <query> Search npm packages, text list
291
+ ghfind pkg <query> --json Search npm packages, output JSON
292
+ ghfind pkg <query> Search npm packages, text list
293
+ ghfind mcp Run the MCP server for AI agents (stdio)
294
+ ghfind skill [name] Print the agent skill guide (or catalog)
270
295
  ghfind --watch <query> Watch mode (poll every Ns)
271
296
  ghfind init Run setup wizard
272
297
  ghfind login Import the gh CLI token or paste one
@@ -321,6 +346,18 @@ Options:
321
346
  await runLoginWizard();
322
347
  return;
323
348
  }
349
+
350
+ // MCP server — expose ghfind as tools to AI agents over stdio
351
+ if (flags.mcp) {
352
+ await runMcpServer({ token: flags.token });
353
+ return;
354
+ }
355
+
356
+ // Agent skill guide — token-efficient usage doc for coding agents
357
+ if (flags.skill !== undefined) {
358
+ printAgentSkill(flags.skill);
359
+ return;
360
+ }
324
361
  // Package search (prototype, ticket 002-008)
325
362
  if (flags.pkg) {
326
363
  const interactive =
@@ -396,6 +433,25 @@ function buildSearchContext(flags: CLIFlags): SearchContext {
396
433
  };
397
434
  }
398
435
 
436
+ /** `ghfind skill [name]` — print the agent skill catalog or one skill's content. */
437
+ function printAgentSkill(name: string): void {
438
+ ensureBuiltinSkill();
439
+ if (!name) {
440
+ console.log(formatSkillCatalog());
441
+ return;
442
+ }
443
+ const skill = getSkill(name);
444
+ if (!skill) {
445
+ console.error(
446
+ `Unknown skill: ${name}. Available: ${listSkills()
447
+ .map((s) => s.name)
448
+ .join(", ")}`,
449
+ );
450
+ process.exit(1);
451
+ }
452
+ console.log(skill.content);
453
+ }
454
+
399
455
  /** `ghfind user <name>` — aggregate user profile: metadata, stars, top languages, top repos. */
400
456
  async function runUserProfile(
401
457
  flags: CLIFlags,
package/src/doctor.ts CHANGED
@@ -237,7 +237,11 @@ function checkDirs(): void {
237
237
  }
238
238
 
239
239
  function printReport(): void {
240
+ // Respect NO_COLOR (https://no-color.org/): plain text when set (any value,
241
+ // including the empty string) or when stdout is not a TTY.
242
+ const noColor = process.env.NO_COLOR !== undefined || !process.stdout.isTTY;
240
243
  const colors = (s: string, n: CheckStatus) => {
244
+ if (noColor) return s;
241
245
  const code =
242
246
  n === "PASS" ? "\x1b[32m" : n === "WARN" ? "\x1b[33m" : "\x1b[31m";
243
247
  return `${code}${s}\x1b[0m`;
package/src/help.ts CHANGED
@@ -82,6 +82,10 @@ export function buildHelpSections(): HelpSection[] {
82
82
  { keys: "Packages", action: "Switch to npm packages" },
83
83
  { keys: "Export", action: "Export results to file" },
84
84
  { keys: "Share", action: "Share repo as text" },
85
+ {
86
+ keys: "Org profile",
87
+ action: "Org summary: repos, stars, top languages",
88
+ },
85
89
  { keys: "Topics", action: "Browse GitHub topics" },
86
90
  { keys: "Saved", action: "View saved searches" },
87
91
  { keys: "Notifs", action: "Check GitHub notifications" },