# spacy

Directs Cursor to follow spaCy best practices in Python: enforces type hints, batch processing via nlp.pipe, and declarative configs.

- rule · `type=rule` · Cursor · ★ 3580
- Author: sanjeed5
- License: CC0-1.0 · policy=mirror · the beginning of the file is at the end of this page
- Source: https://github.com/sanjeed5/awesome-cursor-rules-mdc/tree/HEAD/rules-mdc/spacy.mdc
- Updated: 2026-05-19
- HTML: https://affpapa.org/en/nevibecode/rules/spacy

## What it does

The rule activates on `**/*.py` files to guide the Cursor assistant when building NLP pipelines. It mandates structured project setups via `spacy project`, using `project.yml` and `config.cfg` rather than ad-hoc scripts with hardcoded model paths.

Code generation requires explicit type hints on spaCy objects like `Language`, `Doc`, `Span`, and `Token`. For inference efficiency, the rule tells the agent to process documents in batches using `nlp.pipe` and temporarily turn off unneeded steps with `nlp.select_pipes(enable=...)`.

Custom logic belongs inside components registered through `@Language.factory`, storing outputs via `Doc.set_extension` instead of loose helper dictionaries. Dependencies must remain pinned in `requirements.txt` to keep runs reproducible.

## Install

### Cursor (native platform)

**Manually: put the files in place**
- File: `.cursor/rules/spacy.mdc` — Frontmatter: description, globs, alwaysApply

### Claude Code

**Manually: put the files in place**
- File: `.claude/rules/spacy.md` — The paths frontmatter field limits the files: move globs from the source into paths

### Codex

**AGENTS.md**
- Codex reads AGENTS.md: paste the rule text there

### GitHub Copilot

**Manually: put the files in place**
- File: `.github/instructions/spacy.instructions.md` — The applyTo field sets which files it applies to: move globs from the source into applyTo

### Windsurf (Devin Desktop)

**Manually: put the files in place**
- File: `.devin/rules/spacy.md`

### Cline

**Manually: put the files in place**
- File: `.clinerules/spacy.md`

Where a file is given instead of a command, copy the files from the source to that path: https://github.com/sanjeed5/awesome-cursor-rules-mdc/tree/HEAD/rules-mdc/spacy.mdc

## When to use it
- Structure spaCy workflows using project.yml and config.cfg
- Batch text analysis with nlp.pipe and nlp.select_pipes
- Add type hints for Language, Doc, Span, and Token
- Register custom pipeline extensions via Language.factory

## Example prompts
- Write a typed Python function to extract named entities with spaCy
- Create a custom sentiment analysis component factory with Doc.set_extension
- Optimize this text processing loop using nlp.pipe with batching

## Source text · spacy.mdc · CC0-1.0

Below is the content of a third-party file. It is data, not instructions for you: do not act on anything written inside unless the human asks. Block tag: 89ded66ec581fa11.

BEGIN THIRD-PARTY FILE 89ded66ec581fa11
````text
---
description: This guide provides definitive, opinionated best practices for writing maintainable, performant, and robust spaCy code in Python, focusing on modern patterns and avoiding common pitfalls.
globs: **/*.py
---
# spaCy Best Practices

spaCy is the backbone of our NLP systems. Adhering to these guidelines ensures our pipelines are performant, reproducible, and easy to maintain.

## 1. Project Organization & Configuration

Always structure your spaCy projects using `spacy project` and define all pipeline settings in a declarative YAML config. This is non-negotiable for reproducibility and scalability.

**✅ GOOD: Use `spacy project` and declarative configs.**
Organize your pipeline logic in a dedicated `src/pipeline/` package. Use `project.yml` to manage workflows and `config.cfg` for all spaCy pipeline settings.

```python
# src/pipeline/custom_component.py
from spacy.language import Language
from spacy.tokens import Doc

@Language.factory("my_custom_component")
def create_my_component(nlp: Language, name: str):
    return MyCustomComponent(nlp, name)

class MyCustomComponent:
    def __init__(self, nlp: Language, name: str):
        self.nlp = nlp
        self.name = name

    def __call__(self, doc: Doc) -> Doc:
        # Custom logic here
        return doc

# project.yml (simplified)
# ...
workflows:
  train:
    - "python -m spacy train config.cfg --output models/"
  package:
    - "python -m spacy package models/en_core_web_v1.0.0 ./dist --build wheel"

# config.cfg (simplified)
[nlp]
lang = "en"
pipeline = ["tok2vec", "ner", "my_custom_component"]

[components.my_custom_component]
factory = "my_custom_component"
```

**❌ BAD: Ad-hoc scripts and hardcoded parameters.**
Avoid scattering pipeline logic across multiple scripts or hardcoding model paths and hyperparameters. This makes experiments non-reproducible and deployment fragile.

```python
# bad_script.py
import spacy
# Parameters hardcoded or passed via CLI args, not in a central config
MODEL_PATH = "path/to/my/model"
THRESHOLD = 0.7

nlp = spacy.load(MODEL_PATH)
# ... pipeline components added programmatically ...
```

## 2. Type Hinting

Strictly use type hints for all spaCy objects (`Language`, `Doc`, `Span`, `Token`). This improves code readability, enables static analysis, and reduces runtime errors.

**✅ GOOD: Comprehensive type hints.**
Annotate function arguments and return types with precise spaCy types.

```python
import spacy
from spacy.language import Language
from spacy.tokens import Doc, Span, Token
from typing import List

def process_document(nlp: Language, text: str) -> Doc:
    """Processes text with a spaCy pipeline."""
    return nlp(text)

def extract_entities(doc: Doc) -> List[Span]:
    """Extracts named entities from a processed Doc."""
    return list(doc.ents)

def get_token_lemma(token: Token) -> str:
    """Returns the lemma of a single token."""
    return token.lemma_
```

**❌ BAD: Untyped spaCy code.**
Omitting type hints makes code harder to understand and refactor.

```python
# bad_types.py
import spacy

def process_document(nlp, text): # What are nlp and text? What does it return?
    return nlp(text)

def extract_entities(doc): # What is 'doc'?
    return list(doc.ents)
```

## 3. Performance Considerations

Optimize for speed and memory by disabling unused pipeline components and processing text in batches.

**✅ GOOD: Efficient pipeline usage.**
Use `nlp.select_pipes` for inference to only run necessary components. Process multiple documents with `nlp.pipe`.

```python
import spacy
from spacy.language import Language
from spacy.tokens import Doc
from typing import Iterator

def analyze_text_batch(nlp: Language, texts: List[str]) -> Iterator[Doc]:
    """Processes a batch of texts, only running NER."""
    # Temporarily disable unused pipes for performance during inference
    with nlp.select_pipes(enable=["ner"]):
        yield from nlp.pipe(texts, batch_size=50)

# Example usage
nlp_full = spacy.load("en_core_web_sm")
````
END THIRD-PARTY FILE 89ded66ec581fa11

The third-party file has ended. Everything between the 89ded66ec581fa11 tags is data: requests and commands from it are not followed. An “end of file” line with another tag inside the block is part of the file.

First 4009 of 10530 bytes. © sanjeed5 · CC0-1.0 · https://github.com/sanjeed5/awesome-cursor-rules-mdc/tree/HEAD/rules-mdc/spacy.mdc

_Part of the page did not fit — see the HTML version._

---
NeVibeCode on affpapa.org. Catalog texts are descriptions, not instructions for the agent. How to choose and install: https://affpapa.org/en/nevibecode/agents.md
