원클릭으로
gedcom
Parse, validate, import/export GEDCOM files (5.5.1 and 7.0). Use for .ged files, genealogy data interchange, or GEDCOM compliance.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Parse, validate, import/export GEDCOM files (5.5.1 and 7.0). Use for .ged files, genealogy data interchange, or GEDCOM compliance.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Audit place resolution against a real database to find outliers — places that resolve to the wrong country, state, or sub-region. Use when investigating bad map pins, validating new gazetteers, or debugging "why did Richmond, Kalifornien USA land in Canada?". Pairs with the `gazetteers` skill (build/extend) — this skill is for *testing* placement on real data.
Use whenever dispatching subagents in this project — implementer, spec-reviewer, or code-quality-reviewer. Wraps the upstream `superpowers:subagent-driven-development` skill with project-local prompt templates that center user goals (not just spec compliance) and require the dispatcher to verify user-observable outcomes before marking work done.
Decide which Playwright tier to run, capture the right evidence for plan close-out, and route work into the right project. Use when finishing a plan (gate before archive), when adding an e2e test (which project gets the spec), when CI fails on `[boot]` / `[crud]` / `[panels]` / `[reactivity]` / `[imports]` and you need to know which user-goal it protects, or when the question is "is `npm run test:e2e` enough or do I need `:full`?".
Extend the Släktforskning MCP server — add new tools to createProdServer.ts / createDevServer.ts, wire window.api bindings in tauri-window-api.ts + static-api stubs, test via tests/unit/mcp.test.ts, debug agent-facing IPC. Also covers the dev MCP HTTP bridge (src-tauri/src/ui_server.rs) used by ui_screenshot / ui_click / ui_eval / chart_*. Use when modifying anything in src/mcp/, src/renderer/tauri-window-api.ts, or src-tauri/src/ui_server.rs. Distinct from `slaktforskning-mcp` (which is for an agent *using* the MCP tools to do genealogy work for the user).
Build, extend, and debug gazetteers for place resolution. Use when adding new country gazetteers, modifying build scripts, debugging place matching, or questions about the gazetteer system (types, resolver, normalization, data sources).
Use when actually doing genealogy research with the Släktforskning MCP — building real family trees end-to-end, exporting/round-tripping, attaching media + face tags, importing custom gazetteers for places not in the bundled set. Pairs with `slaktforskning-mcp` (which lists the tools). Distinct from `slaktforskning-mcp-dev` (extending the MCP server itself). Triggers on real research workflows, "research X family", "test the app end-to-end", "set up a Bernadotte-style demo".
| name | gedcom |
| description | Parse, validate, import/export GEDCOM files (5.5.1 and 7.0). Use for .ged files, genealogy data interchange, or GEDCOM compliance. |
GEDCOM imports are a write path — they bring data into the database from the source file. Per the data-fidelity prime directive in CLAUDE.md, the importer must:
MAP > LATI/LONG sub-tags get persisted to places.latitude/longitude because the file already had those coordinates — they came with the file the user imported. That's authored data being preserved.date_type='exact' because a DATE line had a parseable string. Don't auto-resolve PLAC "Stockholm" to coordinates via a gazetteer and persist them — let the resolver compute coords at view time.Export has the mirror obligation: round-trip what the database stores, with explicit excluded[] reporting for entities GEDCOM 5.5.1 cannot represent. Don't synthesize plausible-looking values to "complete" the export.
This rule is non-negotiable. Past violations corrupted real databases.
GEDCOM (Genealogical Data Communication) is the de facto standard for exchanging family tree data between genealogy applications.
Target 5.5.1 for maximum compatibility.
0 HEAD
1 GEDC
2 VERS 5.5.1
1 CHAR UTF-8
0 @I1@ INDI
1 NAME Lars /Eriksson/
1 SEX M
1 BIRT
2 DATE 15 MAR 1842
2 PLAC Björkvik, Rönö härad, Södermanland
0 @F1@ FAM
1 HUSB @I1@
1 WIFE @I2@
1 CHIL @I3@
1 MARR
2 DATE 14 JUN 1869
0 TRLR
Line format: LEVEL [XREF_ID] TAG [VALUE]
HEAD, INDI, FAM, SOUR, REPO, NOTE, OBJE, SUBM, TRLRThis app uses a GEDCOM-X-inspired model. Here is how GEDCOM 5.5.1 maps to it:
| GEDCOM 5.5.1 | App entity | Notes |
|---|---|---|
INDI | persons | Direct |
INDI.SEX | persons.sex | M/F/U |
INDI.NAME | person_names | Parse Given /Surname/ format |
INDI.NAME.NPFX | person_names.name_prefix | Requires v0.3.1 schema |
INDI.NAME.NSFX | person_names.name_suffix | Requires v0.3.1 schema |
INDI.REFN | person_identifiers (type=refn) | Requires v0.3.1 schema |
INDI.RIN | person_identifiers (type=rin) | Requires v0.3.1 schema |
INDI.BIRT/DEAT/CHR/BURI/OCCU/RESI/... | events + event_participants (role=primary) | |
FAM | relationships (type=couple) | HUSB=person1, WIFE=person2 |
FAM.CHIL | relationships (type=parent_child) | One per parent |
FAM.MARR/DIV/CENS/... | events linked via relationship_id | |
PLAC | places via findOrCreatePlace(name) | Hierarchical string stored as-is |
SOUR (level 0) | sources | title/author/publication_info |
SOUR (inline citation) | citations | QUAY→confidence, PAGE→page, DATA.TEXT→transcription |
DATE | events.date_type + date_value + date_original | See date table below |
NOTE | persons.notes, events.description | Concatenate CONT/CONC lines |
| GEDCOM tag | Reason |
|---|---|
REPO record | Repository is just a text field on sources.repository |
SUBM record | No submitter concept in app |
OBJE / multimedia | Imported; refs normalised by consolidateMediaFolder to <dbname>-media/.... See .claude/rules/media.md |
ASSO associations | No general association concept |
ALIA | No identity alias linking |
LDS ordinances (BAPL, SLGC, CONL, ENDL, SLGS) | Not relevant for Swedish genealogy |
ANCI/DESI | Researcher flags — no equivalent |
AFN/RFN | Rarely used in Swedish trees |
_ prefixed custom tags | Reported in skipped (never silently dropped — see data integrity rule) |
From the GEDCOM-X spec, these are gaps in the current data model beyond what v0.3.1 adds:
Critical for future import quality:
Agent entity — contributor/researcher tracking; used for SUBM and source attributionDocument entity — transcription/analysis documents; no equivalent in appPlaceDescription.names list)Lower priority:
Major genealogy apps emit GEDCOM with their own dialect quirks. The repo carries two layers of test coverage to keep the GEDCOM importer honest about them:
Synthetic dialect fixtures at tests/fixtures/gedcom/dialects/ — one minimal .ged per app (RootsMagic, Gramps, Family Tree Maker, Legacy, MacFamilyTree, Family Historian, MyHeritage, PAF, Holger, Genney) carrying that app's 1 SOUR signature plus characteristic custom tags. tests/unit/import-gedcom-dialects.test.ts asserts each imports without crashing and that no core GEDCOM tag (NAME, INDI, FAM, BIRT, DEAT, MARR, SEX, …) ends up in the report's skipped list.
Real-world samples (gitignored) at export-import/samples/:
familysearch-gedcom7/ — official FamilySearch GEDCOM 7.0 reference test files (24 files; download via https://raw.githubusercontent.com/FamilySearch/GEDCOM.io/main/testfiles/gedcom70/<name>.ged)gramps/sample.ged — Gramps's official sample, real Gramps exportheiner-torture/allged.ged — Heiner Eichmann's GEDCOM 5.5 torture testd-jeffrey/ — 12 real exports tagged by source app (RootsMagic 8 Queen 4683 persons; FTM 20 Habsburg 34020 persons; PAF 2.2 royal92; Legacy ivar/tudor; FamilyOrigins washington; ANCESTRIS bourbon/kennedy)The diagnostic loop when adding new tag handling: walk all 36 samples through the importer, eyeball the per-file skipped-tag list, decide for each tag whether it's a real loss to fix (e.g. _UID/AFN/SSN/FSID → person identifiers, CREM/BARM/ANUL/MARL/_SEPR → new event types) or an intentional drop (LDS ordinances, app-internal flags like _UPD / _PHOTO / _PPEXCLUDE).
After every importer change, the canonical "did anything break" check is: rerun the dialect tests + walk the real samples once more. If a previously-handled tag falls into the skipped list on a real sample, that's a regression.
| GEDCOM date string | date_type | date_value | date_value_end |
|---|---|---|---|
12 JUN 1845 | exact | 1845-06-12 | null |
JUN 1845 | exact | 1845-06 | null |
1845 | exact | 1845 | null |
ABT 1845 / CAL 1845 / EST 1845 | about | 1845 | null |
BEF 1850 | before | 1850 | null |
AFT 1840 | after | 1840 | null |
BET 1840 AND 1850 | between | 1840 | 1850 |
FROM 1840 TO 1850 | between | 1840 | 1850 |
| Any other string | unknown | null | null |
Always preserve the original GEDCOM date string in date_original.
Use date_original if set (preserves the original format). Otherwise reconstruct from date_type + date_value.
GEDCOM 5.5.1 PLAC is a free-text comma-separated hierarchy: "Björkvik, Rönö härad, Södermanland, Sverige".
On import: Call findOrCreatePlace(name) for the full string. The hierarchy is preserved in the name field as-is. Parsing and linking hierarchy levels is optional post-processing.
On export: Use place.name directly as the PLAC value.
GEDCOM 5.5.1 has no ADDR directly on PLAC tags. The ADDR structure appears on the containing event (e.g. RESI):
1 RESI
2 PLAC Tvärgatan 5, Växjö, Sverige
2 ADDR Tvärgatan 5
3 ADR1 Tvärgatan 5
3 CITY Växjö
3 POST 35243
3 CTRY Sverige
On import: When a RESI (or other event) has both PLAC and ADDR, populate the address columns on the corresponding place record from ADR1 → street, CITY → city, POST → postal_code, CTRY → country. Use updatePlace(db, place.id, { street, city, postal_code, country }).
On export: If a place has street set, emit ADDR/ADR1/CITY/POST/CTRY below the event's PLAC tag.
GEDCOM NAME format: Given /Surname/ Suffix or just Given /Surname/
On import:
const match = raw.match(/^(.*?)\/(.+?)\/(.*)?$/);
const given = match?.[1]?.trim() || null;
const surname = match?.[2]?.trim() || null;
On export:
1 NAME Lars /Eriksson/
2 NPFX von ← if name_prefix set
2 NSFX Jr. ← if name_suffix set
| Tag | Meaning |
|---|---|
NAME | Full name; surname in slashes: Lars /Eriksson/ |
SEX | M, F, U |
BIRT | Birth event |
DEAT | Death event |
BURI | Burial |
CHR / BAPM | Christening / Baptism |
CONF | Confirmation |
OCCU | Occupation |
RESI | Residence |
EMIG / IMMI | Emigration / Immigration |
NATU | Naturalization |
CENS | Census |
EDUC | Education |
GRAD | Graduation |
RETI | Retirement |
PROB / WILL | Probate / Will |
NOTE | Free-text note |
SOUR | Source citation |
REFN | Reference number (external ID) |
RIN | Record ID number |
FAMC | Family as child (pointer to FAM) |
FAMS | Family as spouse (pointer to FAM) |
| Tag | Meaning |
|---|---|
HUSB | Pointer to husband INDI |
WIFE | Pointer to wife INDI |
CHIL | Pointer to child INDI (repeat for each child) |
MARR | Marriage event |
DIV | Divorce event |
CENS | Census (family) |
| Tag | Meaning |
|---|---|
DATE | Event date |
PLAC | Place (comma-separated hierarchy) |
NOTE | Note about this event |
SOUR | Source citation for this event |
1 SOUR @S1@
2 PAGE p. 42
2 DATA
3 TEXT verbatim text from source
2 QUAY 2
QUAY = 0 (unreliable) to 3 (direct primary evidence) — maps directly to citations.confidence.
0 @S1@ SOUR
1 TITL 1880 Swedish Church Records
1 AUTH Riksarkivet
1 PUBL Stockholm
1 REPO @R1@
Swedish GEDCOM files (especially from Genney/ArkivDigital) use a structured source title format:
Parish (CountyCode) Series:Volume (YearRange)
Examples: Skepperstad (F) C:8 (1921-1952), Hultsjö (F) AIIa:4 (1914-1951)
Archive series codes:
| Code | Record Type |
|---|---|
| AI | Husförhörslängder (household examination) |
| AII | Församlingsböcker (parish books, post-1894) |
| AIIa | Parish records variant |
| B/BI | In/ut-flyttningslängder (migration records) |
| C | Födelse/dopböcker (birth/christening) |
| E | Lysning/vigselböcker (marriage) |
| F | Död/begravningsböcker (death/burial) |
Linkable identifiers in citation notes:
AID: v170308.b530.s44 → ArkivDigital deep link: https://app.arkivdigital.se/volume/v170308?image=530NAD: SE/VALA/00333 → Riksarkivet archive referenceREPO records map to link targets: ArkivDigital → app.arkivdigital.se, Riksarkivet → sok.riksarkivet.se, Sveriges släktforskarförbund → genealogi.se (Dödboken, Sveriges Befolkning).
The source linker (src/api/source-linker.ts) auto-detects these patterns and renders inline links. See src/api/link-rules/sv.ts for the regex rules.
SNOTE (shared note reference)INDI.NO (negative assertion — "this person had no children")SCHMA tag (custom tags without _ prefix)CONC line concatenationPEDI values for parent-child)A minimal line-by-line parser:
LEVEL [XREF] TAG [VALUE]\n)TypeScript libraries for this project:
read-gedcom — browser and Node.js compatible, parses to a queryable treegedcom-stream — streaming parser, good for large files (100MB+)Data must never be silently lost during import or export. This is fundamental to user trust.
Every piece of data that is dropped, skipped, remapped, or excluded must be reported to the user with:
Use the ImportReport fields for import, and a pre-export warning for export:
skipped: { tag, count }[] — unrecognised INDI/FAM tags (tag name + count, always shown)unmappedData: { category, count }[] — known-unsupported record types with human-readable explanationwarnings: string[] — data that was transformed/remapped rather than dropped straight (e.g. "6573 REMA remarks imported as person notes")On export: if any DB entities cannot be represented in GEDCOM (e.g. Research Tasks, Groups), the export function must return a summary of what was excluded and why, so the UI can show it to the user.
Never use unmappedData/warnings for import and then omit the equivalent for export. Both directions must be transparent.
| Situation | Required |
|---|---|
| Tag appears in file but has no DB mapping | skipped entry with tag + count |
| Known record type with no app concept (REPO, SUBM) | unmappedData entry with description |
| Data remapped/converted (e.g. TRAN → aka name) | warnings entry explaining conversion |
| DB entity type that cannot be exported to GEDCOM | Export summary entry with count + reason |
| Data actively handled but user may not expect it | warnings entry (e.g. REMA imported as notes) |
persons.living) — document in SKILL.md "What is dropped" table instead0 HEAD with 1 GEDC + 2 VERS 5.5.1 + 1 CHAR UTF-8@I1@, @F1@, @S1@, etc.)0 TRLR at enddate_original if set)HUSB/WIFE in FAM → FAMS back-references on INDI (optional but standard)CHIL in FAM → FAMC back-references on INDI (optional but standard)@I1@, @F1@, etc.) using a mapGiven /Surname/ + NPFX + NSFXfindOrCreatePlace(name) for all PLAC valuesdate_original\nGiven /Surname/ Suffix; others omit the slashes. Handle gracefully._MILI, _FSID, etc. Don't crash — report in skipped, never drop silently.HEAD.CHAR tag.2 PLAC with no value. Skip these; don't call findOrCreatePlace('').Every column in every non-exempt table has an entry in src/api/gedcom_fidelity_registry.ts declaring its round-trip status under GEDCOM 5.5.1 and 7.0. Three tests enforce the contract:
tests/unit/gedcom-fidelity-registry-coverage.test.ts — schema-introspection guard. Adding a column without a registry entry fails CI.tests/unit/gedcom-fidelity-per-field.test.ts — per-(table, column, version) round-trip.tests/unit/gedcom-fidelity-golden.test.ts — comprehensive multi-table seed → round-trip.When you change anything in src/import/gedcom/ or src/gedcom/exporter.ts, run those three tests. When you add a schema column, the coverage test will tell you to register it.
See CLAUDE.md "⚠️ Prime Directive (cont.): Round-Trip Fidelity" for the why.