# Search Papers

## Basic Search

```bash
axm-bib search "loop invariants"
```

Returns up to 10 results by default. Searches fan out to **6 sources in parallel**: Semantic Scholar, CrossRef, DBLP, OpenReview, arXiv, and OpenAlex. Results are deduplicated by DOI/arXiv ID and the richest metadata kept.

### Relevance Filtering

After deduplication, results are **ranked by title similarity** to the query. Papers whose titles are too dissimilar (below 0.4 similarity ratio) are automatically filtered out. This prevents noise from broad-matching sources (e.g. CrossRef) from diluting results when more precise sources (e.g. S2) are rate-limited.

## Control Result Count

```bash
# Get 10 results
axm-bib search "formal methods" -n 10

# Maximum is 100
axm-bib search "machine learning" -n 100
```

!!! warning "Limit validation"
    - Values ≤ 0 produce an error
    - Values > 100 are clamped to 100

## Abstract Display

By default, full abstracts are shown. You can control this:

```bash
# Hide abstracts entirely
axm-bib search "neural networks" --no-abstract

# Truncate to 100 characters
axm-bib search "neural networks" --abstract-len 100
```

## Papers Without DOIs

When a paper lacks a DOI, the arXiv ID is shown instead:

```
Year: 2017  DOI: arXiv:1706.03762
```

## Search Sources

`axm-bib` fans out to all 6 sources in parallel:

| Source | Abstract | Citations | arXiv ID | Native BibTeX |
|---|---|---|---|---|
| Semantic Scholar | ✅ | ✅ | ✅ | ❌ |
| CrossRef | ❌ | ❌ | ❌ | ❌ |
| DBLP | ❌ | ❌ | ❌ | ✅ |
| OpenReview | ✅ | ❌ | ❌ | ❌ |
| arXiv | ✅ | ❌ | ✅ | ❌ |
| OpenAlex | ✅ | ✅ | ✅ | ❌ |

### Source Visibility

If any source fails during search, a **warning** is emitted. The CLI prints which sources failed to `stderr`, and the MCP tool includes `sources_queried` and `sources_failed` lists in the result:

```json
{
  "papers": [...],
  "count": 5,
  "sources_queried": ["S2", "CrossRef", "DBLP", "OpenReview", "arXiv", "OpenAlex"],
  "sources_failed": ["S2"]
}
```

## Python API

```python
from axm_bib.pipeline import BibPipeline

pipeline = BibPipeline()
result = pipeline.search("attention mechanisms", limit=5)

# result is a SearchResult with .papers, .sources_queried, .sources_failed
for p in result.papers:
    print(f"{p.title} ({p.year}) — {p.doi}")
    print(f"  {p.abstract[:100]}...")

# Check which sources were queried/failed
if result.sources_failed:
    print(f"Warning: {result.sources_failed} failed")
```
