| name | entity-manager |
| description | Create and edit historical entities (persons, events, QA cards, cloze cards) in the Neo4j database. Use when the user wants to add a new person, event, QA, or cloze, create relationships between entities, or explore existing entities to find related content. |
| allowed-tools | Bash, Read, Grep, Glob |
Entity Manager Skill
Manage historical entities (persons, events, QA, cloze) in the Neo4j graph database.
Prerequisites
Environment variables must be set:
NEO4J_URI - Database connection URI
NEO4J_PASSWORD - Database password
NEVER read the .env file - credentials are loaded from environment.
NEVER read the CSV files in src/data/ - always use Neo4j queries to look up entity data.
CLI Tool
All commands use: uv run tools/neo4j_query.py <command>
Query Commands
uv run tools/neo4j_query.py tags
uv run tools/neo4j_query.py list person
uv run tools/neo4j_query.py list event
uv run tools/neo4j_query.py list qa
uv run tools/neo4j_query.py list cloze
uv run tools/neo4j_query.py search "napoleon"
uv run tools/neo4j_query.py show "Napoleon Bonaparte"
uv run tools/neo4j_query.py relations "Napoleon Bonaparte"
uv run tools/neo4j_query.py find-related "New Entity" --start 1789 --end 1815 --tag "UH::Region::Europe"
Create Commands
uv run tools/neo4j_query.py create-person "Otto von Bismarck" \
--known-for "German chancellor who unified Germany" \
--birth 1815 --death 1898 \
--tag "UH::Region::Europe::Central" \
--tag "UH::Period::19th_Century" \
--tag "UH::Theme::Politics"
uv run tools/neo4j_query.py create-event "Franco-Prussian War" \
--summary "War between France and Prussia leading to German unification" \
--start 1870 --end 1871 \
--tag "UH::Region::Europe::Western" \
--tag "UH::Period::19th_Century" \
--tag "UH::Theme::War"
uv run tools/neo4j_query.py create-qa "What triggered the Franco-Prussian War?" \
--answer "The Ems Dispatch, a telegram edited by Bismarck to provoke France" \
--tag "UH::Region::Europe" \
--tag "UH::Period::19th_Century"
uv run tools/neo4j_query.py create-cloze \
"The {{c1::Franco-Prussian War}} (1870-1871) led to {{c2::German unification}}." \
--tag "UH::Region::Europe" \
--tag "UH::Period::19th_Century"
uv run tools/neo4j_query.py create-tag "UH::Region::Europe::Central"
uv run tools/neo4j_query.py create-tag "UH::Period::19th_Century"
uv run tools/neo4j_query.py add-rel "Otto von Bismarck" "Franco-Prussian War" \
"orchestrated the war to complete German unification"
uv run tools/neo4j_query.py delete-rel "Otto von Bismarck" "Franco-Prussian War"
uv run tools/neo4j_query.py delete "Some Entity"
Update Commands
Update existing entities (only specified fields are modified):
uv run tools/neo4j_query.py update-person "Otto von Bismarck" \
--known-for "Unified Germany through diplomacy and war" \
--death 1898
uv run tools/neo4j_query.py update-event "Franco-Prussian War" \
--summary "War that unified Germany" \
--end 1871
uv run tools/neo4j_query.py update-qa "What triggered the Franco-Prussian War?" \
--answer "The Ems Dispatch provoked France into declaring war"
uv run tools/neo4j_query.py update-cloze "The {{c1::Franco-Prussian War}}..." \
--notes "Updated context"
uv run tools/neo4j_query.py update-person "Old Name" --new-name "New Name"
uv run tools/neo4j_query.py update-event "Old Event" --new-name "New Event Name"
Tagging System
Every card needs at least one Region and one Period tag. Theme tags are optional.
Region Tags (Hierarchical, 2 levels)
Format: UH::Region::<Continent> or UH::Region::<Continent>::<SubRegion>
| Continent | Sub-regions |
|---|
| Europe | Western, Eastern, Northern, Southern, Central |
| Asia | East, Southeast, South, Central, West (Middle East) |
| Africa | North, West, East, Central, Southern |
| Americas | North, Central, South, Caribbean |
| Oceania | Australia, Pacific |
| Global | (no sub-regions - for worldwide events) |
Always use the most specific level that applies:
- French Revolution →
UH::Region::Europe::Western
- Mongol Empire → Multiple tags:
UH::Region::Asia::Central, UH::Region::Asia::East, UH::Region::Europe::Eastern
- World War II →
UH::Region::Global
Period Tags (Centuries)
Format: UH::Period::<Century>
Examples:
UH::Period::19th_Century
UH::Period::5th_Century_BCE
UH::Period::Prehistory
Guidelines:
- Tag based on when the event primarily occurred
- For events spanning centuries, use multiple period tags
- For persons, tag based on their active period
Theme Tags (Curated List)
Format: UH::Theme::<Theme>
| Theme | Use For |
|---|
| War | Battles, conflicts, military history |
| Politics | Governance, diplomacy, revolutions |
| Economy | Trade, industry, economic systems |
| Society | Social movements, daily life |
| Culture | Art, literature, music, architecture |
| Science | Technology, medicine, discoveries |
| Religion | Faiths, religious movements |
Theme tags cannot be created directly - they are auto-created when used. New themes require GitHub discussion.
Entity Types
Date Format
Dates support:
- Plain years:
1815, 500
- Approximate dates:
c. 1760 (prefix with "c. ")
- BCE dates:
500 BCE, c. 1,700,000 BCE
- Empty for unknown
IMPORTANT: If start and end years are the same, ONLY specify the start year (birth/start), not the end year (death/end).
Examples:
--birth 1815 → stored as year 1815, not approximate
--birth "c. 500 BCE" → stored as year -500, approximate
--start "c. 1760" → stored as year 1760, approximate
--start 1914 --end 1914 → ❌ Wrong! Use --start 1914 only
--birth 1889 --death 1889 → ❌ Wrong! Use --birth 1889 only
Person
name: Full name
known_for: Brief description of significance (used in isolation for quiz questions - must be distinctive and informative without being verbose)
birth/death: Years (see Date Format above)
tags: Required (at least Region + Period)
notes: Additional context (see Notes Field below) - avoid duplicating information from known_for or relationships
source: Attribution
Event
name: Event name
summary: Brief description (used in isolation for quiz questions - must be distinctive and informative without being verbose)
start_date/end_date: Years (see Date Format above - remember: if same year, only specify start)
tags, notes, source: Same as Person
notes: Avoid duplicating information from summary or relationships
Notes Field
The notes field is valuable for adding historical context that doesn't fit elsewhere.
IMPORTANT: Avoid duplication. Don't repeat information already in:
known_for or summary fields
- Relationship descriptions
- Other notes
Use notes to include:
- Interesting historical details and trivia not mentioned elsewhere
- Context that helps understand the person/event's significance
- Explanations of unusual names, terms, or dating systems
- Key dates and specific facts worth remembering
- Pronunciation guides for names not intuitive to English speakers
Pronunciation Guidelines
For names whose pronunciation is not intuitive for English speakers, add the IPA pronunciation at the end of the notes field. Format: Language: [IPA transcription]
Examples:
- Giuseppe Mazzini:
Italian: [dʒuˈzɛppe matˈtsiːni]
- Klemens von Metternich:
German: [ˈkleːmɛns fɔn ˈmɛtɐnɪç]
- Maximilien Robespierre:
French: [maksimiljɛ̃ ʁɔbɛspjɛʁ]
When to add pronunciation:
- Non-English names with unintuitive spelling (Italian, German, French, Hungarian, Russian, etc.)
- Names with silent letters or unusual letter combinations
- Names where English speakers commonly mispronounce
When NOT to add pronunciation:
- Common English names or anglicized versions
- Names that are pronounced as they are spelled in English
Examples of notes with context and pronunciation:
- For "Thermidorian Reaction": "Named after 9 Thermidor Year II in the French Republican Calendar (July 27, 1794). The Republican Calendar was adopted in 1793, replacing the Gregorian calendar with 12 months of 30 days each, named after natural phenomena. French: [teʁmidɔʁ]"
- For "Otto von Bismarck": "Bismarck began as an outspoken conservative firebrand but became famous for his pragmatic 'Realpolitik,' often outmaneuvering rivals through alliances, timing, and controlled crises. German: [ˈɔto fɔn ˈbɪsmaʁk]"
Always consider adding notes when creating or updating persons and events—they enrich the learning experience.
Picture and Source Fields (Persons only)
Images, source URLs, and licenses are provided by the user. Do not add these fields unless the user provides the information.
When the user provides an image:
When the user provides source/license info, use this format for the --source field:
--source 'Claude Sonnet 4.5<br><br>Image: <a href="https://en.wikipedia.org/wiki/...">Wikipedia</a> (Public domain)'
The source field has two parts separated by <br><br>:
- Data source: Who created/verified the entity data (e.g., "Claude Sonnet 4.5")
- Image attribution: Link to source and license provided by user
QA (Question & Answer)
question: The question to ask
answer: The expected answer
tags, notes, source: Same as above
Cloze
text: Text with Anki cloze deletions {{c1::text}} or {{c1::text::hint}}
- Must have at least one cloze deletion starting at c1
tags, notes, source: Same as above
Cloze Syntax
Valid cloze formats:
{{c1::answer}} - Basic cloze
{{c1::answer::hint}} - Cloze with hint
- Multiple clozes:
{{c1::first}} and {{c2::second}}
Examples:
"{{c1::Napoleon}} was emperor of {{c2::France}}."
"The {{c1::Treaty of Westphalia::1648}} ended the {{c2::Thirty Years' War}}."
Workflow for Adding New Entities
1. Research and Verify
Before creating, search to avoid duplicates:
uv run tools/neo4j_query.py search "bismarck"
2. Find Related Entities
Use time period and tags to discover relationships:
uv run tools/neo4j_query.py find-related "Otto von Bismarck" \
--start 1815 --end 1898 \
--tag "UH::Region::Europe"
3. Review Existing Tags
Check available tags to use consistent naming:
uv run tools/neo4j_query.py tags
4. Create the Entity
Use appropriate tags following the hierarchy. The script will warn about invalid tags.
5. Add Relationships
Link to related persons and events with descriptive relationships:
uv run tools/neo4j_query.py add-rel "Person A" "Person B" "was mentor to"
uv run tools/neo4j_query.py add-rel "Person A" "Event X" "led the"
6. Verify Creation
uv run tools/neo4j_query.py relations "Otto von Bismarck"
Relationship Guidelines
Relationships should be:
- Directional: Source -> Target with a description
- Verbose and contextual: Describe the relationship's historical significance, not just the connection type
- Historical: Focus on significant historical connections
- Non-duplicative: Don't repeat information already in "known_for"/"summary" or vice versa
When to Add Reverse Relationships
IMPORTANT: In most cases, add BOTH directions (A → B and B → A) with distinct contextual descriptions.
General rule: Add the reverse relationship unless the relationship is insignificant from one perspective.
Since each entity is limited to 5 related people and 5 related events, prioritize historically significant relationships. Sometimes a relationship is crucial from one entity's perspective but minor from the other's.
Example of asymmetric significance:
add-rel "Archduke Franz Ferdinand" "Assassination of Archduke Franz Ferdinand" "was killed in this event that triggered World War I"
Another example:
add-rel "Johann Minor Composer" "Ludwig van Beethoven" "studied composition with in Vienna (1815-1820)"
Default approach: Add both directions unless you have a specific reason not to (like the 5-item limit forcing prioritization).
IMPORTANT: Write detailed, contextual relationship descriptions. Short descriptions like "led" or "participated in" are insufficient. Instead, explain the nature and significance of the relationship.
Examples of good relationship descriptions:
-
❌ Bad: "was advisor to"
-
✅ Good: "conservative advisor who guided Alexander III's autocratic governance"
-
❌ Bad: "fought against"
-
✅ Good: "rival-turned-ally-turned-opponent whose conflicts with Russia shaped Alexander's reign"
-
❌ Bad: "participated in"
-
✅ Good: "promoted Russian industrialization through protective tariffs and initiated the Trans-Siberian Railway in 1891"
-
❌ Bad: "was father of"
-
✅ Good: "father whose assassination brought Alexander III to power and shaped his reactionary policies"
Common patterns:
- Person -> Person: "was teacher of", "married", "succeeded", "defeated"
- Person -> Event: "led", "participated in", "caused", "died during"
- Event -> Person: "resulted in rise of", "led to death of"
- Event -> Event: "caused", "preceded", "was part of"
Complete Example
uv run tools/neo4j_query.py search "bismarck"
uv run tools/neo4j_query.py find-related "Otto von Bismarck" --start 1815 --end 1898
uv run tools/neo4j_query.py create-person "Otto von Bismarck" \
--known-for "Prussian statesman who unified Germany through diplomacy and war" \
--birth 1815 --death 1898 \
--tag "UH::Region::Europe::Central" \
--tag "UH::Period::19th_Century" \
--tag "UH::Theme::Politics"
uv run tools/neo4j_query.py create-event "Franco-Prussian War" \
--summary "War between France and Prussia resulting in German unification" \
--start 1870 --end 1871 \
--tag "UH::Region::Europe::Western" \
--tag "UH::Region::Europe::Central" \
--tag "UH::Period::19th_Century" \
--tag "UH::Theme::War"
uv run tools/neo4j_query.py add-rel "Otto von Bismarck" "Franco-Prussian War" \
"orchestrated through the Ems Dispatch"
uv run tools/neo4j_query.py create-qa "How did Bismarck provoke France into the Franco-Prussian War?" \
--answer "By editing and publishing the Ems Dispatch to make it appear insulting to France" \
--tag "UH::Region::Europe" \
--tag "UH::Period::19th_Century" \
--tag "UH::Theme::Politics"
uv run tools/neo4j_query.py create-cloze \
"{{c1::Otto von Bismarck}} unified Germany through {{c2::three wars}}: against {{c3::Denmark}} (1864), {{c4::Austria}} (1866), and {{c5::France}} (1870-71)." \
--tag "UH::Region::Europe::Central" \
--tag "UH::Period::19th_Century" \
--tag "UH::Theme::War"
uv run tools/neo4j_query.py relations "Otto von Bismarck"