flutter_tantivy 2026.10.17
flutter_tantivy: ^2026.10.17 copied to clipboard
A Flutter plugin for full-text search powered by Tantivy
flutter_tantivy #
A Flutter plugin for full-text search powered by Tantivy 0.26.2, a fast full-text search engine library written in Rust. This plugin uses flutter_rust_bridge 2.13 to provide high-performance native search capabilities to Flutter applications.
Features #
- π High Performance: Powered by Tantivy 0.26.2 Rust search engine with fast columnar storage and inverted indexing
- π Full-Text, Regex & Regex Phrase Search: Support for standard text queries, boolean logic, wildcards, inline
/regex/,searchDocumentsRegex, and proximity-basedsearchDocumentsRegexPhrase - π€ Typo-Tolerant Fuzzy Search: Levenshtein automaton fuzzy search (
searchDocumentsFuzzy) with configurable edit distance, transposition cost, and prefix matching - π More-Like-This (Similar Documents): Find similar documents (
searchSimilarDocuments) based on document term vectors and frequencies - π‘οΈ Lenient Query Parsing &
field:*Exists Syntax: Fault-tolerant query parsing (searchDocumentsLenient), field boost, default AND mode, andfield:*/searchDocumentsExistssupport - π¬ Term Dictionary Autocomplete (
suggestTerms): Stream terms and document frequencies by prefix from Tantivy's FST term dictionary - π CJK & 18-Language Stemmer Support: Built-in N-gram tokenizer (
tokenizerType: 'cjk'), whitespace/raw tokenizers, and 18-language stemming (tokenizerType: 'en_stem'or'stem:<language>') - π‘ Rich Snippets & Byte Ranges: Extract HTML-formatted highlighted snippets (
snippet,titleSnippet) along with fragment byte ranges (fragmentRange) and highlight offsets (highlightedRanges) - π Index Space Usage & Segment Inspection: Inspect per-component storage metrics (
getIndexSpaceUsage) and active segment files (listIndexSegmentFiles) - π€ AI Agent Skill Ready: Bundled
skills/flutter-tantivyskill package for AI coding assistants (Antigravity, Gemini CLI, Claude Code, Cursor) - π± Cross-Platform: Supports Android, iOS, macOS, Linux, and Windows
Installation #
Add flutter_tantivy to your package's pubspec.yaml file:
dependencies:
flutter_tantivy: ^2026.10.17
Then run:
flutter pub get
π€ AI Agent Skills Guide (AI μμ΄μ νΈ Skills νμ© κ°μ΄λ) #
This repository includes a dedicated AI agent skill in skills/flutter-tantivy/ so AI coding assistants can accurately set up, index, query, and optimize flutter_tantivy without hallucinating APIs.
Skill Directory Structure #
skills/flutter-tantivy/
βββ SKILL.md # Core workflow, tokenizer selection & search API decision matrix
βββ references/
β βββ api-reference.md # Complete Dart function signatures & data models
βββ examples/
βββ search_repository.dart # Production-ready repository pattern (lenient + fuzzy fallback)
How to Install & Use the Skill #
1. Using npx skills CLI (Universal)
npx skills add JAICHANGPARK/flutter_tantivy
2. Google Antigravity (AGY) / Gemini CLI
Copy the skill into your project's .agents/skills/ directory or your global ~/.gemini/config/skills/ directory:
# Project-scoped (recommended for team sharing)
mkdir -p .agents/skills
cp -R path/to/flutter_tantivy/skills/flutter-tantivy .agents/skills/
# Or global configuration
mkdir -p ~/.gemini/config/skills
cp -R path/to/flutter_tantivy/skills/flutter-tantivy ~/.gemini/config/skills/
3. Claude Code / Cursor
Copy the skill folder to .claude/skills/ or .cursor/skills/ in your workspace:
mkdir -p .claude/skills
cp -R path/to/flutter_tantivy/skills/flutter-tantivy .claude/skills/
4. Example Prompts with the Skill Active
- "Use
flutter-tantivyto create a local Korean/English search service with typo-tolerant fuzzy fallback and search term highlighting." - "Add prefix autocomplete suggestions and 'related articles' (
searchSimilarDocuments) to my detail screen usingflutter_tantivy."
Quick Start #
1. Initialize the Library #
import 'package:flutter_tantivy/flutter_tantivy.dart';
import 'package:path_provider/path_provider.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize Rust FFI bridge
await RustLib.init();
// Initialize Tantivy index
// Supported tokenizerType values:
// - 'default': Standard SimpleTokenizer + LowerCaser
// - 'cjk' / 'ngram': N-gram (1..3) tokenizer for Korean/Chinese/Japanese
// - 'en_stem' / 'stem:<language>': 18-language stemmer (english, french, german, spanish, etc.)
// - 'whitespace' / 'raw'
final directory = await getApplicationDocumentsDirectory();
final indexPath = '${directory.path}/tantivy_index';
initTantivy(dirPath: indexPath, tokenizerType: 'cjk');
runApp(const MyApp());
}
2. Add Documents #
// Add a single document with optional title
const doc = Document(
id: '1',
title: 'Flutter Framework',
text: 'Flutter is an open-source UI toolkit by Google',
);
await addDocument(doc: doc);
// Batch add documents (more efficient)
const docs = [
Document(
id: '1',
title: 'Flutter UI',
text: 'Flutter is a UI toolkit for building natively compiled apps',
),
Document(
id: '2',
title: 'Rust Language',
text: 'Rust is a systems programming language focused on safety',
),
Document(
id: '3',
title: 'Tantivy Search',
text: 'Tantivy is a full-text search engine library written in Rust',
),
];
await addDocumentsBatch(docs: docs);
3. Search Documents with Pagination, Snippets & Fragment Byte Ranges #
final response = await searchDocuments(
query: 'Flutter OR Rust',
topK: BigInt.from(10),
offset: BigInt.from(0), // Optional: for pagination
enableSnippet: true, // Optional: generate highlighted text snippets & byte ranges
);
print('Total matching documents: ${response.totalHits}');
for (final result in response.results) {
print('Score: ${result.score}');
print('ID: ${result.doc.id}');
print('Title: ${result.doc.title}');
print('Text: ${result.doc.text}');
if (result.snippet != null) {
print('Snippet: ${result.snippet}'); // e.g. "<b>Flutter</b> is a UI..."
}
if (result.fragmentRange != null) {
print('Fragment byte range: ${result.fragmentRange!.start}..${result.fragmentRange!.end}');
}
}
4. Fuzzy Search, Regex Phrase & Similar Documents (MoreLikeThis) #
// Typo-tolerant Fuzzy Search (Levenshtein distance 1..2)
final fuzzyResponse = await searchDocumentsFuzzy(
term: 'Fluter',
distance: 1,
transpositionCostOne: true,
prefix: true,
topK: BigInt.from(10),
enableSnippet: true,
);
// Regex Phrase Search with proximity slop
final phraseResponse = await searchDocumentsRegexPhrase(
patterns: ['flut.*', 'toolkit'],
slop: 2,
topK: BigInt.from(10),
);
// Find Similar Documents (MoreLikeThisQuery)
final similarResponse = await searchSimilarDocuments(
id: '1',
topK: BigInt.from(5),
);
// Term Dictionary Prefix Autocomplete
final suggestions = await suggestTerms(
prefix: 'flut',
limit: BigInt.from(5),
);
5. Index Statistics, Space Usage & Release #
// Get total document count in index
final count = getNumDocs();
print('Indexed Documents: $count');
// Inspect detailed index storage space usage
final usage = getIndexSpaceUsage();
print('Total bytes: ${usage.totalBytes}, Segments: ${usage.numSegments}');
// List active segment files in index metadata
final segmentFiles = listIndexSegmentFiles();
print('Segment files: $segmentFiles');
// Delete all documents in index
await deleteAllDocuments();
// Close and release Tantivy resources (optional)
closeTantivy();
API Reference #
Initialization & Diagnostics #
initTantivy({required String dirPath, String? tokenizerType})- Initialize or open a Tantivy index at the specified directorygetNumDocs()- Synchronously returns the total count of indexed documentsgetIndexSpaceUsage()- Synchronously returnsIndexSpaceUsagewith byte breakdown across store, postings, positions, fast fields, termdict, fieldnorms, and deleteslistIndexSegmentFiles()- Synchronously returns candidate relative paths for all active segments inIndexMetacloseTantivy()- Safely release and close Tantivy resources
CRUD & Batch Operations #
addDocument({required Document doc})- Add or update a single document (auto-commits)getDocumentById({required String id})- Retrieve a document by its ID (synchronous)updateDocument({required Document doc})- Update an existing documentdeleteDocument({required String id})- Delete a document by IDdeleteAllDocuments()- Delete all documents in the indexaddDocumentsBatch({required List<Document> docs})- Add multiple documents efficientlydeleteDocumentsBatch({required List<String> ids})- Delete multiple documents efficientlyaddDocumentNoCommit({required Document doc})- Add document without committingdeleteDocumentNoCommit({required String id})- Delete document without committingcommit()- Manually commit pending changes
Search & Suggestion Operations #
searchDocuments({required String query, required BigInt topK, BigInt? offset, bool? enableSnippet})- Full-text search supporting boolean operators, phrase slop ("..."~N), phrase prefix ("..."*), boost (^N), inline regex (/pattern/), and field existence (title:*)searchDocumentsLenient({required String query, required BigInt topK, BigInt? offset, bool? enableSnippet, bool? conjunctionByDefault, double? titleBoost})- Lenient search returningLenientSearchResponse(results + non-fatal syntax errors)searchDocumentsRegex({required String pattern, required BigInt topK, BigInt? offset, bool? enableSnippet})- Regex pattern search acrosstitleandtextsearchDocumentsRegexPhrase({required List<String> patterns, int? slop, int? maxExpansions, required BigInt topK, BigInt? offset, bool? enableSnippet})- Ordered sequence of regex patterns with optionalslopsearchDocumentsFuzzy({required String term, int? distance, bool? transpositionCostOne, bool? prefix, required BigInt topK, BigInt? offset, bool? enableSnippet})- Typo-tolerant Levenshtein automaton searchsearchSimilarDocuments({required String id, required BigInt topK, ...})-MoreLikeThisQuerysimilarity search for a reference document IDsearchDocumentsExists({required String fieldName, required BigInt topK, BigInt? offset})- Match documents wherefieldName(id,title, ortext) has a non-null valuesuggestTerms({required String prefix, BigInt? limit, bool? includeTitle})- Stream prefix suggestions and document frequencies from the term dictionary
Query Syntax #
Tantivy supports a rich query syntax matching across title and text:
- Term search:
flutter - Phrase & Slop search:
"flutter framework","flutter toolkit"~2 - Phrase prefix search:
"flutter frame"* - Boolean operators:
flutter AND dart,ios OR android,flutter NOT web - Field search & Boost:
title:flutter^2.0ortext:rust - Exists query:
title:*,* NOT title:* - Inline Regex & Wildcard:
title:/flut.*/,flut*
Architecture #
This plugin uses:
- Rust for core search engine logic (Tantivy 0.26.2)
- flutter_rust_bridge 2.13 for type-safe Dart-Rust FFI interop
- Cargokit for seamless multi-platform native build & bundling
π€ AI Agent Skills Guide (Claude, Codex, Gemini / Antigravity νμ© κ°μ΄λ) #
flutter_tantivy includes built-in AI Agent Skills and instruction files so AI coding assistants (Claude Code, OpenAI Codex, and Google Antigravity / Gemini CLI) can automatically understand the FFI initialization flow, tokenizer options (cjk, default, en_stem, stem:<lang>, whitespace, raw), and search APIs without hallucinating outdated bindings.
π Included Skill & Agent Files #
flutter_tantivy/
βββ skills/flutter-tantivy/ # Canonical Agent Skill package
β βββ SKILL.md # Step-by-step workflow & API selection table
β βββ references/api-reference.md # Complete Dart FFI signatures & data models
β βββ examples/search_repository.dart # Ready-to-use LocalSearchRepository template
βββ .agents/skills/flutter-tantivy/ # Auto-discovered by Gemini (Antigravity) & Codex
βββ .claude/skills/flutter-tantivy/ # Auto-discovered by Claude Code
βββ .codex/skills/flutter-tantivy/ # Auto-discovered by OpenAI Codex
βββ CLAUDE.md # Root context for Claude Code
βββ AGENTS.md # Root context for OpenAI Codex & Antigravity
βββ GEMINI.md # Root context for Gemini CLI & Antigravity
π How to Use in Your Flutter Project (λ΄ Flutter μ± νλ‘μ νΈμ μ μ©νκΈ°) #
1. Quick Install via npx skills CLI (κΆμ₯)
Install the flutter-tantivy skill directly into your Flutter app workspace for Claude Code, Codex, and Gemini (Antigravity):
# Install for all detected agents (Claude, Codex, Antigravity/Gemini)
npx skills add jaichangpark/flutter_tantivy
# Or target a specific agent:
npx skills add jaichangpark/flutter_tantivy -a claude-code
npx skills add jaichangpark/flutter_tantivy -a codex
npx skills add jaichangpark/flutter_tantivy -a antigravity
2. Agent-Specific Setup (μμ΄μ νΈλ³ μλ μ€μ λ°©λ²)
π£ Claude Code (claude)
Claude Code automatically loads skills from .claude/skills/<skill-name>/SKILL.md and project instructions from CLAUDE.md.
# Copy skill into your Flutter project's .claude/skills directory
mkdir -p .claude/skills
cp -R /path/to/flutter_tantivy/skills/flutter-tantivy .claude/skills/flutter-tantivy
- Usage in Claude Code: Simply ask in natural language or invoke
/flutter-tantivy:"Use the
flutter-tantivyskill to implement Korean+English full-text search with fuzzy fallback and highlighted snippets."
π’ OpenAI Codex (codex)
OpenAI Codex CLI automatically reads AGENTS.md and loads workspace skills from .agents/skills/<skill-name>/SKILL.md (or .codex/skills/<skill-name>/SKILL.md).
# Copy skill into your Flutter project's .agents/skills directory
mkdir -p .agents/skills
cp -R /path/to/flutter_tantivy/skills/flutter-tantivy .agents/skills/flutter-tantivy
- Optionally add a reference in your project's
AGENTS.md:- For local full-text search using `flutter_tantivy`, read `.agents/skills/flutter-tantivy/SKILL.md`.
π΅ Gemini CLI / Google Antigravity (gemini / agy)
Google Antigravity and Gemini CLI automatically discover workspace skills in .agents/skills/<skill-name>/SKILL.md, global skills in ~/.gemini/config/skills/<skill-name>/SKILL.md, and rules in GEMINI.md / AGENTS.md.
# Option A: Workspace-level (recommended for team projects via Git)
mkdir -p .agents/skills
cp -R /path/to/flutter_tantivy/skills/flutter-tantivy .agents/skills/flutter-tantivy
# Option B: Global machine-level (available across all your Flutter projects)
mkdir -p ~/.gemini/config/skills
cp -R /path/to/flutter_tantivy/skills/flutter-tantivy ~/.gemini/config/skills/flutter-tantivy
π‘ Example Prompts for AI Agents (ν둬ννΈ νμ© μμ) #
Once the skill is loaded in Claude, Codex, or Gemini (Antigravity), try asking:
- μ΄κΈ°ν λ° νκ΅μ΄/μμ΄ ν΅ν© κ²μ μλΉμ€ ꡬν:
"
flutter-tantivyμ€ν¬μ μ°Έκ³ ν΄μtokenizerType: 'cjk'λ‘ μΈλ±μ€λ₯Ό μ΄κΈ°ννκ³ , μ¬μ©μ κ²μμ΄ μ λ ₯ μsearchDocumentsLenientλ‘ κ²μνλ κ²°κ³Όκ° μμΌλ©΄searchDocumentsFuzzyλ‘ μ€ν 보μ κ²μμ μννλSearchServiceλ₯Ό μμ±ν΄ μ€." - μ€μκ° μλμμ± λ° μ λμ΄ μΆμ² κ²μ UI ꡬν:
"
flutter-tantivyμ€ν¬μsuggestTermsμsearchDocumentsLenientλ₯Ό νμ©ν΄μ κ²μμ°½ μ λ ₯ μ€ μ€μκ° μΆμ² κ²μμ΄ μΉ©(Chip)κ³Ό λ¬Έμ λΉλ(docFreq)λ₯Ό 보μ¬μ£Όλ Flutter μμ ―μ λ§λ€μ΄ μ€." - κ²μ κ²°κ³Ό μ€λν« λ° λ°μ΄νΈ μ€νμ
νμ΄λΌμ΄ν
ꡬν:
"
flutter-tantivyμ€ν¬μSearchResult.snippet,titleSnippet,highlightedRanges(TextRange)λ₯Ό μ¬μ©ν΄μ κ²μμ΄ λ§€μΉ κ΅¬κ°μ νμ΄λΌμ΄ν νλ 리μ€νΈ μμ΄ν μμ ―μ λ§λ€μ΄ μ€." - μ°κ΄ κ²μκΈ(MoreLikeThis) μΆμ² κΈ°λ₯ μΆκ°:
"νμ¬ λ³΄κ³ μλ λ¬Έμ IDλ₯Ό κΈ°μ€μΌλ‘
searchSimilarDocumentsλ₯Ό νΈμΆν΄ νλ¨μ 'μ μ¬ν κΈ 5κ°'λ₯Ό μΆμ²νλ κΈ°λ₯μ μΆκ°ν΄ μ€."
License #
This project is licensed under the MIT License - see the LICENSE file for details.