Import chess games from PGN into beautifully structured Obsidian notes.
Chessian automatically detects chess openings, game outcomes, time variants, and termination reasons—then renders everything into your customizable note templates. No manual metadata entry required.
- Chessian
- Paste PGN - Directly paste PGN notation into modal
- Chess.com API - Fetch recent public games by username, then copy PGN or create a note from the selected game
- Lichess API - Coming soon - Import directly from Lichess
Chessian enriches raw PGN data with intelligent detection:
- Prefers PGN Opening and ECO tags when available
- Falls back to analyzing move sequences against the complete ECO database (A–E, 4000+ variations)
- Uses exact move-order matching first, then a conservative transposition fallback for common alternative move orders
- Extracts:
- Opening: Full descriptive name (e.g., "Sicilian Defense")
- Variation: Specific variation branch (e.g., "Najdorf Variation")
- ECO: Standard classification code (e.g., "B90")
- Note: PGN headers are treated as the source of truth. Move-based detection is used when those headers are missing.
Opening Detection Disclaimer
Openings are detected using the Lichess open ECO database and move-based analysis. Due to differences in classification methods between platforms, detected openings may not always match those shown on Chess.com or other services.
- Major opening names become wiki-links:
[[Sicilian Defense]] - Linkable openings are configurable in settings
- The settings UI builds its opening list from the same ECO data used for opening detection
- Use the two-column selector to move openings between Selected and Available
- Search by opening name or ECO code, sort by name or ECO, and restore the default curated selection
- Only full opening names are linked (no partial matches)
Automatically infers your game result:
- Reads your username from settings (Lichess or Chess.com)
- Compares against PGN player names
- Converts
1-0,0-1,1/2-1/2→ win, loss, draw - Falls back to raw PGN result if username not found
- Player perspective fields (
player,opponent,playerColor,ownElo,opponentElo) are only filled when your configured username matches White or Black
- Uses the public Chess.com archives API; no authentication required
- Fetches the latest monthly archive for the entered username
- Shows recent games with date, players, result, and time control
- Lets you Copy PGN or Use in template to create a note through the existing PGN flow
- Caches fetched games in memory during the current plugin session to avoid repeated requests for the same username
Infers game type from time control:
0–60 sec→ Bullet61–180 sec→ Blitz181–600 sec→ Rapid600+ sec→ Classical
Automatically extracts or reconstructs:
- Lichess:
https://lichess.org/<gameId> - Chess.com: Extracted from PGN tags
- Fallback: Uses
GameIdorLinktag if present
Parses how the game ended:
- Types: Checkmate, Resignation, Timeout, Stalemate, Repetition, 50-move rule, Insufficient material, Agreement, Abandoned, Fair play violation
- Multilingual keyword detection (English, Polish)
- Provides both normalized type + localized label
- Converts PGN date format
YYYY.MM.DD→ StandardYYYY-MM-DD
Define exactly how your notes look. Three template types:
In settings, each template field includes a Restore default button. The Template variables help button shows the available {{variable}} placeholders without leaving Obsidian.
This creates: 2026-04-14 - Magnus vs Ding.md
---
white: {{white}}
whiteElo: {{whiteElo}}
black: {{black}}
blackElo: {{blackElo}}
eco: {{eco}}
opening: {{opening}}
openingBase: {{openingBase}}
openingBaseLinked: {{openingBaseLinked}}
variant: {{variant}}
outcome: {{outcome}}
termination: {{terminationLabel}}
date: {{date}}
link: {{link}}
---Missing values in frontmatter are rendered as null so generated YAML stays valid. For example, if the configured username is not a participant in the game, perspective fields can safely render as:
player: null
opponent: null
ownElo: null| Variable | Type | Example |
|---|---|---|
white |
string | "Magnus Carlsen" |
whiteElo |
number | "2758" |
black |
string | "Ding Liren" |
blackElo |
number | "2700" |
player |
string | null | "Magnus Carlsen" |
opponent |
string | null | "Ding Liren" |
ownElo |
number | null | "2758" |
opponentElo |
number | null | "2700" |
playerColor |
string | null | "white" |
result |
string | "1-0" |
outcome |
string | "win" |
opening |
string | "Sicilian Defense: Najdorf Variation" |
openingBase |
string | "Sicilian Defense" |
openingBaseLinked |
string | "[[Sicilian Defense]]" |
openingVariation |
string | "Najdorf Variation" |
openingLinkable |
boolean | "true" |
eco |
string | "B90" |
variant |
string | "rapid" |
date |
string | "2026-04-14" |
dateLabel |
string | "2026-04-14" |
timeControl |
string | "300+3" |
timeControlLabel |
string | "5+3" |
platform |
string | "lichess" / "chess.com" |
site |
string | "lichess.org" |
link |
string | "https://lichess.org/abc123" |
gameId |
string | "abc123" |
termination |
string | "checkmate" |
terminationLabel |
string | "Checkmate" |
movesCount |
number | "42" |
moves |
string | "1. e4 c5 2. Nf3 d6" |
movesList |
string[] | ["e4", "c5", "Nf3", "d6"] |
pgn |
string | Full PGN text with headers |
rawPgn |
string | Original unprocessed PGN text |
The in-app variable helper groups variables into Common, Players and perspective, Game details, Moves, Advanced, and Future API fields. Planned future API placeholders are shown as disabled hints only.
Smart filename generation prevents data loss:
- First import:
Game.md - Second:
Game-1.md - Third:
Game-2.md - Works across all import methods consistently
- Generated filenames are sanitized for Obsidian vault paths
- Missing nested folders in the configured default folder are created automatically
- Default folder – Where imported notes are created (default:
Chess) - Language – English or Polish. Applies to settings UI and localized generated labels.
- Lichess username – For auto-detecting wins/losses in Lichess games
- Chess.com username - For Chess.com game outcome detection and as the default username in the Chess.com import tab
- Smart result detection – Toggle automatic win/loss/draw inference
- Templates – Customize filename, frontmatter, and note body templates; restore defaults when needed
- Template variables – Open an in-app helper listing all available template placeholders
- Linkable openings – Choose which detected opening names become Obsidian wiki-links
- Move openings between Selected and Available with double-click or Enter
- Filter selected and available openings independently
- Search/filter by ECO code
- Sort by opening name or ECO code
- Restore the curated defaults or clear all opening links
Chess.com imports fetch recent public games from the latest monthly archive, map the API response into the shared game model, and then reuse the same PGN parsing, enrichment, templating, and file creation flow as pasted PGNs.
Raw PGN is parsed into components:
- Player names, ratings, dates
- PGN tags (ECO, Site, Result, TimeControl, Termination, etc.)
- Move list (cleaned of annotations and numeric markers)
- Full PGN text (
pgn) and original raw PGN (rawPgn)
A trie-based tree is built from ECO database at plugin load:
root
├─ e4
│ ├─ c5 (Sicilian Defense)
│ │ ├─ d6 (Sicilian Defense: Open)
│ │ └─ e6 (Sicilian Defense: French Variation)
│ └─ e5 (Open Game)
...
For each game, Chessian first uses PGN Opening and ECO tags when present.
When those tags are missing, moves are traversed through the tree and the deepest exact match is used.
If the exact path only finds an early match, a side-aware transposition fallback can prefer a deeper ECO line reached through a common alternative move order.
The settings tab derives a unique list of opening names from the ECO database.
Selected openings are saved in plugin settings and used during enrichment to decide whether {{openingBaseLinked}} should render as a wiki-link.
ECO codes are displayed as compact contiguous ranges. Non-contiguous codes remain explicit, for example:
A00, A03, A10-A11
Game data is augmented with:
- Detected opening name + variation + ECO code
- Wiki-linked opening names based on your selected linkable openings
- Inferred outcome (win/loss/draw)
- Inferred variant (bullet/blitz/rapid/classical)
- Reconstructed game link
- Normalized termination reason
- Player perspective only when the configured username matches White or Black
- Display-friendly fields such as
dateLabel,timeControlLabel, and localized termination labels
enrichPGN() output is merged into templates using simple {{variable}} substitution.
Internally, Chessian maps parsed/enriched data into a structured Game model with players, ratings, opening, metadata, moves, and PGN fields. Existing template variables remain backward compatible.
Frontmatter rendering is YAML-safe: missing values and PGN/API ? ratings are rendered as null in frontmatter rather than placeholder text.
Note is created with smart duplicate prevention to avoid overwrites.
- Open Obsidian → Settings → Community plugins → Browse
- Search "Chessian"
- Install and Enable
Disclaimer This plugin is not yet available in the Obsidian Community Plugins directory.
# Clone
git clone https://github.com/mik0lajek/chessian
cd chessian
# Install dependencies
npm install
# Build
npm run build
# Output: main.js, manifest.jsonCopy to: <YourVault>/.obsidian/plugins/chessian/
Run the unit test suite:
npm testRun tests with coverage:
npm run test:coverage- Set your username in plugin settings (Lichess or Chess.com)
- Optionally choose your Language, templates, and linkable openings
- Click Chessian icon in ribbon (or open modal)
- Paste a PGN manually, or open the Chess.com tab and fetch recent games by username
- Select Create note for pasted PGN, or Use in template for a Chess.com game
- Note is created in your default folder with all metadata extracted and templated
Example:
Input: [White "Magnus"] [Black "Ding"] [Result "1-0"] ... 1.e4 c5 2.Nf3 ...
Output:
File: "2026-04-14 - Magnus vs Ding.md"
Content:
---
white: Magnus
black: Ding
opening: [[Sicilian Defense]]
outcome: win
---
# Magnus vs Ding
Opening: [[Sicilian Defense]] – Najdorf Variation (B90)
Result: win
- v1.1 - Lichess API integration (direct game import)
- v1.2 - Additional Chess.com controls and filtering
- v1.3 - Interactive board rendering (move-by-move visualization)
- Board rendering not yet implemented
- Lichess API is still a placeholder
- Chess.com import uses only public recent monthly archives and does not support authentication
- Chess.com game cache is in-memory only and resets when the plugin reloads
- Template system is basic (no conditionals or filters)
- Supports online PGNs only (Lichess, Chess.com formats)
Found a bug or have an idea? Open an issue on GitHub.
MIT (See LICENSE)