Commit Graph

104 Commits

Author SHA1 Message Date
github-actions[bot] b250c25156 chore(release): version packages (#2923) 2026-07-25 06:37:59 +03:00
Enes Gules 1c081df0b6 CTX7-1872: Improve Context7 documentation queries (#2941)
* focus Context7 documentation queries

* narrow documentation query prompt changes

* remove focused from query prompts

* use lookup wording in query prompts

* distinguish documentation lookup from task

* allow live Pi test more time

* add prompt guidance changeset
2026-07-25 06:23:59 +03:00
Fahreddin Özcan c82cc8afa0 fix(cli): fall back to direct SKILL.md fetch when GitHub tree API is unreachable (#2938)
The skill download step in `ctx7 setup` hits the git tree API on
api.github.com to enumerate a skill's files. When that host is blocked
or unreachable (while the docs host is fine), the fetch throws and setup
reports "Skill failed / fetch failed" (#2936).

Fall back to fetching the single SKILL.md directly from
raw.githubusercontent.com — the URL the docs API already resolves — so
single-file skills install even when api.github.com is not reachable.
2026-07-23 14:49:58 +03:00
mehmet turac 23843e9ce6 fix(cli): avoid shell for GitHub auth token (#2920)
* fix(cli): avoid shell for GitHub auth token

* fix(cli): document the shell-free constraint and harden gh token tests

Record why `gh auth token` must stay shell-free so the .cmd/.bat shim gap
is not "fixed" by re-adding `shell`, which would restore the cmd.exe
process that #2918 is about.

- reset mock implementations between tests so they stop leaking
- assert listSkillsFromGitHub's result; the tests passed green without it
- cover the GH_TOKEN fallback, which was previously untested
- reword the changeset: execSync spawned a shell on every platform, and
  on Windows that shell was load-bearing rather than "unnecessary"

---------

Co-authored-by: Fahreddin Özcan <ozcanfahrettinn@gmail.com>
2026-07-17 15:59:08 +03:00
github-actions[bot] 4124503867 chore(release): version packages (#2892)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-17 11:41:03 +03:00
Fahreddin Özcan e1b47937db CTX7-1839: Surface the real error when a CLI OAuth request fails (#2915) 2026-07-17 11:38:45 +03:00
Fahreddin Özcan c61a56543d chore(deps): combined dependabot updates (Node 20 compatible) (#2891) 2026-07-09 12:50:14 +03:00
github-actions[bot] 98baa58d36 chore(release): version packages (#2878) 2026-07-06 15:31:33 +03:00
Enes Gules 33229cb332 docs: enhance query descriptions for clarity and specificity (#2868)
* docs: enhance query descriptions for clarity and specificity

* update all propmts/skills

* format

* address pr review
2026-07-06 15:12:06 +03:00
石岳峰 84620bd483 fix(cli): align find-docs skill with context7-cli rule guidance (#2863)
Fixes #2860

- Use npx ctx7@latest as the canonical CLI invocation in find-docs SKILL.md
- Add official library naming guidance matching rules/context7-cli.md
- De-emphasize global npm install as the primary workflow
- Add regression tests to keep skill and rule guidance aligned

Co-authored-by: syf2211 <syf2211@users.noreply.github.com>
2026-07-03 11:33:46 +03:00
github-actions[bot] 9256fdfb9c chore(release): version packages (#2787) 2026-06-17 13:24:19 +03:00
Enes Gules acd0d4640e fix(cli): surface GitHub API error details when skill download fails (#2786)
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2026-06-17 13:22:29 +03:00
github-actions[bot] 0c53c6fb3e chore(release): version packages (#2731)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-11 16:33:50 +03:00
Fahreddin Özcan cb6aee187e chore(deps): combined dependabot dependency updates (#2737)
* chore(deps): bump dependencies (combined dependabot updates)

Combines the safe dependabot dependency bumps into a single change:

- @modelcontextprotocol/sdk 1.25.2 -> 1.29.0 (mcp)
- undici 6.26.0 -> 8.3.0 (mcp)
- zod 4.3.5 -> 4.4.3 (mcp, tools-ai-sdk)
- commander 13.1.0 -> 15.0.0 (cli)
- ora 9.0.0 -> 9.4.0 (cli)
- dotenv 17.2.3 -> 17.4.2 (sdk, tools-ai-sdk, pi)
- @earendil-works/pi-coding-agent 0.75.5 -> 0.78.0 (pi)

eslint 9 -> 10 (#2703) is excluded: it is incompatible with the
pinned typescript-eslint v8 and breaks lint.

Verified: build, typecheck, lint, and tests pass.

* chore: add changesets for runtime dependency bumps

* fix(deps): pin undici to 7.x for Node 20 compatibility

undici 8 requires Node >=22.19.0 (it calls worker_threads.markAsUncloneable
unconditionally at module load), but CI and the release pipeline run Node 20,
which crashed the mcp test suite with 'markAsUncloneable is not a function'.
undici 7.27.0 guards that call and supports Node >=20.18.1.
2026-06-09 13:21:58 +03:00
Fahreddin Özcan f327589a9a fix(sdk): avoid raw SyntaxError on non-JSON error responses (#2732)
* fix(sdk): avoid raw SyntaxError on non-JSON error responses

Wrap res.json() in the error path with .catch(() => ({})) so non-JSON
error bodies (HTML 502s, plain-text 429s, Cloudflare challenge pages)
fall through to res.statusText and always surface as a typed
Context7Error instead of a native SyntaxError.

Closes #1964

* chore: add changeset for sdk non-JSON error fix

* test(cli): pin home dir via HOME env instead of mocking os builtin

The storage-paths and auth-utils tests mocked the `os` module to fix
homedir, but that mock resolves inconsistently across Node versions and
worker pooling, leaking the real homedir on CI (/home/runner) and
failing 6 tests. os.homedir() reads $HOME first on POSIX, so stub HOME
(and clear XDG_* vars) for deterministic, order-independent paths with
no builtin-module mock. Also make the device-auth body assertion parse
client_id rather than matching the exact string, since hostname is
appended best-effort and varies by machine.
2026-06-09 11:47:14 +03:00
Fahreddin Özcan 428af3e067 fix(cli): recover library ID mangled by Git Bash on Windows (#2733)
* fix(cli): recover library ID mangled by Git Bash on Windows

Git Bash rewrites a leading-slash argument like /facebook/react into a
Windows path under the Git install dir (C:/Program Files/Git/facebook/react),
so "ctx7 docs" rejected it as an invalid library ID. This mainly affected
users running ctx7 through Claude Code.

Detect and undo the conversion before validation, and point users at the
//owner/repo escape for install layouts that aren't auto-detected.

* chore: add changeset
2026-06-08 16:42:10 +03:00
vincent 88c5b29e99 feat(cli): add -v short flag for version command (#2314)
Co-authored-by: liwenjun-dev <liwenjun.dev@gmail.com>
Co-authored-by: Enes Gules <101020733+enesgules@users.noreply.github.com>
2026-06-08 15:56:52 +03:00
Javier Gómez c03bc9c95b fix(cli): use XDG dirs for context files (#2678)
* fix(cli): use XDG dirs for context files

* fix(cli): harden XDG migration and cover previews dir

- Move `generate` previews to $XDG_CACHE_HOME/context7/previews (was the
  last writer recreating ~/.context7)
- Make legacy->XDG migration best-effort and fall back to reading the
  legacy file so loadTokens/readUpdateState never throw or silently log out
- Split update-check read (legacy fallback) from write (always XDG target)
- Ignore relative/empty XDG_* values per the spec
- Fix non-hermetic XDG_STATE_HOME test that moved the real ~/.context7
  cli-state into a temp dir; add storage-paths tests and a migration-failure
  fallback test

* chore: add changeset for XDG directories

* fix(cli): enforce 0o600 on credentials after migration

rename preserves the legacy file's mode, so a credentials file that was
group/world-readable in ~/.context7 stayed readable after migrating to the
XDG path. chmod the target to 0o600 on migrate, and re-assert it after every
write (writeFileSync's mode is ignored when the file already exists).

---------

Co-authored-by: Fahreddin Özcan <ozcanfahrettinn@gmail.com>
2026-06-08 15:19:23 +03:00
github-actions[bot] d82bcc9c9c chore(release): version packages (#2721)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-05 11:03:36 +03:00
Fahreddin Özcan ea91d7dc75 feat(cli): device-code flow is now the default for ctx7 login (#2720)
The localhost-callback path is gone. Every install — laptop, SSH,
Codespace, Docker, CI — goes through the same boxed prompt and
verification page. Three reasons to make this the default:

- The localhost flow was broken anywhere the browser couldn't reach
  127.0.0.1:52417 (SSH, Docker, Codespaces). Auto-detection via
  SSH_CONNECTION / $DISPLAY was a half-fix that depended on env
  vars users don't always set.
- Device flow works everywhere, has no random port-binding behavior,
  and still ends in the same long-lived ctx7sk- API key.
- One UX path is simpler to support than two.

Drops the --device flag (it was the opt-in for what's now the
default). Older CLI versions (<= 0.5.0) continue to work against the
unchanged auth endpoints, so pinned installs are unaffected.

The legacy localhost machinery in utils/auth.ts is left in place
for now — nothing imports it from commands/auth.ts anymore, and a
follow-up can delete it once we're confident no rollback is needed.
2026-06-04 15:31:45 +03:00
github-actions[bot] 22a6089546 chore(release): version packages (#2719)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-04 14:51:51 +03:00
Fahreddin Özcan 5a180d5b80 feat(cli): OAuth 2.0 device authorization flow (#2714)
* feat(cli): OAuth 2.0 device authorization flow

Adds RFC 8628 device-code login for headless / remote hosts (SSH,
Codespaces, Docker, CI) where the existing localhost-callback flow
can't work — the browser opens on the user's laptop while the
callback listener runs on the remote host, so the redirect target
is unreachable.

Device flow prints a verification URL and short code, then polls the
new /api/oauth/device/token endpoint. The user visits the URL on any
device, signs in, and approves; the CLI receives the same ctx7sk- API
key it would have gotten from the legacy flow.

- shouldUseDeviceFlow() auto-detects via SSH_CONNECTION /
  SSH_CLIENT / SSH_TTY and missing $DISPLAY on Linux.
- ctx7 login --device forces it. ctx7 setup picks it up
  automatically when resolveCliAuth needs to authenticate.
- pollDeviceToken returns a "transient" status for network errors
  and 5xx responses so a flaky backend or Upstash blip doesn't end
  the session — keeps polling until the device_code TTL elapses.

* polish(cli): boxed device-code prompt, Press-Enter, whoami success line

Tightens up the device-flow UX so it matches the patterns from gh /
stripe / wrangler:

- Wrap the user_code + verification URL in a boxen rounded box with
  a title, gray border, and the code as the visual headline (green
  bold, indented on its own line).
- Add a "Press Enter to open the browser, or Ctrl-C to quit..."
  confirmation step in TTY mode so the user can read the code before
  the browser steals focus. Skipped under --no-browser or non-TTY.
- Replace the generic "Login successful!" line with
  "Logged in as <email> (<team>)" by fetching /api/dashboard/whoami
  with the freshly minted token. Falls back to the old text if the
  call fails.
- Tighten the mockShouldUseDeviceFlow signature in the test mock so
  the spread-into-mock pattern typechecks.

No behavior change to the localhost-callback flow.

* test(cli): cover shouldUseDeviceFlow + start/poll + performDeviceLogin

auth-utils: SSH/$DISPLAY heuristics for shouldUseDeviceFlow; the
form-encoded start-device-authorization request shape and error
propagation; pollDeviceToken status mapping for each RFC 8628 code,
5xx -> transient, network error -> transient, and unknown 4xx ->
throw.

auth-commands: performDeviceLogin happy path (approved -> saveTokens
called), denied/expired return null and don't save, transient errors
keep polling instead of bailing, slow_down bumps the interval
(verified with fake timers), startDeviceAuthorization throwing exits
without polling, browser-open behavior under openBrowser=true/false.
Also covers the performLogin selector: forceDevice=true and
shouldUseDeviceFlow=true both route through performDeviceLogin
without hitting the localhost callback path.

28 new tests; suite is 235/235.

* docs(cli): tighten device-flow comments

Drop restatement; keep only WHY-bearing notes.

* fix(cli): default poll interval to 5s per RFC 8628 §3.2

The CLI was treating `interval` as required and would NaN-crash if
a future server omitted it. Spec requires clients to default to 5
when absent.

DeviceAuthorizationResponse.interval is now optional, and
performDeviceLogin uses DEFAULT_DEVICE_POLL_INTERVAL_SECONDS (5) as
the fallback. Test covers the missing-interval path.

* fix(cli): rfc 8628 spec gaps — backoff, hostname, bare verification_uri

Three small spec-compliance fixes from the §3.5 / §3.3 / §5.4 audit:

- §3.5: poll loop now bumps intervalMs by 5s on `transient` results
  (network errors and 5xx) — the RFC requires unilateral backoff on
  connection timeouts, and mirroring the slow_down handler is the
  simplest correct response.
- §3.3: the boxed prompt now prints the bare verification_uri
  alongside verification_uri_complete so screen readers / paper /
  another device can still type the short form.
- §5.4: startDeviceAuthorization sends `os.hostname()` so the server
  can show it on the verification page; the user can confirm the
  device they're authorizing matches the one running the CLI.

Transient-backoff test rewritten with fake timers (the new +5s wait
made the old real-timer assertion blow past the 5s default timeout).
2026-06-04 14:47:23 +03:00
github-actions[bot] c436700959 chore(release): version packages (#2712) 2026-06-02 18:55:18 +03:00
Fahreddin Özcan 268f52f813 fix(cli): --api-key alone no longer forces MCP mode in setup (#2713)
resolveMode treated --api-key as a non-interactive marker and
short-circuited to MCP, but --api-key is equally valid for CLI +
Skills mode (which authenticates skill downloads). Users who
preferred CLI mode were silently locked into MCP unless they
also passed --cli.

Remove options.apiKey from the auto-MCP OR-chain. --mcp / --cli /
--stdio / --oauth / -y still skip the prompt; --api-key alone now
falls through to the interactive mode picker.
2026-06-02 17:03:18 +03:00
Fahreddin Özcan 2affada9f9 fix(cli): wire --antigravity and remove broken --universal in setup (#2700)
* fix(cli): wire --antigravity and remove broken --universal in setup

The setup command advertised --universal and --antigravity flags but
neither was wired through getSelectedAgents, so passing them silently
fell back to auto-detection and wrote to the wrong directory (see #2695).

Remove --universal from setup entirely, and add a full Antigravity
SetupAgent config: skills under .agent/skills, MCP config at
~/.gemini/antigravity/mcp_config.json with serverUrl for HTTP, and
detection of .agent or ~/.gemini/antigravity.

* fix(cli): align antigravity setup with official Google docs

After verifying against Google Codelabs / Google Cloud Community
docs, correct the Antigravity config:

- MCP global path: ~/.gemini/config/mcp_config.json (Antigravity 2.0
  shared config, replacing the older ~/.gemini/antigravity/ path
  which an outdated github/github-mcp-server install guide cited).
- HTTP key: httpUrl (Gemini convention; antigravity is Gemini-based).
  The previous serverUrl was sourced from the same outdated guide.
- Rule: append to GEMINI.md / ~/.gemini/GEMINI.md (Antigravity reads
  Gemini-family rules, not a vendor-specific file).
- Project MCP: none documented; projectPaths is empty and setupAgent
  / remove falls back to globalPaths so --project --mcp still writes
  to the correct location.

Skills stay at .agent/skills to keep the in-repo IDE_PATHS convention
consistent across setup, skill, and generate commands.

* chore(cli): move Antigravity to 5th in agent selection list

Match the natural ordering users expect in the checkbox prompt:
Claude Code, Cursor, OpenCode, Codex, Antigravity, Gemini CLI.

* fix(cli): antigravity HTTP key is serverUrl, not httpUrl

Antigravity rejects the entry with "serverURL or command must be
specified" when given httpUrl. Switch the HTTP entry back to
serverUrl (the github-mcp-server install guide had this right even
though its file path was outdated).

Also tighten the empty-projectPaths fallback in remove.ts: it
incorrectly leaked global state into project-scope detection,
making `remove --project` report Antigravity whenever a global
~/.gemini/config/mcp_config.json existed. Project-scope detect/
remove now no-ops for agents with no project-level MCP, while
setup still falls back to the global path so --project --mcp
--antigravity writes to the file Antigravity actually reads.

* fix(cli): wire --antigravity into the remove command

Symmetric to the setup fix: --antigravity was missing from
UninstallOptions and getSelectedAgents, so users had no CLI path
to undo a `ctx7 setup --antigravity` install.
2026-06-02 16:44:59 +03:00
Enes Gules 2e97dae44e refactor(cli): update CLI documentation and add deprecation warning to skill commands (#2711) 2026-06-02 16:15:51 +03:00
github-actions[bot] ee0bb7a65e chore(release): version packages (#2660) 2026-05-22 19:19:26 +03:00
TT 7cacc9460a Add JSON output for skills list (#2658)
* Add JSON output for skills list

* test(cli): resolve tempDir via realpath for macOS compatibility

On macOS, os.tmpdir() returns /var/folders/... but process.cwd()
reports the symlink-resolved /private/var/folders/... after chdir.
The JSON output uses the resolved cwd, so the test assertion mismatched
the unresolved tempDir on macOS.

* chore: add changeset for skills list --json

---------

Co-authored-by: Fahreddin Özcan <ozcanfahrettinn@gmail.com>
2026-05-21 13:46:08 +03:00
github-actions[bot] 1ed71d7edc chore(release): version packages (#2605) 2026-05-21 09:54:51 +03:00
Fahreddin Özcan 34fda7d9b8 feat(mcp): prompt anonymous users to sign in (#2604)
Co-authored-by: enesgules <abdullah.enes.gules@gmail.com>
2026-05-20 17:47:20 +03:00
Fahreddin Özcan dea0e4318d fix(cli): declare @inquirer/core as direct dependency (#2653)
* fix(cli): declare @inquirer/core as direct dependency

selectOrInput.ts imports from @inquirer/core directly, but the package
was only resolvable as a transitive of @inquirer/prompts. Under pnpm's
isolated linker this fails with ERR_MODULE_NOT_FOUND at startup.

Fixes #2651

* chore: add changeset
2026-05-20 12:46:12 +03:00
Fahreddin Özcan 61de754d48 fix(cli): harden skill name handling during install (#2597)
* fix(cli): validate skill names to prevent path traversal on install

Adds boundary validation and containment checks so a remote SKILL.md
with a malicious name field (e.g. `name: ..`) cannot escape the skills
root during `ctx7 skills install`. Previously, the value flowed from
parseSkillFrontmatter to installSkillFiles unchecked, and the existing
traversal guard only verified files stayed inside the attacker-chosen
directory rather than the real skills root, enabling arbitrary file
writes outside `.claude/skills` (e.g. `.claude/settings.json` for
hook-driven RCE). symlinkSkill had the same trust issue and could
`rm(recursive: true)` arbitrary directories.

* chore: add changeset for skill name validation

* chore: soften changeset wording
2026-05-12 15:13:36 +03:00
github-actions[bot] 13f3ef03d9 chore(release): version packages (#2576)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-11 22:50:59 +03:00
Fahreddin Özcan 6c71e4deb4 fix(cli): handle malformed MCP config files in remove detection (#2574)
readJsonConfig only caught file-read errors, not JSON.parse errors.
During `ctx7 remove`, the detector iterates every agent's well-known
config path; an unparseable JSON file at any of them (e.g. a
hand-edited ~/.claude.json) crashed the command with an unhandled
SyntaxError before it could do anything.

Wrap the readJsonConfig call in hasMcpConfig with a try/catch that
logs a warning naming the path and parse error and skips that agent.
Keep readJsonConfig itself strict so write paths in setup and
uninstallMcp continue to surface failures via their existing handling.
2026-05-06 11:32:58 +03:00
Andrew Barnes 40568503ff fix(cli): respect CLAUDE_CONFIG_DIR for Claude setup (#2564)
* fix cli claude config dir

* chore: add changeset for CLAUDE_CONFIG_DIR support

---------

Co-authored-by: Fahreddin Özcan <ozcanfahrettinn@gmail.com>
2026-05-06 11:22:23 +03:00
github-actions[bot] 85c3a0cbfd chore(release): version packages (#2533)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-04 20:37:03 +03:00
Enes Akar 1aa3430bf6 feat: remove research mode (#2554)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: enesgules <abdullah.enes.gules@gmail.com>
2026-05-04 20:33:42 +03:00
github-actions[bot] 5d284f2154 chore(release): version packages (#2489)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-24 20:49:48 +03:00
Enes Akar 17b864f23f expose research mode through MCP and CLI (#2498)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: enesgules <abdullah.enes.gules@gmail.com>
2026-04-24 20:48:05 +03:00
Fahreddin Özcan f056b14cde CTX7-1542: add uninstall command for Context7 setup (#2473)
* CTX7-1542: add uninstall command for Context7 setup

* CTX7-1542: refine uninstall mode flags

* CTX7-1542: rename uninstall command to remove

* CTX7-1542: rename remove command files and add tests

* CTX7-1542: show detected agents in remove prompt

* CTX7-1542: tighten remove detection and cleanup coverage

* CTX7-1542: add remove command changeset
2026-04-21 12:41:32 +03:00
Fahreddin Özcan 4feee1521e CTX7-1544: add CLI update notifications and upgrade command (#2477)
* CTX7-1544: add CLI update notifications and upgrade command

* CTX7-1544: stabilize upgrade output tests
2026-04-21 12:41:19 +03:00
github-actions[bot] c8506690ce chore(release): version packages (#2453)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-14 10:51:17 +03:00
Astrazenith 3f6e310630 fix: skill installation path check compatibility for Windows (#2441)
* fix(cli): support Windows backslash in skill installation path check

* chore(cli): add changeset for Windows path check fix

* style(cli): format Windows path guard

---------

Co-authored-by: Fahreddin Özcan <ozcanfahrettinn@gmail.com>
2026-04-13 14:12:14 +03:00
github-actions[bot] c31528d0cd chore(release): version packages (#2433) 2026-04-13 03:20:32 +03:00
Fahreddin Özcan 33f2338092 Handle Codex CLI sandbox DNS failures in setup (#2449) 2026-04-12 17:10:53 -07:00
github-actions[bot] 5f108ecf88 chore(release): version packages (#2425)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-09 11:51:22 +03:00
Fahreddin Özcan bc8eaf11a6 Add all-agents option for ctx7 skills install (#2424)
* Add all-agents option for ctx7 skills install

* Update docs and add changeset for skills install flags
2026-04-09 11:44:56 +03:00
github-actions[bot] 36463ad6e3 chore(release): version packages (#2351)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-06 20:41:52 +03:00
Enes Gules 83228794e4 docs: enhance library name guidelines in CLI and documentation (#2408) 2026-04-06 20:40:00 +03:00
Fahreddin Özcan fb29170d85 feat(cli): add Gemini CLI support to setup command (#2406)
* feat(cli): add Gemini CLI support to setup command

Adds Gemini CLI as a supported agent in `ctx7 setup`. Configures MCP
server in `.gemini/settings.json` using `httpUrl` (Gemini's HTTP
streaming transport), appends rules to `GEMINI.md`, and installs skills
to `.gemini/skills/`. Also adds a permission fix tip when skill
installation fails with EACCES.

* chore: add changeset for Gemini CLI setup
2026-04-06 15:13:45 +03:00