SkillAgentSearch skills...

ghostimport

๐Ÿ‘ป Detects ghost imports โ€” npm packages that don't exist, hallucinated by AI coding tools like Cursor, Copilot, and Claude

Install / Use

claude mcp add FGuerreir0 -- npx -y github:FGuerreir0/ghostimport

If the server publishes to npm under a different name, use that package instead โ€” check the repo README.

About this skill
๐Ÿ”Œ

MCP Server

Model Context Protocol server

Quality Score

81/100

Category

Security

Supported Platforms

Claude Code
Claude Desktop
Cursor
GitHub Copilot

Our assessment of ghostimport

ghostimport scores 81/100 on our quality scale, 812th of 1,000 Security skills we index.

Its MCP Server is 9.5 KB long, well organised into 9 sections with 12 code examples: a thorough specification that gives an agent plenty to work with.

It has 3 GitHub stars, so there is little community track record yet; judge it on its content.

Substance
29/30
Structure
20/20
Description
15/15
Adoption
3/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 16 days ago, so ghostimport is actively maintained.
  • No license is declared. By default that means all rights are reserved: you can read it, but reusing or redistributing it is not clearly permitted. Ask the author before building on it commercially.
  • Its trust signals score 80/100, with 2 cautions from licensing, adoption, age or documentation. These come from repository metadata, not a code audit โ€” read the skill file before letting an agent act on it.

Safety scan

No issues found

Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands.

Automated pattern scan on 2026-10-01. It catches known dangerous patterns, not every risk โ€” read a skill before letting an agent act on it.

ghostimport compared with similar skills

All 4 of these similar skills score higher than ghostimport; compare them before choosing.

SkillScoreStarsUpdatedFormat
ghostimport (this skill)by FGuerreir081316d agoMCP Server
Agent-Reachby Panniantong10087.2k16d agoCLAUDE.md
headroomby headroomlabs-ai10074.2ktodayCLAUDE.md
rufloby ruvnet10073.6ktodayCLAUDE.md
CowAgentby zhayujie10047.2ktodayCLAUDE.md

Frequently asked questions

How do I install ghostimport?
Run claude mcp add FGuerreir0 -- npx -y github:FGuerreir0/ghostimport. The install tabs above show the steps for each supported agent.
Which AI agents does ghostimport work with?
It is written for Claude Code, Claude Desktop, Cursor and GitHub Copilot, as a MCP Server file. Other agents that read the same format can often use it too.
Is ghostimport safe to use?
Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. It declares no license and scores 80/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is ghostimport still maintained?
The repository was last updated 16 days ago, so ghostimport is actively maintained.
<p align="center"> <img src="assets/logo.png" width="128" alt="ghostimport logo"> </p> <h1 align="center">ghostimport</h1> <p align="center"> <strong>Stops your AI coding agent from installing npm packages that don't exist.</strong> </p> <p align="center"> <img src="https://github.com/FGuerreir0/ghostimport/actions/workflows/ci.yml/badge.svg" alt="CI"> <a href="https://www.npmjs.com/package/ghostimport"><img src="https://img.shields.io/npm/v/ghostimport" alt="npm"></a> <a href="https://github.com/FGuerreir0/ghostimport"><img src="https://img.shields.io/badge/ghostimport-%E2%9C%93%20clean-brightgreen" alt="ghostimport"></a> <a href="https://buymeacoffee.com/fabioguerreiro"><img src="https://img.shields.io/badge/buy%20me%20a%20coffee-support-FFDD00?logo=buymeacoffee&logoColor=black" alt="Buy me a coffee"></a> </p> <p align="center"> <a href="https://fguerreir0.github.io/ghostimport/"><strong>How the attack works โ†’</strong></a> </p>

Your agent invents a package name. It doesn't exist on npm yet. Someone is watching for exactly that, and the moment they register it, npm install runs their postinstall script on your machine.

This is slopsquatting. Most dependency scanners inspect packages after they are installed; ghostimport checks names before they are โ€” against the live registry, at the moment your agent writes or installs them.

$ ghostimport

  Scanned 142 files ยท 38 packages

  โœ— react-server-fetch  does not exist on npm
    โ†ณ src/data/loader.ts
    โ†ณ unregistered โ€” anyone could claim this name with a malicious postinstall

  โœ— axois  high risk
    โ†ณ src/api/client.ts
    โ†ณ 1-2 chars from 'axios' โ€” likely a typo
    โ†ณ has postinstall script โ€” runs code on npm install
    created 2019-08-29 ยท 1245/week ยท 1 version

  2 problems found.

Install

npm install -g ghostimport     # or: npx ghostimport

Node.js 22+. Zero runtime dependencies โ€” the published package uses only Node built-ins.

Use it with your AI agent

This is the part that matters. A CI check tells you about a bad package after it's in your repo; these stop it at the moment it's written.

Hooks โ€” the enforcing one

Add to .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Bash", "hooks": [{ "type": "command", "command": "ghostimport hook" }] }
    ],
    "PostToolUse": [
      { "matcher": "Edit|Write|MultiEdit", "hooks": [{ "type": "command", "command": "ghostimport hook" }] }
    ]
  }
}
  • PreToolUse on Bash โ€” reads any install command and denies the tool call if it would fetch a package that doesn't exist, is a typosquat, or ships an install script. This is the one that stops a real attack.
  • PostToolUse on edits โ€” checks imports the agent just wrote, or dependencies it just added to a package.json, and tells it to fix them.

The agent sees why it was stopped:

ghostimport blocked this: the install command below would fetch packages that
are unsafe or do not exist.

  โ€ข 'axois' exists but is high risk: name is 1-2 chars from 'axios';
    single version published.

Do not retry this command as written.

It fails open. Registry unreachable, malformed payload, or a check exceeding its 20-second budget โ†’ exits 0 and stays out of the way. A security tool that wedges your agent when you're offline gets uninstalled by Friday.

MCP โ€” the self-service one

Lets the model verify a name before it writes the import. Hooks are mandatory; MCP tools are offered โ€” use both.

claude mcp add ghostimport -- npx -y ghostimport mcp
<details> <summary>Cursor, Windsurf, and other MCP clients</summary>

Add to .cursor/mcp.json or your client's config:

{
  "mcpServers": {
    "ghostimport": {
      "command": "npx",
      "args": ["-y", "ghostimport", "mcp"]
    }
  }
}

| Tool | What it does | |---|---| | check_packages | Verify package names exist on npm. deep adds risk heuristics. | | check_install_command | Vet a full npm/pnpm/yarn/bun install command. | | scan_project | Audit a whole directory. |

</details>

CLI

ghostimport              # scan the current directory
ghostimport ./src        # scan a folder
ghostimport --json       # machine-readable
ghostimport --watch      # re-scan on change

Exits 1 if any imported package doesn't exist, so it works as a CI gate as-is.

<details> <summary>All options</summary>

| Flag | Effect | |---|---| | --quiet, -q | Only show problems | | --json | Output results as JSON | | --watch, -w | Re-scan on file changes | | --badge | Print a README badge after scanning | | --fast | Skip the deep supply-chain check on undeclared packages | | --no-undeclared | Hide "imported but not in package.json" warnings | | --no-cache | Bypass the 24h registry cache | | --version, -v ยท --help, -h | |

Optional .ghostimportrc.json in your project root:

{ "ignore": ["@company/*", "internal-lib"], "includeUndeclared": true }
</details> <details> <summary>CI: GitHub Actions and pre-commit</summary>
- uses: FGuerreir0/ghostimport@v0.6.0
  with:
    path: '.'

Or just run: npx ghostimport --quiet.

For pre-commit, in .pre-commit-config.yaml:

repos:
  - repo: https://github.com/FGuerreir0/ghostimport
    rev: v0.6.0
    hooks:
      - id: ghostimport
</details>

API

import { verifyPackages, scan } from 'ghostimport'

await verifyPackages(['axios', 'axois'], { deep: true })
// [ { pkg: 'axios', status: 'ok', typosquatOf: null },
//   { pkg: 'axois', status: 'suspicious', risk: 'high', typosquatOf: 'axios', ... } ]

const { missing, undeclared, risks } = await scan('./src')

status is 'ok' | 'missing' | 'suspicious' | 'unknown'. 'unknown' means the registry was unreachable โ€” never treat it as a failure.

<details> <summary>Full API and TypeScript types</summary>

| Export | Purpose | |---|---| | scan(dir, opts?) | Scan a directory. Returns ScanResult. | | verifyPackages(names, opts?) | Check a list of names. Returns PackageVerdict[]. | | checkNpm(name) | Does this one package exist? | | checkPackageRisk(name) | Full supply-chain check for one package. | | detectTyposquat(name) | Returns the popular package it's 1-2 chars from, or null. | | extractImports(code) | Package names from a source string. | | extractInstallTargets(cmd) | Packages a shell command would install. |

interface ScanResult {
  scanned: number
  packages: number
  missing: { pkg: string; files: string[]; claimable: boolean | null }[]
                                                  // don't exist on npm; claimable is false
                                                  // inside a scope someone already owns
  undeclared: { pkg: string; files: string[] }[]  // exist, but not in package.json
  risks: RiskEntry[]                              // supply-chain findings
  errors: { pkg: string; error: string; files: string[] }[]
  cacheHits: number
}

type RiskEntry =
  | { pkg: string; files: string[]; type: 'unregistered'; typosquatOf: string | null }
  | { pkg: string; files: string[]; type: 'suspicious'
      risk: 'medium' | 'high'; flags: string[]; installScripts: string[]
      typosquatOf: string | null; maintainers: number
      created: string; downloads: number | null; versions: number }

Types are shipped with the package: ScanResult, ScanOptions, MissingRef, RiskEntry, PackageVerdict, VerdictStatus, PackageRiskResult, NpmCheckResult, Config.

</details> <details> <summary>What gets scanned, and what raises a risk</summary>

Detects: import, require(), dynamic import(), export โ€ฆ from, scoped packages, subpath imports (pkg/utils โ†’ pkg), and <script> blocks in .vue, .svelte and .astro (markup is ignored, so a package name in template text is never flagged). Also every registry dependency declared in any package.json, whether or not anything imports it โ€” workspace:, file:, link:, git and URL specs are skipped, and npm: aliases are followed to the real name.

Extensions: .js .jsx .ts .tsx .mjs .cjs .vue .svelte .astro

Ignores: Node built-ins, relative imports, path aliases (@/, ~/, $lib/, tsconfig paths), URL/protocol imports, virtual modules, workspace packages, and node_modules/ dist/ build/ .git/.

Risk signals:

| Signal | Weight | Why | |---|---|---| | postinstall / preinstall / install script | critical | Runs arbitrary code on npm install | | Name 1-2 chars from a popular package | critical | Classic typosquat | | Created < 30 days ago | medium | No track record | | < 50 weekly downloads | medium | Near-zero adoption | | Single version published | medium | Abandoned or one-shot | | Single maintainer | amplifier | Only counts alongside another signal |

high if any critical signal fires, or 2+ medium ones. Only medium and high are reported.

A name that doesn't exist on npm is reported as squattable unless it sits in a scope someone already owns โ€” only a scope's owner can publish under it, so @babel/made-up is a broken import but not a squatting target. That check costs at most one request per scope, so --fast doesn't disable it.

</details>

Contributing

Development setup, the source layout, and how the site in docs/ is built and deployed all live in CONTRIBUTING.md.

Support

ghostimport is free, MIT licensed and has no runtime dependencies โ€” and it stays that way. If it caught something for you, you can buy me a coffee.

License

MIT

Related Skills

View on GitHub
GitHub Stars3
CategorySecurity
Updated16d ago
Forks0

Languages

TypeScript

Trust signals

80/100

From repository metadata: license, adoption, age and documentation. Not a code audit โ€” see the Safety scan above for what the skill file itself contains.

1 medium1 low