Files

1 line
165 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "atomflow-ai/molecode", "files": {"README.md": {"a4df3b04552b829ff816467b9620757a5dad765b": {"t": 1785747237.9117143, "n": 14395, "h": "72aa1f72300957a7", "c": "<div align=\"center\">\n\n# 🧬 MoleCode\n\n### An LLM-native, graph-explicit molecular language\n\nOfficial repository for [**MoleCode unlocks structural intelligence in large language models**](https://arxiv.org/pdf/2605.16480).\n\n*Molecode presents molecules as code and enables LLMs to operate and reason on chemistry directly.*\n<br>*Instead of making language models reconstruct molecular structure from cryptic strings,*\n<br>*MoleCode lets them read, write, and edit directly on the structures.*\n\n[![arXiv](https://img.shields.io/badge/arXiv-MoleCode-firebrick)](https://arxiv.org/abs/2605.16480)\n[![PDF](https://img.shields.io/badge/PDF-DADBDD)](https://arxiv.org/pdf/2605.16480)\n[![Website](https://img.shields.io/badge/AtomFlow-atomflow--ai.com-0b7285.svg)](https://atomflow-ai.com/)\n[![GitHub Stars](https://img.shields.io/github/stars/AtomFlow-AI/MoleCode.svg?style=social\\&label=Stars)](https://github.com/AtomFlow-AI/MoleCode)\n<br>[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)\n[![Powered by RDKit](https://img.shields.io/badge/powered%20by-RDKit-green.svg)](https://www.rdkit.org/)\n<br>[![Works with Claude Code](https://img.shields.io/badge/Works%20with-Claude%20Code-d97757.svg)](.claude/skills/molecode/)\n[![Works with Codex](https://img.shields.io/badge/Works%20with-Codex-412991.svg)](AGENTS.md)\n[![Agent Skill](https://img.shields.io/badge/Agent-Skill-blue.svg)](.claude/skills/molecode/SKILL.md)\n\n**English** | [中文](README.zh-CN.md)\n\n<br>\n<br>\n\n<img src=\"docs/assets/overview.png\" alt=\"MoleCode overview\" width=\"100%\">\n\n</div>\n\n---\n\n## Try our latest products on the official website!\nPlease visit the [AtomFlow website](https://atomflow-ai.com/).\n\n<p align=\"center\">\n <img src=\"docs/assets/demo_atomchat.png\" width=\"33%\" />\n <img src=\"docs/assets/demo_retro.png\" width=\"33%\" />\n <img src=\"docs/assets/demo_paper_read.png\" width=\"33%\" />\n</p>\n\n<br>\n \n## What is MoleCode?\n\nA molecule **is** a graph: atoms are nodes, bonds are edges, and chemistry emerges from the topology. Yet large language models are almost always fed molecules as *linear strings* like SMILES, where the graph is **implicit** — connectivity is positional, branches are syntactic, and rings hide inside index digits. Before an LLM can do any chemistry, it must first *reconstruct the graph from the syntax*, spending reasoning budget on structural bookkeeping.\n\n**MoleCode makes the structure the language.** Every atom and bond is written as a typed declaration with a persistent identifier, serialized as a [Mermaid](https://mermaid.js.org/) graph. Topology becomes directly readable, editable, and auditable inside the context window — and the format is **deterministically and losslessly inter-convertible with SMILES / MOL via RDKit** (no learned model, no information loss).\n\n```mermaid\ngraph TB\n subgraph chlorophenol[\"para-chlorophenol\"]\n chlorophenol_C_1[C]\n chlorophenol_O_1[OH]\n chlorophenol_C_2[CH]\n chlorophenol_C_3[CH]\n chlorophenol_C_4[C]\n chlorophenol_Cl_1[Cl]\n chlorophenol_C_5[CH]\n chlorophenol_C_6[CH]\n chlorophenol_C_1 === chlorophenol_C_2\n chlorophenol_C_2 --- chlorophenol_C_3\n chlorophenol_C_3 === chlorophenol_C_4\n chlorophenol_C_4 --- chlorophenol_C_5\n chlorophenol_C_5 === chlorophenol_C_6\n chlorophenol_C_6 --- chlorophenol_C_1\n chlorophenol_C_1 --- chlorophenol_O_1\n chlorophenol_C_4 --- chlorophenol_Cl_1\n end\n```\n\n> The same `Subgraph → Node → Edge` grammar covers **small molecules, polymers, and Markush structures** — and extends to reaction mechanisms and multimodal document parsing.\n\n---\n\n## Why it matters\n\n| | SMILES | **MoleCode** |\n| --- | --- | --- |\n| Topology | implicit, positional | **explicit, named nodes & edges** |\n| Atom identity | none | **persistent IDs** (stable across prompt → reasoning → output) |\n| Editing | whole-string rewrite | **local graph op** (add a methyl = 1 node + 1 edge) |\n| Validation | fragile string parsing | **deterministic RDKit round-trip** |\n| Reasoning behavior | memorizes syntax | **generalizes over structure** |\n\nEmpirically (see the [MoleCode paper](#-citation) and [docs/06-why-it-works.md](docs/06-why-it-works.md)):\n\n- **Generalization, not memorization.** SMILES accuracy collapses from ~42% on familiar molecules to ~20% on novel ones; MoleCode holds **~76–80%** across all familiarity tiers.\n- **Cheaper reasoning.** MoleCode has longer *input* but its chain-of-thought grows **sub-linearly** with molecule size (~C^0.52) versus SMILES' super-linear ~C^1.65 — about a **5× lower total token cost** per query.\n- **Scales to big, repetitive objects.** Full-chain SMILES accuracy falls toward **0%** as polymer chains grow; MoleCode stays flat.\n- **Markush understanding** jumps from **38.1% → 84.0%**.\n\n---\n\n## Install\n\n```bash\npip install molecode # from PyPI — pulls in rdkit + networkx\n```\n\nOr from source (for the examples, the Agent Skill, and development):\n\n```bash\ngit clone https://github.com/AtomFlow-AI/MoleCode.git\ncd MoleCode\npip install -e .\n```\n\n> `pip install molecode` gives you the **library** (`molecode.molecule`,\n> `molecode.polymer`, `molecode.markush`, `molecode.prompts`, `molecode.llm`).\n> The runnable [`examples/`](examples) and the [Agent Skill](.claude/skills/molecode/)\n> live in the repository. Full API reference → [docs/api.md](docs/api.md).\n\n## Quick start\n\n```python\nfrom rdkit import Chem\nfrom molecode import mol_to_mermaid, mermaid_to_mol, mol_to_smiles\n\n# SMILES -> MoleCode graph\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nprint(graph)\n\n# MoleCode graph -> SMILES (lossless round-trip)\nassert mol_to_smiles(mermaid_to_mol(graph)) == Chem.CanonSmiles(\"CC(=O)Oc1ccccc1C(=O)O\")\n```\n\n---\n\n## Works with your coding agent (Claude Code · Codex)\n\nMoleCode ships as a ready-to-use **[Agent Skill](https://docs.claude.com/en/docs/claude-code/skills)**,\nso coding agents can clone this repo and immediately reason over and edit\nmolecules at the explicit-graph level — no extra setup, no MCP server required.\n\n| Agent | How it picks MoleCode up |\n| --- | --- |\n| **Claude Code** | Auto-discovers the skill at [`.claude/skills/molecode/`](.claude/skills/molecode/). Just ask it to understand or edit a molecule. |\n| **Codex** (and other agents) | Reads [`AGENTS.md`](AGENTS.md) at the repo root and uses the bundled CLI; interface metadata in [`agents/openai.yaml`](.claude/skills/molecode/agents/openai.yaml). |\n\nInstead of asking the model to hand-write SMILES — error-prone for anything\nnon-trivial — the skill has it **convert → inspect the named atoms/bonds → edit\nthe graph → validate**, all through one stable CLI:\n\n```bash\npython .claude/skills/molecode/scripts/molecode_convert.py doctor\npython .claude/skills/molecode/scripts/molecode_convert.py smiles-to-molecode \"CCO\" --name Ethanol\npython .claude/skills/molecode/scripts/molecode_convert.py validate --input edited.mmd # formula, counts, round-trip\npython .claude/skills/molecode/scripts/molecode_convert.py molecode-to-smiles --input edited.mmd\n```\n\nThe skill bundles the six conversion forms (SMILES / PSMILES / Markush ↔\nMoleCode) plus `validate`, `compare` (Markush-aware isomorphism) and `doctor`, a\nsyntax reference for hand-editing graphs, and a file-based edit workflow built\nfor large molecules. See [`.claude/skills/molecode/SKILL.md`](.claude/skills/molecode/SKILL.md).\n\n## Three domains, one grammar\n\n### 🧪 Small molecules — [`molecode.molecule`](molecode/molecule)\n\nAtoms are `prefix_Element_Number[Label]` nodes; bonds are `---` (single), `===` (double), `-.-` (triple), with `===|E|`/`===|Z|` and `_R`/`_S` for stereochemistry. → [syntax reference](docs/02-syntax.md)\n\n### 🔗 Polymers — [`molecode.polymer`](molecode/polymer)\n\nThe repeat unit stays **explicit** as a subgraph carrying a symbolic `×n` count, with `TL`/`TR` terminus markers — so the graph does not blow up with chain length. → [polymer docs](docs/03-polymers.md)\n\n```python\nfrom molecode.polymer import polymer_to_mermaid, mermaid_to_psmiles\n\ngraph = polymer_to_mermaid(\"*NCCCCCC(=O)*\", n=8, name=\"Nylon-6\") # PSMILES -> graph\nmermaid_to_psmiles(graph) # -> '*NCCCCCC(=O)*'\n```\n\n### 🧩 Markush structures — [`molecode.markush`](molecode/markush)\n\nVariable R-groups and named substituents become **abbreviation nodes** in curly braces — `{R1}`, `{Boc}`, `{Ar}` — something plain SMILES cannot express. A built-in graph-isomorphism comparator scores predictions up to abbreviation expansion. → [Markush docs](docs/04-markush.md)\n\n```mermaid\ngraph TB\n subgraph Mol[\"molecule name\"]\n Mol_C_1[C]\n Mol_O_1[OH]\n Mol_X_1{Boc}\n Mol_X_2{R1}\n Mol_C_1 --- Mol_O_1\n Mol_C_1 --- Mol_X_1\n end\n```\n\n---\n\n## Run the tasks: understand · generate · edit · reason\n\nMoleCode is a **drop-in representation for any LLM** — feed the grammar as a system prompt, hand the model a graph, and validate its output deterministically. The [`examples/`](examples) folder has runnable scripts for all four task families (they run **offline by default**, printing the exact prompt; set `MOLECODE_API_KEY` to call a model):\n\n```bash\npython examples/01_molecule_roundtrip.py # SMILES <-> graph (lossless)\npython examples/02_polymer_roundtrip.py # polymers with ×n\npython examples/03_markush_roundtrip.py # abbreviation nodes & isomorphism\npython examples/04_understanding.py # count atoms / formula / rings ...\npython examples/05_generation.py # de novo design under constraints\npython examples/06_editing.py # local graph edits (add/del/substitute)\npython examples/07_reasoning.py # reaction-product prediction\npython examples/08_image_to_molecode.py # OCSR: molecule image -> MoleCode (vision model)\n```\n\nThe reusable ingredients:\n\n```python\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT # give this to the LLM as the system prompt\nfrom molecode.molecule import mol_to_mermaid # your molecule -> what the model reads\nfrom molecode.molecule import mermaid_to_mol # model output -> validated RDKit Mol\n```\n\n### Calling an LLM\n\nMoleCode is just a representation, so you can use **any** LLM SDK — the prompts\nare plain strings. For convenience the package also ships a tiny,\ndependency-free, **OpenAI-compatible** client (`molecode.llm.LLMClient`, built on\nstdlib `urllib`). You supply the API key and base URL — nothing is hard-coded, so\nit works with OpenAI, DeepSeek, Azure, Together, vLLM, Ollama, …\n\n```python\nfrom molecode import LLMClient\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT\nfrom molecode.molecule import mol_to_mermaid, mermaid_to_mol\nfrom rdkit import Chem\n\nclient = LLMClient(api_key=\"sk-...\", base_url=\"https://api.openai.com/v1\", model=\"\")\n# (or set MOLECODE_API_KEY / MOLECODE_BASE_URL / MOLECODE_MODEL and call LLMClient())\n\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nreply = client.chat(f\"How many carbons are in this molecule?\\n```mermaid\\n{graph}\\n```\",\n system=MOLECULE_SYSTEM_PROMPT)\nprint(reply)\n```\n\nPrefer the official `openai` SDK? Pass the same prompt strings straight to\n`openai.OpenAI().chat.completions.create(...)` — you don't need `LLMClient` at all.\n\nSee [docs/05-tasks.md](docs/05-tasks.md) for the full task catalog.\n\n| Domain | Understanding | Generation | Editing | Reasoning |\n| --- | :---: | :---: | :---: | :---: |\n| Molecules | ✅ | ✅ | ✅ | ✅ |\n| Polymers | ✅ | ✅ | ✅ | — |\n| Markush | ✅ | — | — | — |\n\n---\n\n## Repository layout\n\n```\nmolecode/ # the library (pip-installable)\n├── molecule/ # small-molecule <-> Mermaid (rdkit_to_mermaid, mermaid_to_rdkit)\n├── polymer/ # polymer <-> Mermaid (polymer_to_mermaid, mermaid_to_psmiles)\n├── markush/ # Markush <-> Mermaid + graph isomorphism + abbreviation_map\n├── prompts/ # LLM system prompts (molecule + markush grammars)\n└── llm.py # optional OpenAI-compatible client (you supply key + base_url)\nexamples/ # 7 runnable demos (round-trips + 4 task families)\ndocs/ # overview, syntax, polymers, markush, tasks, why-it-works\nAGENTS.md # entrypoint for coding agents\n.claude/skills/molecode/ # Agent Skill: SKILL.md + CLI + references (Claude Code / Codex)\n```\n\n---\n\n## Results at a glance\n\n| Generalization & reasoning | Goal-directed design | Scaling | Long molecules | General language |\n| :---: | :---: | :---: | :---: | :---: |\n| ![](docs/assets/results_1_main.png) | ![](docs/assets/results_2_chemistry.png) | ![](docs/assets/results_3_scaling.png) | ![](docs/assets/results_4_long_molecules.png) | ![](docs/assets/results_5_extension.png) |\n\n---\n\n## About AtomFlow\n\nMoleCode is built and maintained by **[AtomFlow](https://atomflow-ai.com/)**.\n\nAtomFlow builds **LLM-native AI for chemistry** — letting language models operate\ndirectly on molecular structure rather than on opaque strings. Our work centers on\nmolecule-grounded applications, including:\n\n- **Molecular chat & interaction** — converse with a molecule; select atoms, bonds,\n or fragments and edit them in natural language.\n- **Structure-aware editing** — auditable, graph-level molecular edits.\n- **Retrosynthesis** — LLM-native synthesis planning over explicit structures.\n- **Literature reading & structure parsing** — extracting structures from papers\n and patents, including optical chemical structure recognition (OCSR).\n\nMoleCode is the open representation layer underneath these products — making\nmolecular structure explicit, editable, and auditable for LLMs.\n\n🌐 Learn more at **[atomflow-ai.com](https://atomflow-ai.com/)**.\n\n## 📚 Citation\n\nIf you use MoleCode in your research, please cite the MoleCode technical report:\n\n```bibtex\n@article{yan2026molecode,\n title={MoleCode unlocks structural intelligence in large language models},\n author={Yan, Zhiyuan and Liu, Chen and Zhao, Boxuan and Lin, Kaiqing and Zhao, Jixiang and Wang, Yimi and Lv, Liuzhenghao and Li, Hao and Zhang, Shanzhuo and Yuan, Li and others},\n journal={arXiv preprint arXiv:2605.16480},\n year={2026}\n}\n```\n\n## License\n\n[MIT](LICENSE) © 2026 AtomFlow-AI\n"}, "b08803da710791e620ea70898835a59de5c4fa02": {"t": 1785771608.736666, "n": 14395, "h": "72aa1f72300957a7", "c": "<div align=\"center\">\n\n# 🧬 MoleCode\n\n### An LLM-native, graph-explicit molecular language\n\nOfficial repository for [**MoleCode unlocks structural intelligence in large language models**](https://arxiv.org/pdf/2605.16480).\n\n*Molecode presents molecules as code and enables LLMs to operate and reason on chemistry directly.*\n<br>*Instead of making language models reconstruct molecular structure from cryptic strings,*\n<br>*MoleCode lets them read, write, and edit directly on the structures.*\n\n[![arXiv](https://img.shields.io/badge/arXiv-MoleCode-firebrick)](https://arxiv.org/abs/2605.16480)\n[![PDF](https://img.shields.io/badge/PDF-DADBDD)](https://arxiv.org/pdf/2605.16480)\n[![Website](https://img.shields.io/badge/AtomFlow-atomflow--ai.com-0b7285.svg)](https://atomflow-ai.com/)\n[![GitHub Stars](https://img.shields.io/github/stars/AtomFlow-AI/MoleCode.svg?style=social\\&label=Stars)](https://github.com/AtomFlow-AI/MoleCode)\n<br>[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)\n[![Powered by RDKit](https://img.shields.io/badge/powered%20by-RDKit-green.svg)](https://www.rdkit.org/)\n<br>[![Works with Claude Code](https://img.shields.io/badge/Works%20with-Claude%20Code-d97757.svg)](.claude/skills/molecode/)\n[![Works with Codex](https://img.shields.io/badge/Works%20with-Codex-412991.svg)](AGENTS.md)\n[![Agent Skill](https://img.shields.io/badge/Agent-Skill-blue.svg)](.claude/skills/molecode/SKILL.md)\n\n**English** | [中文](README.zh-CN.md)\n\n<br>\n<br>\n\n<img src=\"docs/assets/overview.png\" alt=\"MoleCode overview\" width=\"100%\">\n\n</div>\n\n---\n\n## Try our latest products on the official website!\nPlease visit the [AtomFlow website](https://atomflow-ai.com/).\n\n<p align=\"center\">\n <img src=\"docs/assets/demo_atomchat.png\" width=\"33%\" />\n <img src=\"docs/assets/demo_retro.png\" width=\"33%\" />\n <img src=\"docs/assets/demo_paper_read.png\" width=\"33%\" />\n</p>\n\n<br>\n \n## What is MoleCode?\n\nA molecule **is** a graph: atoms are nodes, bonds are edges, and chemistry emerges from the topology. Yet large language models are almost always fed molecules as *linear strings* like SMILES, where the graph is **implicit** — connectivity is positional, branches are syntactic, and rings hide inside index digits. Before an LLM can do any chemistry, it must first *reconstruct the graph from the syntax*, spending reasoning budget on structural bookkeeping.\n\n**MoleCode makes the structure the language.** Every atom and bond is written as a typed declaration with a persistent identifier, serialized as a [Mermaid](https://mermaid.js.org/) graph. Topology becomes directly readable, editable, and auditable inside the context window — and the format is **deterministically and losslessly inter-convertible with SMILES / MOL via RDKit** (no learned model, no information loss).\n\n```mermaid\ngraph TB\n subgraph chlorophenol[\"para-chlorophenol\"]\n chlorophenol_C_1[C]\n chlorophenol_O_1[OH]\n chlorophenol_C_2[CH]\n chlorophenol_C_3[CH]\n chlorophenol_C_4[C]\n chlorophenol_Cl_1[Cl]\n chlorophenol_C_5[CH]\n chlorophenol_C_6[CH]\n chlorophenol_C_1 === chlorophenol_C_2\n chlorophenol_C_2 --- chlorophenol_C_3\n chlorophenol_C_3 === chlorophenol_C_4\n chlorophenol_C_4 --- chlorophenol_C_5\n chlorophenol_C_5 === chlorophenol_C_6\n chlorophenol_C_6 --- chlorophenol_C_1\n chlorophenol_C_1 --- chlorophenol_O_1\n chlorophenol_C_4 --- chlorophenol_Cl_1\n end\n```\n\n> The same `Subgraph → Node → Edge` grammar covers **small molecules, polymers, and Markush structures** — and extends to reaction mechanisms and multimodal document parsing.\n\n---\n\n## Why it matters\n\n| | SMILES | **MoleCode** |\n| --- | --- | --- |\n| Topology | implicit, positional | **explicit, named nodes & edges** |\n| Atom identity | none | **persistent IDs** (stable across prompt → reasoning → output) |\n| Editing | whole-string rewrite | **local graph op** (add a methyl = 1 node + 1 edge) |\n| Validation | fragile string parsing | **deterministic RDKit round-trip** |\n| Reasoning behavior | memorizes syntax | **generalizes over structure** |\n\nEmpirically (see the [MoleCode paper](#-citation) and [docs/06-why-it-works.md](docs/06-why-it-works.md)):\n\n- **Generalization, not memorization.** SMILES accuracy collapses from ~42% on familiar molecules to ~20% on novel ones; MoleCode holds **~76–80%** across all familiarity tiers.\n- **Cheaper reasoning.** MoleCode has longer *input* but its chain-of-thought grows **sub-linearly** with molecule size (~C^0.52) versus SMILES' super-linear ~C^1.65 — about a **5× lower total token cost** per query.\n- **Scales to big, repetitive objects.** Full-chain SMILES accuracy falls toward **0%** as polymer chains grow; MoleCode stays flat.\n- **Markush understanding** jumps from **38.1% → 84.0%**.\n\n---\n\n## Install\n\n```bash\npip install molecode # from PyPI — pulls in rdkit + networkx\n```\n\nOr from source (for the examples, the Agent Skill, and development):\n\n```bash\ngit clone https://github.com/AtomFlow-AI/MoleCode.git\ncd MoleCode\npip install -e .\n```\n\n> `pip install molecode` gives you the **library** (`molecode.molecule`,\n> `molecode.polymer`, `molecode.markush`, `molecode.prompts`, `molecode.llm`).\n> The runnable [`examples/`](examples) and the [Agent Skill](.claude/skills/molecode/)\n> live in the repository. Full API reference → [docs/api.md](docs/api.md).\n\n## Quick start\n\n```python\nfrom rdkit import Chem\nfrom molecode import mol_to_mermaid, mermaid_to_mol, mol_to_smiles\n\n# SMILES -> MoleCode graph\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nprint(graph)\n\n# MoleCode graph -> SMILES (lossless round-trip)\nassert mol_to_smiles(mermaid_to_mol(graph)) == Chem.CanonSmiles(\"CC(=O)Oc1ccccc1C(=O)O\")\n```\n\n---\n\n## Works with your coding agent (Claude Code · Codex)\n\nMoleCode ships as a ready-to-use **[Agent Skill](https://docs.claude.com/en/docs/claude-code/skills)**,\nso coding agents can clone this repo and immediately reason over and edit\nmolecules at the explicit-graph level — no extra setup, no MCP server required.\n\n| Agent | How it picks MoleCode up |\n| --- | --- |\n| **Claude Code** | Auto-discovers the skill at [`.claude/skills/molecode/`](.claude/skills/molecode/). Just ask it to understand or edit a molecule. |\n| **Codex** (and other agents) | Reads [`AGENTS.md`](AGENTS.md) at the repo root and uses the bundled CLI; interface metadata in [`agents/openai.yaml`](.claude/skills/molecode/agents/openai.yaml). |\n\nInstead of asking the model to hand-write SMILES — error-prone for anything\nnon-trivial — the skill has it **convert → inspect the named atoms/bonds → edit\nthe graph → validate**, all through one stable CLI:\n\n```bash\npython .claude/skills/molecode/scripts/molecode_convert.py doctor\npython .claude/skills/molecode/scripts/molecode_convert.py smiles-to-molecode \"CCO\" --name Ethanol\npython .claude/skills/molecode/scripts/molecode_convert.py validate --input edited.mmd # formula, counts, round-trip\npython .claude/skills/molecode/scripts/molecode_convert.py molecode-to-smiles --input edited.mmd\n```\n\nThe skill bundles the six conversion forms (SMILES / PSMILES / Markush ↔\nMoleCode) plus `validate`, `compare` (Markush-aware isomorphism) and `doctor`, a\nsyntax reference for hand-editing graphs, and a file-based edit workflow built\nfor large molecules. See [`.claude/skills/molecode/SKILL.md`](.claude/skills/molecode/SKILL.md).\n\n## Three domains, one grammar\n\n### 🧪 Small molecules — [`molecode.molecule`](molecode/molecule)\n\nAtoms are `prefix_Element_Number[Label]` nodes; bonds are `---` (single), `===` (double), `-.-` (triple), with `===|E|`/`===|Z|` and `_R`/`_S` for stereochemistry. → [syntax reference](docs/02-syntax.md)\n\n### 🔗 Polymers — [`molecode.polymer`](molecode/polymer)\n\nThe repeat unit stays **explicit** as a subgraph carrying a symbolic `×n` count, with `TL`/`TR` terminus markers — so the graph does not blow up with chain length. → [polymer docs](docs/03-polymers.md)\n\n```python\nfrom molecode.polymer import polymer_to_mermaid, mermaid_to_psmiles\n\ngraph = polymer_to_mermaid(\"*NCCCCCC(=O)*\", n=8, name=\"Nylon-6\") # PSMILES -> graph\nmermaid_to_psmiles(graph) # -> '*NCCCCCC(=O)*'\n```\n\n### 🧩 Markush structures — [`molecode.markush`](molecode/markush)\n\nVariable R-groups and named substituents become **abbreviation nodes** in curly braces — `{R1}`, `{Boc}`, `{Ar}` — something plain SMILES cannot express. A built-in graph-isomorphism comparator scores predictions up to abbreviation expansion. → [Markush docs](docs/04-markush.md)\n\n```mermaid\ngraph TB\n subgraph Mol[\"molecule name\"]\n Mol_C_1[C]\n Mol_O_1[OH]\n Mol_X_1{Boc}\n Mol_X_2{R1}\n Mol_C_1 --- Mol_O_1\n Mol_C_1 --- Mol_X_1\n end\n```\n\n---\n\n## Run the tasks: understand · generate · edit · reason\n\nMoleCode is a **drop-in representation for any LLM** — feed the grammar as a system prompt, hand the model a graph, and validate its output deterministically. The [`examples/`](examples) folder has runnable scripts for all four task families (they run **offline by default**, printing the exact prompt; set `MOLECODE_API_KEY` to call a model):\n\n```bash\npython examples/01_molecule_roundtrip.py # SMILES <-> graph (lossless)\npython examples/02_polymer_roundtrip.py # polymers with ×n\npython examples/03_markush_roundtrip.py # abbreviation nodes & isomorphism\npython examples/04_understanding.py # count atoms / formula / rings ...\npython examples/05_generation.py # de novo design under constraints\npython examples/06_editing.py # local graph edits (add/del/substitute)\npython examples/07_reasoning.py # reaction-product prediction\npython examples/08_image_to_molecode.py # OCSR: molecule image -> MoleCode (vision model)\n```\n\nThe reusable ingredients:\n\n```python\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT # give this to the LLM as the system prompt\nfrom molecode.molecule import mol_to_mermaid # your molecule -> what the model reads\nfrom molecode.molecule import mermaid_to_mol # model output -> validated RDKit Mol\n```\n\n### Calling an LLM\n\nMoleCode is just a representation, so you can use **any** LLM SDK — the prompts\nare plain strings. For convenience the package also ships a tiny,\ndependency-free, **OpenAI-compatible** client (`molecode.llm.LLMClient`, built on\nstdlib `urllib`). You supply the API key and base URL — nothing is hard-coded, so\nit works with OpenAI, DeepSeek, Azure, Together, vLLM, Ollama, …\n\n```python\nfrom molecode import LLMClient\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT\nfrom molecode.molecule import mol_to_mermaid, mermaid_to_mol\nfrom rdkit import Chem\n\nclient = LLMClient(api_key=\"sk-...\", base_url=\"https://api.openai.com/v1\", model=\"\")\n# (or set MOLECODE_API_KEY / MOLECODE_BASE_URL / MOLECODE_MODEL and call LLMClient())\n\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nreply = client.chat(f\"How many carbons are in this molecule?\\n```mermaid\\n{graph}\\n```\",\n system=MOLECULE_SYSTEM_PROMPT)\nprint(reply)\n```\n\nPrefer the official `openai` SDK? Pass the same prompt strings straight to\n`openai.OpenAI().chat.completions.create(...)` — you don't need `LLMClient` at all.\n\nSee [docs/05-tasks.md](docs/05-tasks.md) for the full task catalog.\n\n| Domain | Understanding | Generation | Editing | Reasoning |\n| --- | :---: | :---: | :---: | :---: |\n| Molecules | ✅ | ✅ | ✅ | ✅ |\n| Polymers | ✅ | ✅ | ✅ | — |\n| Markush | ✅ | — | — | — |\n\n---\n\n## Repository layout\n\n```\nmolecode/ # the library (pip-installable)\n├── molecule/ # small-molecule <-> Mermaid (rdkit_to_mermaid, mermaid_to_rdkit)\n├── polymer/ # polymer <-> Mermaid (polymer_to_mermaid, mermaid_to_psmiles)\n├── markush/ # Markush <-> Mermaid + graph isomorphism + abbreviation_map\n├── prompts/ # LLM system prompts (molecule + markush grammars)\n└── llm.py # optional OpenAI-compatible client (you supply key + base_url)\nexamples/ # 7 runnable demos (round-trips + 4 task families)\ndocs/ # overview, syntax, polymers, markush, tasks, why-it-works\nAGENTS.md # entrypoint for coding agents\n.claude/skills/molecode/ # Agent Skill: SKILL.md + CLI + references (Claude Code / Codex)\n```\n\n---\n\n## Results at a glance\n\n| Generalization & reasoning | Goal-directed design | Scaling | Long molecules | General language |\n| :---: | :---: | :---: | :---: | :---: |\n| ![](docs/assets/results_1_main.png) | ![](docs/assets/results_2_chemistry.png) | ![](docs/assets/results_3_scaling.png) | ![](docs/assets/results_4_long_molecules.png) | ![](docs/assets/results_5_extension.png) |\n\n---\n\n## About AtomFlow\n\nMoleCode is built and maintained by **[AtomFlow](https://atomflow-ai.com/)**.\n\nAtomFlow builds **LLM-native AI for chemistry** — letting language models operate\ndirectly on molecular structure rather than on opaque strings. Our work centers on\nmolecule-grounded applications, including:\n\n- **Molecular chat & interaction** — converse with a molecule; select atoms, bonds,\n or fragments and edit them in natural language.\n- **Structure-aware editing** — auditable, graph-level molecular edits.\n- **Retrosynthesis** — LLM-native synthesis planning over explicit structures.\n- **Literature reading & structure parsing** — extracting structures from papers\n and patents, including optical chemical structure recognition (OCSR).\n\nMoleCode is the open representation layer underneath these products — making\nmolecular structure explicit, editable, and auditable for LLMs.\n\n🌐 Learn more at **[atomflow-ai.com](https://atomflow-ai.com/)**.\n\n## 📚 Citation\n\nIf you use MoleCode in your research, please cite the MoleCode technical report:\n\n```bibtex\n@article{yan2026molecode,\n title={MoleCode unlocks structural intelligence in large language models},\n author={Yan, Zhiyuan and Liu, Chen and Zhao, Boxuan and Lin, Kaiqing and Zhao, Jixiang and Wang, Yimi and Lv, Liuzhenghao and Li, Hao and Zhang, Shanzhuo and Yuan, Li and others},\n journal={arXiv preprint arXiv:2605.16480},\n year={2026}\n}\n```\n\n## License\n\n[MIT](LICENSE) © 2026 AtomFlow-AI\n"}, "27a26519985dc0c3f379f055825361392bf7b881": {"t": 1785771610.0778072, "n": 13964, "h": "f1a8462ed8e3485c", "c": "<div align=\"center\">\n\n# 🧬 MoleCode\n\n### An LLM-native, graph-explicit molecular language\n\nOfficial repository for [**MoleCode unlocks structural intelligence in large language models**](https://arxiv.org/pdf/2605.16480).\n\n*Molecode presents molecules as code and enables LLMs to operate and reason on chemistry directly.*\n<br>*Instead of making language models reconstruct molecular structure from cryptic strings,*\n<br>*MoleCode lets them read, write, and edit directly on the structures.*\n\n[![arXiv](https://img.shields.io/badge/arXiv-MoleCode-firebrick)](https://arxiv.org/abs/2605.16480)\n[![PDF](https://img.shields.io/badge/PDF-DADBDD)](https://arxiv.org/pdf/2605.16480)\n[![Website](https://img.shields.io/badge/AtomFlow-atomflow--ai.com-0b7285.svg)](https://atomflow-ai.com/)\n[![GitHub Stars](https://img.shields.io/github/stars/AtomFlow-AI/MoleCode.svg?style=social\\&label=Stars)](https://github.com/AtomFlow-AI/MoleCode)\n<br>[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)\n[![Powered by RDKit](https://img.shields.io/badge/powered%20by-RDKit-green.svg)](https://www.rdkit.org/)\n<br>[![Works with Claude Code](https://img.shields.io/badge/Works%20with-Claude%20Code-d97757.svg)](.claude/skills/molecode/)\n[![Works with Codex](https://img.shields.io/badge/Works%20with-Codex-412991.svg)](AGENTS.md)\n[![Agent Skill](https://img.shields.io/badge/Agent-Skill-blue.svg)](.claude/skills/molecode/SKILL.md)\n\n**English** | [中文](README.zh-CN.md)\n\n<br>\n<br>\n\n<img src=\"docs/assets/overview.png\" alt=\"MoleCode overview\" width=\"100%\">\n\n</div>\n\n---\n\n## Try our latest products on the official website!\nPlease visit the [AtomFlow website](https://atomflow-ai.com/).\n\n<p align=\"center\">\n <img src=\"docs/assets/demo_atomchat.png\" width=\"33%\" />\n <img src=\"docs/assets/demo_retro.png\" width=\"33%\" />\n <img src=\"docs/assets/demo_paper_read.png\" width=\"33%\" />\n</p>\n\n<br>\n \n## What is MoleCode?\n\nA molecule **is** a graph: atoms are nodes, bonds are edges, and chemistry emerges from the topology. Yet large language models are almost always fed molecules as *linear strings* like SMILES, where the graph is **implicit** — connectivity is positional, branches are syntactic, and rings hide inside index digits. Before an LLM can do any chemistry, it must first *reconstruct the graph from the syntax*, spending reasoning budget on structural bookkeeping.\n\n**MoleCode makes the structure the language.** Every atom and bond is written as a typed declaration with a persistent identifier, serialized as a [Mermaid](https://mermaid.js.org/) graph. Topology becomes directly readable, editable, and auditable inside the context window — and the format is **deterministically and losslessly inter-convertible with SMILES / MOL via RDKit** (no learned model, no information loss).\n\n```mermaid\ngraph TB\n subgraph chlorophenol[\"para-chlorophenol\"]\n chlorophenol_C_1[C]\n chlorophenol_O_1[OH]\n chlorophenol_C_2[CH]\n chlorophenol_C_3[CH]\n chlorophenol_C_4[C]\n chlorophenol_Cl_1[Cl]\n chlorophenol_C_5[CH]\n chlorophenol_C_6[CH]\n chlorophenol_C_1 === chlorophenol_C_2\n chlorophenol_C_2 --- chlorophenol_C_3\n chlorophenol_C_3 === chlorophenol_C_4\n chlorophenol_C_4 --- chlorophenol_C_5\n chlorophenol_C_5 === chlorophenol_C_6\n chlorophenol_C_6 --- chlorophenol_C_1\n chlorophenol_C_1 --- chlorophenol_O_1\n chlorophenol_C_4 --- chlorophenol_Cl_1\n end\n```\n\n> The same `Subgraph → Node → Edge` grammar covers **small molecules, polymers, and Markush structures** — and extends to reaction mechanisms and multimodal document parsing.\n\n---\n\n## Why it matters\n\n| | SMILES | **MoleCode** |\n| --- | --- | --- |\n| Topology | implicit, positional | **explicit, named nodes & edges** |\n| Atom identity | none | **persistent IDs** (stable across prompt → reasoning → output) |\n| Editing | whole-string rewrite | **local graph op** (add a methyl = 1 node + 1 edge) |\n| Validation | fragile string parsing | **deterministic RDKit round-trip** |\n| Reasoning behavior | memorizes syntax | **generalizes over structure** |\n\nEmpirically (see the [MoleCode paper](#-citation) and [docs/06-why-it-works.md](docs/06-why-it-works.md)):\n\n- **Generalization, not memorization.** SMILES accuracy collapses from ~42% on familiar molecules to ~20% on novel ones; MoleCode holds **~76–80%** across all familiarity tiers.\n- **Cheaper reasoning.** MoleCode has longer *input* but its chain-of-thought grows **sub-linearly** with molecule size (~C^0.52) versus SMILES' super-linear ~C^1.65 — about a **5× lower total token cost** per query.\n- **Scales to big, repetitive objects.** Full-chain SMILES accuracy falls toward **0%** as polymer chains grow; MoleCode stays flat.\n- **Markush understanding** jumps from **38.1% → 84.0%**.\n\n---\n\n## Install\n\n```bash\ngit clone https://github.com/AtomFlow-AI/MoleCode.git\ncd MoleCode\npip install -e . # installs rdkit + networkx\n```\n\n## Quick start\n\n```python\nfrom rdkit import Chem\nfrom molecode import mol_to_mermaid, mermaid_to_mol, mol_to_smiles\n\n# SMILES -> MoleCode graph\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nprint(graph)\n\n# MoleCode graph -> SMILES (lossless round-trip)\nassert mol_to_smiles(mermaid_to_mol(graph)) == Chem.CanonSmiles(\"CC(=O)Oc1ccccc1C(=O)O\")\n```\n\n---\n\n## Works with your coding agent (Claude Code · Codex)\n\nMoleCode ships as a ready-to-use **[Agent Skill](https://docs.claude.com/en/docs/claude-code/skills)**,\nso coding agents can clone this repo and immediately reason over and edit\nmolecules at the explicit-graph level — no extra setup, no MCP server required.\n\n| Agent | How it picks MoleCode up |\n| --- | --- |\n| **Claude Code** | Auto-discovers the skill at [`.claude/skills/molecode/`](.claude/skills/molecode/). Just ask it to understand or edit a molecule. |\n| **Codex** (and other agents) | Reads [`AGENTS.md`](AGENTS.md) at the repo root and uses the bundled CLI; interface metadata in [`agents/openai.yaml`](.claude/skills/molecode/agents/openai.yaml). |\n\nInstead of asking the model to hand-write SMILES — error-prone for anything\nnon-trivial — the skill has it **convert → inspect the named atoms/bonds → edit\nthe graph → validate**, all through one stable CLI:\n\n```bash\npython .claude/skills/molecode/scripts/molecode_convert.py doctor\npython .claude/skills/molecode/scripts/molecode_convert.py smiles-to-molecode \"CCO\" --name Ethanol\npython .claude/skills/molecode/scripts/molecode_convert.py validate --input edited.mmd # formula, counts, round-trip\npython .claude/skills/molecode/scripts/molecode_convert.py molecode-to-smiles --input edited.mmd\n```\n\nThe skill bundles the six conversion forms (SMILES / PSMILES / Markush ↔\nMoleCode) plus `validate`, `compare` (Markush-aware isomorphism) and `doctor`, a\nsyntax reference for hand-editing graphs, and a file-based edit workflow built\nfor large molecules. See [`.claude/skills/molecode/SKILL.md`](.claude/skills/molecode/SKILL.md).\n\n## Three domains, one grammar\n\n### 🧪 Small molecules — [`molecode.molecule`](molecode/molecule)\n\nAtoms are `prefix_Element_Number[Label]` nodes; bonds are `---` (single), `===` (double), `-.-` (triple), with `===|E|`/`===|Z|` and `_R`/`_S` for stereochemistry. → [syntax reference](docs/02-syntax.md)\n\n### 🔗 Polymers — [`molecode.polymer`](molecode/polymer)\n\nThe repeat unit stays **explicit** as a subgraph carrying a symbolic `×n` count, with `TL`/`TR` terminus markers — so the graph does not blow up with chain length. → [polymer docs](docs/03-polymers.md)\n\n```python\nfrom molecode.polymer import polymer_to_mermaid, mermaid_to_psmiles\n\ngraph = polymer_to_mermaid(\"*NCCCCCC(=O)*\", n=8, name=\"Nylon-6\") # PSMILES -> graph\nmermaid_to_psmiles(graph) # -> '*NCCCCCC(=O)*'\n```\n\n### 🧩 Markush structures — [`molecode.markush`](molecode/markush)\n\nVariable R-groups and named substituents become **abbreviation nodes** in curly braces — `{R1}`, `{Boc}`, `{Ar}` — something plain SMILES cannot express. A built-in graph-isomorphism comparator scores predictions up to abbreviation expansion. → [Markush docs](docs/04-markush.md)\n\n```mermaid\ngraph TB\n subgraph Mol[\"molecule name\"]\n Mol_C_1[C]\n Mol_O_1[OH]\n Mol_X_1{Boc}\n Mol_X_2{R1}\n Mol_C_1 --- Mol_O_1\n Mol_C_1 --- Mol_X_1\n end\n```\n\n---\n\n## Run the tasks: understand · generate · edit · reason\n\nMoleCode is a **drop-in representation for any LLM** — feed the grammar as a system prompt, hand the model a graph, and validate its output deterministically. The [`examples/`](examples) folder has runnable scripts for all four task families (they run **offline by default**, printing the exact prompt; set `MOLECODE_API_KEY` to call a model):\n\n```bash\npython examples/01_molecule_roundtrip.py # SMILES <-> graph (lossless)\npython examples/02_polymer_roundtrip.py # polymers with ×n\npython examples/03_markush_roundtrip.py # abbreviation nodes & isomorphism\npython examples/04_understanding.py # count atoms / formula / rings ...\npython examples/05_generation.py # de novo design under constraints\npython examples/06_editing.py # local graph edits (add/del/substitute)\npython examples/07_reasoning.py # reaction-product prediction\npython examples/08_image_to_molecode.py # OCSR: molecule image -> MoleCode (vision model)\n```\n\nThe reusable ingredients:\n\n```python\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT # give this to the LLM as the system prompt\nfrom molecode.molecule import mol_to_mermaid # your molecule -> what the model reads\nfrom molecode.molecule import mermaid_to_mol # model output -> validated RDKit Mol\n```\n\n### Calling an LLM\n\nMoleCode is just a representation, so you can use **any** LLM SDK — the prompts\nare plain strings. For convenience the package also ships a tiny,\ndependency-free, **OpenAI-compatible** client (`molecode.llm.LLMClient`, built on\nstdlib `urllib`). You supply the API key and base URL — nothing is hard-coded, so\nit works with OpenAI, DeepSeek, Azure, Together, vLLM, Ollama, …\n\n```python\nfrom molecode import LLMClient\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT\nfrom molecode.molecule import mol_to_mermaid, mermaid_to_mol\nfrom rdkit import Chem\n\nclient = LLMClient(api_key=\"sk-...\", base_url=\"https://api.openai.com/v1\", model=\"\")\n# (or set MOLECODE_API_KEY / MOLECODE_BASE_URL / MOLECODE_MODEL and call LLMClient())\n\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nreply = client.chat(f\"How many carbons are in this molecule?\\n```mermaid\\n{graph}\\n```\",\n system=MOLECULE_SYSTEM_PROMPT)\nprint(reply)\n```\n\nPrefer the official `openai` SDK? Pass the same prompt strings straight to\n`openai.OpenAI().chat.completions.create(...)` — you don't need `LLMClient` at all.\n\nSee [docs/05-tasks.md](docs/05-tasks.md) for the full task catalog.\n\n| Domain | Understanding | Generation | Editing | Reasoning |\n| --- | :---: | :---: | :---: | :---: |\n| Molecules | ✅ | ✅ | ✅ | ✅ |\n| Polymers | ✅ | ✅ | ✅ | — |\n| Markush | ✅ | — | — | — |\n\n---\n\n## Repository layout\n\n```\nmolecode/ # the library (pip-installable)\n├── molecule/ # small-molecule <-> Mermaid (rdkit_to_mermaid, mermaid_to_rdkit)\n├── polymer/ # polymer <-> Mermaid (polymer_to_mermaid, mermaid_to_psmiles)\n├── markush/ # Markush <-> Mermaid + graph isomorphism + abbreviation_map\n├── prompts/ # LLM system prompts (molecule + markush grammars)\n└── llm.py # optional OpenAI-compatible client (you supply key + base_url)\nexamples/ # 7 runnable demos (round-trips + 4 task families)\ndocs/ # overview, syntax, polymers, markush, tasks, why-it-works\nAGENTS.md # entrypoint for coding agents\n.claude/skills/molecode/ # Agent Skill: SKILL.md + CLI + references (Claude Code / Codex)\n```\n\n---\n\n## Results at a glance\n\n| Generalization & reasoning | Goal-directed design | Scaling | Long molecules | General language |\n| :---: | :---: | :---: | :---: | :---: |\n| ![](docs/assets/results_1_main.png) | ![](docs/assets/results_2_chemistry.png) | ![](docs/assets/results_3_scaling.png) | ![](docs/assets/results_4_long_molecules.png) | ![](docs/assets/results_5_extension.png) |\n\n---\n\n## About AtomFlow\n\nMoleCode is built and maintained by **[AtomFlow](https://atomflow-ai.com/)**.\n\nAtomFlow builds **LLM-native AI for chemistry** — letting language models operate\ndirectly on molecular structure rather than on opaque strings. Our work centers on\nmolecule-grounded applications, including:\n\n- **Molecular chat & interaction** — converse with a molecule; select atoms, bonds,\n or fragments and edit them in natural language.\n- **Structure-aware editing** — auditable, graph-level molecular edits.\n- **Retrosynthesis** — LLM-native synthesis planning over explicit structures.\n- **Literature reading & structure parsing** — extracting structures from papers\n and patents, including optical chemical structure recognition (OCSR).\n\nMoleCode is the open representation layer underneath these products — making\nmolecular structure explicit, editable, and auditable for LLMs.\n\n🌐 Learn more at **[atomflow-ai.com](https://atomflow-ai.com/)**.\n\n## 📚 Citation\n\nIf you use MoleCode in your research, please cite the MoleCode technical report:\n\n```bibtex\n@article{yan2026molecode,\n title={MoleCode unlocks structural intelligence in large language models},\n author={Yan, Zhiyuan and Liu, Chen and Zhao, Boxuan and Lin, Kaiqing and Zhao, Jixiang and Wang, Yimi and Lv, Liuzhenghao and Li, Hao and Zhang, Shanzhuo and Yuan, Li and others},\n journal={arXiv preprint arXiv:2605.16480},\n year={2026}\n}\n```\n\n## License\n\n[MIT](LICENSE) © 2026 AtomFlow-AI\n"}, "9313c566162a2e8edff900ba37e8a6150f09cfc9": {"t": 1785771611.7731187, "n": 13640, "h": "08ace5e4848a8c47", "c": "<div align=\"center\">\n\n# 🧬 MoleCode\n\n### An LLM-native, graph-explicit molecular language\n\nOfficial repository for [**MoleCode unlocks structural intelligence in large language models**](https://arxiv.org/pdf/2605.16480).\n\n*Molecode presents molecules as code and enables LLMs to operate and reason on chemistry directly.*\n<br>*Instead of making language models reconstruct molecular structure from cryptic strings,*\n<br>*MoleCode lets them read, write, and edit directly on the structures.*\n\n[![arXiv](https://img.shields.io/badge/arXiv-MoleCode-firebrick)](https://arxiv.org/abs/2605.16480)\n[![PDF](https://img.shields.io/badge/PDF-DADBDD)](https://arxiv.org/pdf/2605.16480)\n[![Website](https://img.shields.io/badge/AtomFlow-atomflow--ai.com-0b7285.svg)](https://atomflow-ai.com/)\n[![GitHub Stars](https://img.shields.io/github/stars/AtomFlow-AI/MoleCode.svg?style=social\\&label=Stars)](https://github.com/AtomFlow-AI/MoleCode)\n<br>[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)\n[![Powered by RDKit](https://img.shields.io/badge/powered%20by-RDKit-green.svg)](https://www.rdkit.org/)\n<br>[![Works with Claude Code](https://img.shields.io/badge/Works%20with-Claude%20Code-d97757.svg)](.claude/skills/molecode/)\n[![Works with Codex](https://img.shields.io/badge/Works%20with-Codex-412991.svg)](AGENTS.md)\n[![Agent Skill](https://img.shields.io/badge/Agent-Skill-blue.svg)](.claude/skills/molecode/SKILL.md)\n\n**English** | [中文](README.zh-CN.md)\n\n<br>\n<br>\n\n<img src=\"docs/assets/overview.png\" alt=\"MoleCode overview\" width=\"100%\">\n\n</div>\n\n---\n\n## What is MoleCode?\n\nA molecule **is** a graph: atoms are nodes, bonds are edges, and chemistry emerges from the topology. Yet large language models are almost always fed molecules as *linear strings* like SMILES, where the graph is **implicit** — connectivity is positional, branches are syntactic, and rings hide inside index digits. Before an LLM can do any chemistry, it must first *reconstruct the graph from the syntax*, spending reasoning budget on structural bookkeeping.\n\n**MoleCode makes the structure the language.** Every atom and bond is written as a typed declaration with a persistent identifier, serialized as a [Mermaid](https://mermaid.js.org/) graph. Topology becomes directly readable, editable, and auditable inside the context window — and the format is **deterministically and losslessly inter-convertible with SMILES / MOL via RDKit** (no learned model, no information loss).\n\n```mermaid\ngraph TB\n subgraph chlorophenol[\"para-chlorophenol\"]\n chlorophenol_C_1[C]\n chlorophenol_O_1[OH]\n chlorophenol_C_2[CH]\n chlorophenol_C_3[CH]\n chlorophenol_C_4[C]\n chlorophenol_Cl_1[Cl]\n chlorophenol_C_5[CH]\n chlorophenol_C_6[CH]\n chlorophenol_C_1 === chlorophenol_C_2\n chlorophenol_C_2 --- chlorophenol_C_3\n chlorophenol_C_3 === chlorophenol_C_4\n chlorophenol_C_4 --- chlorophenol_C_5\n chlorophenol_C_5 === chlorophenol_C_6\n chlorophenol_C_6 --- chlorophenol_C_1\n chlorophenol_C_1 --- chlorophenol_O_1\n chlorophenol_C_4 --- chlorophenol_Cl_1\n end\n```\n\n> The same `Subgraph → Node → Edge` grammar covers **small molecules, polymers, and Markush structures** — and extends to reaction mechanisms and multimodal document parsing.\n\n---\n\n## Why it matters\n\n| | SMILES | **MoleCode** |\n| --- | --- | --- |\n| Topology | implicit, positional | **explicit, named nodes & edges** |\n| Atom identity | none | **persistent IDs** (stable across prompt → reasoning → output) |\n| Editing | whole-string rewrite | **local graph op** (add a methyl = 1 node + 1 edge) |\n| Validation | fragile string parsing | **deterministic RDKit round-trip** |\n| Reasoning behavior | memorizes syntax | **generalizes over structure** |\n\nEmpirically (see the [MoleCode paper](#-citation) and [docs/06-why-it-works.md](docs/06-why-it-works.md)):\n\n- **Generalization, not memorization.** SMILES accuracy collapses from ~42% on familiar molecules to ~20% on novel ones; MoleCode holds **~76–80%** across all familiarity tiers.\n- **Cheaper reasoning.** MoleCode has longer *input* but its chain-of-thought grows **sub-linearly** with molecule size (~C^0.52) versus SMILES' super-linear ~C^1.65 — about a **5× lower total token cost** per query.\n- **Scales to big, repetitive objects.** Full-chain SMILES accuracy falls toward **0%** as polymer chains grow; MoleCode stays flat.\n- **Markush understanding** jumps from **38.1% → 84.0%**.\n\n---\n\n## Install\n\n```bash\ngit clone https://github.com/AtomFlow-AI/MoleCode.git\ncd MoleCode\npip install -e . # installs rdkit + networkx\n```\n\n## Quick start\n\n```python\nfrom rdkit import Chem\nfrom molecode import mol_to_mermaid, mermaid_to_mol, mol_to_smiles\n\n# SMILES -> MoleCode graph\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nprint(graph)\n\n# MoleCode graph -> SMILES (lossless round-trip)\nassert mol_to_smiles(mermaid_to_mol(graph)) == Chem.CanonSmiles(\"CC(=O)Oc1ccccc1C(=O)O\")\n```\n\n---\n\n## Works with your coding agent (Claude Code · Codex)\n\nMoleCode ships as a ready-to-use **[Agent Skill](https://docs.claude.com/en/docs/claude-code/skills)**,\nso coding agents can clone this repo and immediately reason over and edit\nmolecules at the explicit-graph level — no extra setup, no MCP server required.\n\n| Agent | How it picks MoleCode up |\n| --- | --- |\n| **Claude Code** | Auto-discovers the skill at [`.claude/skills/molecode/`](.claude/skills/molecode/). Just ask it to understand or edit a molecule. |\n| **Codex** (and other agents) | Reads [`AGENTS.md`](AGENTS.md) at the repo root and uses the bundled CLI; interface metadata in [`agents/openai.yaml`](.claude/skills/molecode/agents/openai.yaml). |\n\nInstead of asking the model to hand-write SMILES — error-prone for anything\nnon-trivial — the skill has it **convert → inspect the named atoms/bonds → edit\nthe graph → validate**, all through one stable CLI:\n\n```bash\npython .claude/skills/molecode/scripts/molecode_convert.py doctor\npython .claude/skills/molecode/scripts/molecode_convert.py smiles-to-molecode \"CCO\" --name Ethanol\npython .claude/skills/molecode/scripts/molecode_convert.py validate --input edited.mmd # formula, counts, round-trip\npython .claude/skills/molecode/scripts/molecode_convert.py molecode-to-smiles --input edited.mmd\n```\n\nThe skill bundles the six conversion forms (SMILES / PSMILES / Markush ↔\nMoleCode) plus `validate`, `compare` (Markush-aware isomorphism) and `doctor`, a\nsyntax reference for hand-editing graphs, and a file-based edit workflow built\nfor large molecules. See [`.claude/skills/molecode/SKILL.md`](.claude/skills/molecode/SKILL.md).\n\n## Three domains, one grammar\n\n### 🧪 Small molecules — [`molecode.molecule`](molecode/molecule)\n\nAtoms are `prefix_Element_Number[Label]` nodes; bonds are `---` (single), `===` (double), `-.-` (triple), with `===|E|`/`===|Z|` and `_R`/`_S` for stereochemistry. → [syntax reference](docs/02-syntax.md)\n\n### 🔗 Polymers — [`molecode.polymer`](molecode/polymer)\n\nThe repeat unit stays **explicit** as a subgraph carrying a symbolic `×n` count, with `TL`/`TR` terminus markers — so the graph does not blow up with chain length. → [polymer docs](docs/03-polymers.md)\n\n```python\nfrom molecode.polymer import polymer_to_mermaid, mermaid_to_psmiles\n\ngraph = polymer_to_mermaid(\"*NCCCCCC(=O)*\", n=8, name=\"Nylon-6\") # PSMILES -> graph\nmermaid_to_psmiles(graph) # -> '*NCCCCCC(=O)*'\n```\n\n### 🧩 Markush structures — [`molecode.markush`](molecode/markush)\n\nVariable R-groups and named substituents become **abbreviation nodes** in curly braces — `{R1}`, `{Boc}`, `{Ar}` — something plain SMILES cannot express. A built-in graph-isomorphism comparator scores predictions up to abbreviation expansion. → [Markush docs](docs/04-markush.md)\n\n```mermaid\ngraph TB\n subgraph Mol[\"molecule name\"]\n Mol_C_1[C]\n Mol_O_1[OH]\n Mol_X_1{Boc}\n Mol_X_2{R1}\n Mol_C_1 --- Mol_O_1\n Mol_C_1 --- Mol_X_1\n end\n```\n\n---\n\n## Run the tasks: understand · generate · edit · reason\n\nMoleCode is a **drop-in representation for any LLM** — feed the grammar as a system prompt, hand the model a graph, and validate its output deterministically. The [`examples/`](examples) folder has runnable scripts for all four task families (they run **offline by default**, printing the exact prompt; set `MOLECODE_API_KEY` to call a model):\n\n```bash\npython examples/01_molecule_roundtrip.py # SMILES <-> graph (lossless)\npython examples/02_polymer_roundtrip.py # polymers with ×n\npython examples/03_markush_roundtrip.py # abbreviation nodes & isomorphism\npython examples/04_understanding.py # count atoms / formula / rings ...\npython examples/05_generation.py # de novo design under constraints\npython examples/06_editing.py # local graph edits (add/del/substitute)\npython examples/07_reasoning.py # reaction-product prediction\npython examples/08_image_to_molecode.py # OCSR: molecule image -> MoleCode (vision model)\n```\n\nThe reusable ingredients:\n\n```python\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT # give this to the LLM as the system prompt\nfrom molecode.molecule import mol_to_mermaid # your molecule -> what the model reads\nfrom molecode.molecule import mermaid_to_mol # model output -> validated RDKit Mol\n```\n\n### Calling an LLM\n\nMoleCode is just a representation, so you can use **any** LLM SDK — the prompts\nare plain strings. For convenience the package also ships a tiny,\ndependency-free, **OpenAI-compatible** client (`molecode.llm.LLMClient`, built on\nstdlib `urllib`). You supply the API key and base URL — nothing is hard-coded, so\nit works with OpenAI, DeepSeek, Azure, Together, vLLM, Ollama, …\n\n```python\nfrom molecode import LLMClient\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT\nfrom molecode.molecule import mol_to_mermaid, mermaid_to_mol\nfrom rdkit import Chem\n\nclient = LLMClient(api_key=\"sk-...\", base_url=\"https://api.openai.com/v1\", model=\"\")\n# (or set MOLECODE_API_KEY / MOLECODE_BASE_URL / MOLECODE_MODEL and call LLMClient())\n\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nreply = client.chat(f\"How many carbons are in this molecule?\\n```mermaid\\n{graph}\\n```\",\n system=MOLECULE_SYSTEM_PROMPT)\nprint(reply)\n```\n\nPrefer the official `openai` SDK? Pass the same prompt strings straight to\n`openai.OpenAI().chat.completions.create(...)` — you don't need `LLMClient` at all.\n\nSee [docs/05-tasks.md](docs/05-tasks.md) for the full task catalog.\n\n| Domain | Understanding | Generation | Editing | Reasoning |\n| --- | :---: | :---: | :---: | :---: |\n| Molecules | ✅ | ✅ | ✅ | ✅ |\n| Polymers | ✅ | ✅ | ✅ | — |\n| Markush | ✅ | — | — | — |\n\n---\n\n## Repository layout\n\n```\nmolecode/ # the library (pip-installable)\n├── molecule/ # small-molecule <-> Mermaid (rdkit_to_mermaid, mermaid_to_rdkit)\n├── polymer/ # polymer <-> Mermaid (polymer_to_mermaid, mermaid_to_psmiles)\n├── markush/ # Markush <-> Mermaid + graph isomorphism + abbreviation_map\n├── prompts/ # LLM system prompts (molecule + markush grammars)\n└── llm.py # optional OpenAI-compatible client (you supply key + base_url)\nexamples/ # 7 runnable demos (round-trips + 4 task families)\ndocs/ # overview, syntax, polymers, markush, tasks, why-it-works\nAGENTS.md # entrypoint for coding agents\n.claude/skills/molecode/ # Agent Skill: SKILL.md + CLI + references (Claude Code / Codex)\n```\n\n---\n\n## Results at a glance\n\n| Generalization & reasoning | Goal-directed design | Scaling | Long molecules | General language |\n| :---: | :---: | :---: | :---: | :---: |\n| ![](docs/assets/results_1_main.png) | ![](docs/assets/results_2_chemistry.png) | ![](docs/assets/results_3_scaling.png) | ![](docs/assets/results_4_long_molecules.png) | ![](docs/assets/results_5_extension.png) |\n\n---\n\n## About AtomFlow\n\nMoleCode is built and maintained by **[AtomFlow](https://atomflow-ai.com/)**.\n\nAtomFlow builds **LLM-native AI for chemistry** — letting language models operate\ndirectly on molecular structure rather than on opaque strings. Our work centers on\nmolecule-grounded applications, including:\n\n- **Molecular chat & interaction** — converse with a molecule; select atoms, bonds,\n or fragments and edit them in natural language.\n- **Structure-aware editing** — auditable, graph-level molecular edits.\n- **Retrosynthesis** — LLM-native synthesis planning over explicit structures.\n- **Literature reading & structure parsing** — extracting structures from papers\n and patents, including optical chemical structure recognition (OCSR).\n\nMoleCode is the open representation layer underneath these products — making\nmolecular structure explicit, editable, and auditable for LLMs.\n\n🌐 Learn more at **[atomflow-ai.com](https://atomflow-ai.com/)**.\n\n## 📚 Citation\n\nIf you use MoleCode in your research, please cite the MoleCode technical report:\n\n```bibtex\n@article{yan2026molecode,\n title={MoleCode unlocks structural intelligence in large language models},\n author={Yan, Zhiyuan and Liu, Chen and Zhao, Boxuan and Lin, Kaiqing and Zhao, Jixiang and Wang, Yimi and Lv, Liuzhenghao and Li, Hao and Zhang, Shanzhuo and Yuan, Li and others},\n journal={arXiv preprint arXiv:2605.16480},\n year={2026}\n}\n```\n\n## License\n\n[MIT](LICENSE) © 2026 AtomFlow-AI\n"}, "e7859d2be8956a06a5394e0e76c4f05dd772bd38": {"t": 1785771613.7314856, "n": 13640, "h": "9a02af3bb63eca60", "c": "<div align=\"center\">\n\n# 🧬 MoleCode\n\n### An LLM-native, graph-explicit molecular language\n\nOfficial repository for [**MoleCode unlocks structural intelligence in large language models**](https://arxiv.org/pdf/2605.16480).\n\n*Molecode presents molecules as code and enables LLMs to operate and reason on chemistry directly.*\n<br>*Instead of making language models reconstruct molecular structure from cryptic strings,*\n<br>*MoleCode lets them read, write, and edit on the structures directly.*\n\n[![arXiv](https://img.shields.io/badge/arXiv-MoleCode-firebrick)](https://arxiv.org/abs/2605.16480)\n[![PDF](https://img.shields.io/badge/PDF-DADBDD)](https://arxiv.org/pdf/2605.16480)\n[![Website](https://img.shields.io/badge/AtomFlow-atomflow--ai.com-0b7285.svg)](https://atomflow-ai.com/)\n[![GitHub Stars](https://img.shields.io/github/stars/AtomFlow-AI/MoleCode.svg?style=social\\&label=Stars)](https://github.com/AtomFlow-AI/MoleCode)\n<br>[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)\n[![Powered by RDKit](https://img.shields.io/badge/powered%20by-RDKit-green.svg)](https://www.rdkit.org/)\n<br>[![Works with Claude Code](https://img.shields.io/badge/Works%20with-Claude%20Code-d97757.svg)](.claude/skills/molecode/)\n[![Works with Codex](https://img.shields.io/badge/Works%20with-Codex-412991.svg)](AGENTS.md)\n[![Agent Skill](https://img.shields.io/badge/Agent-Skill-blue.svg)](.claude/skills/molecode/SKILL.md)\n\n**English** | [中文](README.zh-CN.md)\n\n<br>\n<br>\n\n<img src=\"docs/assets/overview.png\" alt=\"MoleCode overview\" width=\"100%\">\n\n</div>\n\n---\n\n## What is MoleCode?\n\nA molecule **is** a graph: atoms are nodes, bonds are edges, and chemistry emerges from the topology. Yet large language models are almost always fed molecules as *linear strings* like SMILES, where the graph is **implicit** — connectivity is positional, branches are syntactic, and rings hide inside index digits. Before an LLM can do any chemistry, it must first *reconstruct the graph from the syntax*, spending reasoning budget on structural bookkeeping.\n\n**MoleCode makes the structure the language.** Every atom and bond is written as a typed declaration with a persistent identifier, serialized as a [Mermaid](https://mermaid.js.org/) graph. Topology becomes directly readable, editable, and auditable inside the context window — and the format is **deterministically and losslessly inter-convertible with SMILES / MOL via RDKit** (no learned model, no information loss).\n\n```mermaid\ngraph TB\n subgraph chlorophenol[\"para-chlorophenol\"]\n chlorophenol_C_1[C]\n chlorophenol_O_1[OH]\n chlorophenol_C_2[CH]\n chlorophenol_C_3[CH]\n chlorophenol_C_4[C]\n chlorophenol_Cl_1[Cl]\n chlorophenol_C_5[CH]\n chlorophenol_C_6[CH]\n chlorophenol_C_1 === chlorophenol_C_2\n chlorophenol_C_2 --- chlorophenol_C_3\n chlorophenol_C_3 === chlorophenol_C_4\n chlorophenol_C_4 --- chlorophenol_C_5\n chlorophenol_C_5 === chlorophenol_C_6\n chlorophenol_C_6 --- chlorophenol_C_1\n chlorophenol_C_1 --- chlorophenol_O_1\n chlorophenol_C_4 --- chlorophenol_Cl_1\n end\n```\n\n> The same `Subgraph → Node → Edge` grammar covers **small molecules, polymers, and Markush structures** — and extends to reaction mechanisms and multimodal document parsing.\n\n---\n\n## Why it matters\n\n| | SMILES | **MoleCode** |\n| --- | --- | --- |\n| Topology | implicit, positional | **explicit, named nodes & edges** |\n| Atom identity | none | **persistent IDs** (stable across prompt → reasoning → output) |\n| Editing | whole-string rewrite | **local graph op** (add a methyl = 1 node + 1 edge) |\n| Validation | fragile string parsing | **deterministic RDKit round-trip** |\n| Reasoning behavior | memorizes syntax | **generalizes over structure** |\n\nEmpirically (see the [MoleCode paper](#-citation) and [docs/06-why-it-works.md](docs/06-why-it-works.md)):\n\n- **Generalization, not memorization.** SMILES accuracy collapses from ~42% on familiar molecules to ~20% on novel ones; MoleCode holds **~76–80%** across all familiarity tiers.\n- **Cheaper reasoning.** MoleCode has longer *input* but its chain-of-thought grows **sub-linearly** with molecule size (~C^0.52) versus SMILES' super-linear ~C^1.65 — about a **5× lower total token cost** per query.\n- **Scales to big, repetitive objects.** Full-chain SMILES accuracy falls toward **0%** as polymer chains grow; MoleCode stays flat.\n- **Markush understanding** jumps from **38.1% → 84.0%**.\n\n---\n\n## Install\n\n```bash\ngit clone https://github.com/AtomFlow-AI/MoleCode.git\ncd MoleCode\npip install -e . # installs rdkit + networkx\n```\n\n## Quick start\n\n```python\nfrom rdkit import Chem\nfrom molecode import mol_to_mermaid, mermaid_to_mol, mol_to_smiles\n\n# SMILES -> MoleCode graph\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nprint(graph)\n\n# MoleCode graph -> SMILES (lossless round-trip)\nassert mol_to_smiles(mermaid_to_mol(graph)) == Chem.CanonSmiles(\"CC(=O)Oc1ccccc1C(=O)O\")\n```\n\n---\n\n## Works with your coding agent (Claude Code · Codex)\n\nMoleCode ships as a ready-to-use **[Agent Skill](https://docs.claude.com/en/docs/claude-code/skills)**,\nso coding agents can clone this repo and immediately reason over and edit\nmolecules at the explicit-graph level — no extra setup, no MCP server required.\n\n| Agent | How it picks MoleCode up |\n| --- | --- |\n| **Claude Code** | Auto-discovers the skill at [`.claude/skills/molecode/`](.claude/skills/molecode/). Just ask it to understand or edit a molecule. |\n| **Codex** (and other agents) | Reads [`AGENTS.md`](AGENTS.md) at the repo root and uses the bundled CLI; interface metadata in [`agents/openai.yaml`](.claude/skills/molecode/agents/openai.yaml). |\n\nInstead of asking the model to hand-write SMILES — error-prone for anything\nnon-trivial — the skill has it **convert → inspect the named atoms/bonds → edit\nthe graph → validate**, all through one stable CLI:\n\n```bash\npython .claude/skills/molecode/scripts/molecode_convert.py doctor\npython .claude/skills/molecode/scripts/molecode_convert.py smiles-to-molecode \"CCO\" --name Ethanol\npython .claude/skills/molecode/scripts/molecode_convert.py validate --input edited.mmd # formula, counts, round-trip\npython .claude/skills/molecode/scripts/molecode_convert.py molecode-to-smiles --input edited.mmd\n```\n\nThe skill bundles the six conversion forms (SMILES / PSMILES / Markush ↔\nMoleCode) plus `validate`, `compare` (Markush-aware isomorphism) and `doctor`, a\nsyntax reference for hand-editing graphs, and a file-based edit workflow built\nfor large molecules. See [`.claude/skills/molecode/SKILL.md`](.claude/skills/molecode/SKILL.md).\n\n## Three domains, one grammar\n\n### 🧪 Small molecules — [`molecode.molecule`](molecode/molecule)\n\nAtoms are `prefix_Element_Number[Label]` nodes; bonds are `---` (single), `===` (double), `-.-` (triple), with `===|E|`/`===|Z|` and `_R`/`_S` for stereochemistry. → [syntax reference](docs/02-syntax.md)\n\n### 🔗 Polymers — [`molecode.polymer`](molecode/polymer)\n\nThe repeat unit stays **explicit** as a subgraph carrying a symbolic `×n` count, with `TL`/`TR` terminus markers — so the graph does not blow up with chain length. → [polymer docs](docs/03-polymers.md)\n\n```python\nfrom molecode.polymer import polymer_to_mermaid, mermaid_to_psmiles\n\ngraph = polymer_to_mermaid(\"*NCCCCCC(=O)*\", n=8, name=\"Nylon-6\") # PSMILES -> graph\nmermaid_to_psmiles(graph) # -> '*NCCCCCC(=O)*'\n```\n\n### 🧩 Markush structures — [`molecode.markush`](molecode/markush)\n\nVariable R-groups and named substituents become **abbreviation nodes** in curly braces — `{R1}`, `{Boc}`, `{Ar}` — something plain SMILES cannot express. A built-in graph-isomorphism comparator scores predictions up to abbreviation expansion. → [Markush docs](docs/04-markush.md)\n\n```mermaid\ngraph TB\n subgraph Mol[\"molecule name\"]\n Mol_C_1[C]\n Mol_O_1[OH]\n Mol_X_1{Boc}\n Mol_X_2{R1}\n Mol_C_1 --- Mol_O_1\n Mol_C_1 --- Mol_X_1\n end\n```\n\n---\n\n## Run the tasks: understand · generate · edit · reason\n\nMoleCode is a **drop-in representation for any LLM** — feed the grammar as a system prompt, hand the model a graph, and validate its output deterministically. The [`examples/`](examples) folder has runnable scripts for all four task families (they run **offline by default**, printing the exact prompt; set `MOLECODE_API_KEY` to call a model):\n\n```bash\npython examples/01_molecule_roundtrip.py # SMILES <-> graph (lossless)\npython examples/02_polymer_roundtrip.py # polymers with ×n\npython examples/03_markush_roundtrip.py # abbreviation nodes & isomorphism\npython examples/04_understanding.py # count atoms / formula / rings ...\npython examples/05_generation.py # de novo design under constraints\npython examples/06_editing.py # local graph edits (add/del/substitute)\npython examples/07_reasoning.py # reaction-product prediction\npython examples/08_image_to_molecode.py # OCSR: molecule image -> MoleCode (vision model)\n```\n\nThe reusable ingredients:\n\n```python\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT # give this to the LLM as the system prompt\nfrom molecode.molecule import mol_to_mermaid # your molecule -> what the model reads\nfrom molecode.molecule import mermaid_to_mol # model output -> validated RDKit Mol\n```\n\n### Calling an LLM\n\nMoleCode is just a representation, so you can use **any** LLM SDK — the prompts\nare plain strings. For convenience the package also ships a tiny,\ndependency-free, **OpenAI-compatible** client (`molecode.llm.LLMClient`, built on\nstdlib `urllib`). You supply the API key and base URL — nothing is hard-coded, so\nit works with OpenAI, DeepSeek, Azure, Together, vLLM, Ollama, …\n\n```python\nfrom molecode import LLMClient\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT\nfrom molecode.molecule import mol_to_mermaid, mermaid_to_mol\nfrom rdkit import Chem\n\nclient = LLMClient(api_key=\"sk-...\", base_url=\"https://api.openai.com/v1\", model=\"\")\n# (or set MOLECODE_API_KEY / MOLECODE_BASE_URL / MOLECODE_MODEL and call LLMClient())\n\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nreply = client.chat(f\"How many carbons are in this molecule?\\n```mermaid\\n{graph}\\n```\",\n system=MOLECULE_SYSTEM_PROMPT)\nprint(reply)\n```\n\nPrefer the official `openai` SDK? Pass the same prompt strings straight to\n`openai.OpenAI().chat.completions.create(...)` — you don't need `LLMClient` at all.\n\nSee [docs/05-tasks.md](docs/05-tasks.md) for the full task catalog.\n\n| Domain | Understanding | Generation | Editing | Reasoning |\n| --- | :---: | :---: | :---: | :---: |\n| Molecules | ✅ | ✅ | ✅ | ✅ |\n| Polymers | ✅ | ✅ | ✅ | — |\n| Markush | ✅ | — | — | — |\n\n---\n\n## Repository layout\n\n```\nmolecode/ # the library (pip-installable)\n├── molecule/ # small-molecule <-> Mermaid (rdkit_to_mermaid, mermaid_to_rdkit)\n├── polymer/ # polymer <-> Mermaid (polymer_to_mermaid, mermaid_to_psmiles)\n├── markush/ # Markush <-> Mermaid + graph isomorphism + abbreviation_map\n├── prompts/ # LLM system prompts (molecule + markush grammars)\n└── llm.py # optional OpenAI-compatible client (you supply key + base_url)\nexamples/ # 7 runnable demos (round-trips + 4 task families)\ndocs/ # overview, syntax, polymers, markush, tasks, why-it-works\nAGENTS.md # entrypoint for coding agents\n.claude/skills/molecode/ # Agent Skill: SKILL.md + CLI + references (Claude Code / Codex)\n```\n\n---\n\n## Results at a glance\n\n| Generalization & reasoning | Goal-directed design | Scaling | Long molecules | General language |\n| :---: | :---: | :---: | :---: | :---: |\n| ![](docs/assets/results_1_main.png) | ![](docs/assets/results_2_chemistry.png) | ![](docs/assets/results_3_scaling.png) | ![](docs/assets/results_4_long_molecules.png) | ![](docs/assets/results_5_extension.png) |\n\n---\n\n## About AtomFlow\n\nMoleCode is built and maintained by **[AtomFlow](https://atomflow-ai.com/)**.\n\nAtomFlow builds **LLM-native AI for chemistry** — letting language models operate\ndirectly on molecular structure rather than on opaque strings. Our work centers on\nmolecule-grounded applications, including:\n\n- **Molecular chat & interaction** — converse with a molecule; select atoms, bonds,\n or fragments and edit them in natural language.\n- **Structure-aware editing** — auditable, graph-level molecular edits.\n- **Retrosynthesis** — LLM-native synthesis planning over explicit structures.\n- **Literature reading & structure parsing** — extracting structures from papers\n and patents, including optical chemical structure recognition (OCSR).\n\nMoleCode is the open representation layer underneath these products — making\nmolecular structure explicit, editable, and auditable for LLMs.\n\n🌐 Learn more at **[atomflow-ai.com](https://atomflow-ai.com/)**.\n\n## 📚 Citation\n\nIf you use MoleCode in your research, please cite the MoleCode technical report:\n\n```bibtex\n@article{yan2026molecode,\n title={MoleCode unlocks structural intelligence in large language models},\n author={Yan, Zhiyuan and Liu, Chen and Zhao, Boxuan and Lin, Kaiqing and Zhao, Jixiang and Wang, Yimi and Lv, Liuzhenghao and Li, Hao and Zhang, Shanzhuo and Yuan, Li and others},\n journal={arXiv preprint arXiv:2605.16480},\n year={2026}\n}\n```\n\n## License\n\n[MIT](LICENSE) © 2026 AtomFlow-AI\n"}, "977b14bdcabbeeaf9dcd85c92c6c21de8487ffef": {"t": 1785771614.9508228, "n": 13122, "h": "454ca2c193bde659", "c": "<div align=\"center\">\n\n# 🧬 MoleCode\n\n### An LLM-native, graph-explicit molecular language\n\n**From molecular strings to structural code: enabling LLMs to operate on chemistry directly.**\n\n*Stop making language models reconstruct molecular structure from cryptic strings — let them read, write, and edit structure directly.*\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)\n[![Powered by RDKit](https://img.shields.io/badge/powered%20by-RDKit-green.svg)](https://www.rdkit.org/)\n[![Website](https://img.shields.io/badge/AtomFlow-atomflow--ai.com-0b7285.svg)](https://atomflow-ai.com/)\n\n[![Works with Claude Code](https://img.shields.io/badge/Works%20with-Claude%20Code-d97757.svg)](.claude/skills/molecode/)\n[![Works with Codex](https://img.shields.io/badge/Works%20with-Codex-412991.svg)](AGENTS.md)\n[![Agent Skill](https://img.shields.io/badge/Agent-Skill-blue.svg)](.claude/skills/molecode/SKILL.md)\n\n**English** | [中文](README.zh-CN.md)\n\n<img src=\"docs/assets/overview.png\" alt=\"MoleCode overview\" width=\"100%\">\n\n</div>\n\n---\n\n## What is MoleCode?\n\nA molecule **is** a graph: atoms are nodes, bonds are edges, and chemistry emerges from the topology. Yet large language models are almost always fed molecules as *linear strings* like SMILES, where the graph is **implicit** — connectivity is positional, branches are syntactic, and rings hide inside index digits. Before an LLM can do any chemistry, it must first *reconstruct the graph from the syntax*, spending reasoning budget on structural bookkeeping.\n\n**MoleCode makes the structure the language.** Every atom and bond is written as a typed declaration with a persistent identifier, serialized as a [Mermaid](https://mermaid.js.org/) graph. Topology becomes directly readable, editable, and auditable inside the context window — and the format is **deterministically and losslessly inter-convertible with SMILES / MOL via RDKit** (no learned model, no information loss).\n\n```mermaid\ngraph TB\n subgraph chlorophenol[\"para-chlorophenol\"]\n chlorophenol_C_1[C]\n chlorophenol_O_1[OH]\n chlorophenol_C_2[CH]\n chlorophenol_C_3[CH]\n chlorophenol_C_4[C]\n chlorophenol_Cl_1[Cl]\n chlorophenol_C_5[CH]\n chlorophenol_C_6[CH]\n chlorophenol_C_1 === chlorophenol_C_2\n chlorophenol_C_2 --- chlorophenol_C_3\n chlorophenol_C_3 === chlorophenol_C_4\n chlorophenol_C_4 --- chlorophenol_C_5\n chlorophenol_C_5 === chlorophenol_C_6\n chlorophenol_C_6 --- chlorophenol_C_1\n chlorophenol_C_1 --- chlorophenol_O_1\n chlorophenol_C_4 --- chlorophenol_Cl_1\n end\n```\n\n> The same `Subgraph → Node → Edge` grammar covers **small molecules, polymers, and Markush structures** — and extends to reaction mechanisms and multimodal document parsing.\n\n---\n\n## Why it matters\n\n| | SMILES | **MoleCode** |\n| --- | --- | --- |\n| Topology | implicit, positional | **explicit, named nodes & edges** |\n| Atom identity | none | **persistent IDs** (stable across prompt → reasoning → output) |\n| Editing | whole-string rewrite | **local graph op** (add a methyl = 1 node + 1 edge) |\n| Validation | fragile string parsing | **deterministic RDKit round-trip** |\n| Reasoning behavior | memorizes syntax | **generalizes over structure** |\n\nEmpirically (see the [MoleCode paper](#-citation) and [docs/06-why-it-works.md](docs/06-why-it-works.md)):\n\n- **Generalization, not memorization.** SMILES accuracy collapses from ~42% on familiar molecules to ~20% on novel ones; MoleCode holds **~76–80%** across all familiarity tiers.\n- **Cheaper reasoning.** MoleCode has longer *input* but its chain-of-thought grows **sub-linearly** with molecule size (~C^0.52) versus SMILES' super-linear ~C^1.65 — about a **5× lower total token cost** per query.\n- **Scales to big, repetitive objects.** Full-chain SMILES accuracy falls toward **0%** as polymer chains grow; MoleCode stays flat.\n- **Markush understanding** jumps from **38.1% → 84.0%**.\n\n---\n\n## Install\n\n```bash\ngit clone https://github.com/AtomFlow-AI/MoleCode.git\ncd MoleCode\npip install -e . # installs rdkit + networkx\n```\n\n## Quick start\n\n```python\nfrom rdkit import Chem\nfrom molecode import mol_to_mermaid, mermaid_to_mol, mol_to_smiles\n\n# SMILES -> MoleCode graph\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nprint(graph)\n\n# MoleCode graph -> SMILES (lossless round-trip)\nassert mol_to_smiles(mermaid_to_mol(graph)) == Chem.CanonSmiles(\"CC(=O)Oc1ccccc1C(=O)O\")\n```\n\n---\n\n## Works with your coding agent (Claude Code · Codex)\n\nMoleCode ships as a ready-to-use **[Agent Skill](https://docs.claude.com/en/docs/claude-code/skills)**,\nso coding agents can clone this repo and immediately reason over and edit\nmolecules at the explicit-graph level — no extra setup, no MCP server required.\n\n| Agent | How it picks MoleCode up |\n| --- | --- |\n| **Claude Code** | Auto-discovers the skill at [`.claude/skills/molecode/`](.claude/skills/molecode/). Just ask it to understand or edit a molecule. |\n| **Codex** (and other agents) | Reads [`AGENTS.md`](AGENTS.md) at the repo root and uses the bundled CLI; interface metadata in [`agents/openai.yaml`](.claude/skills/molecode/agents/openai.yaml). |\n\nInstead of asking the model to hand-write SMILES — error-prone for anything\nnon-trivial — the skill has it **convert → inspect the named atoms/bonds → edit\nthe graph → validate**, all through one stable CLI:\n\n```bash\npython .claude/skills/molecode/scripts/molecode_convert.py doctor\npython .claude/skills/molecode/scripts/molecode_convert.py smiles-to-molecode \"CCO\" --name Ethanol\npython .claude/skills/molecode/scripts/molecode_convert.py validate --input edited.mmd # formula, counts, round-trip\npython .claude/skills/molecode/scripts/molecode_convert.py molecode-to-smiles --input edited.mmd\n```\n\nThe skill bundles the six conversion forms (SMILES / PSMILES / Markush ↔\nMoleCode) plus `validate`, `compare` (Markush-aware isomorphism) and `doctor`, a\nsyntax reference for hand-editing graphs, and a file-based edit workflow built\nfor large molecules. See [`.claude/skills/molecode/SKILL.md`](.claude/skills/molecode/SKILL.md).\n\n## Three domains, one grammar\n\n### 🧪 Small molecules — [`molecode.molecule`](molecode/molecule)\n\nAtoms are `prefix_Element_Number[Label]` nodes; bonds are `---` (single), `===` (double), `-.-` (triple), with `===|E|`/`===|Z|` and `_R`/`_S` for stereochemistry. → [syntax reference](docs/02-syntax.md)\n\n### 🔗 Polymers — [`molecode.polymer`](molecode/polymer)\n\nThe repeat unit stays **explicit** as a subgraph carrying a symbolic `×n` count, with `TL`/`TR` terminus markers — so the graph does not blow up with chain length. → [polymer docs](docs/03-polymers.md)\n\n```python\nfrom molecode.polymer import polymer_to_mermaid, mermaid_to_psmiles\n\ngraph = polymer_to_mermaid(\"*NCCCCCC(=O)*\", n=8, name=\"Nylon-6\") # PSMILES -> graph\nmermaid_to_psmiles(graph) # -> '*NCCCCCC(=O)*'\n```\n\n### 🧩 Markush structures — [`molecode.markush`](molecode/markush)\n\nVariable R-groups and named substituents become **abbreviation nodes** in curly braces — `{R1}`, `{Boc}`, `{Ar}` — something plain SMILES cannot express. A built-in graph-isomorphism comparator scores predictions up to abbreviation expansion. → [Markush docs](docs/04-markush.md)\n\n```mermaid\ngraph TB\n subgraph Mol[\"molecule name\"]\n Mol_C_1[C]\n Mol_O_1[OH]\n Mol_X_1{Boc}\n Mol_X_2{R1}\n Mol_C_1 --- Mol_O_1\n Mol_C_1 --- Mol_X_1\n end\n```\n\n---\n\n## Run the tasks: understand · generate · edit · reason\n\nMoleCode is a **drop-in representation for any LLM** — feed the grammar as a system prompt, hand the model a graph, and validate its output deterministically. The [`examples/`](examples) folder has runnable scripts for all four task families (they run **offline by default**, printing the exact prompt; set `MOLECODE_API_KEY` to call a model):\n\n```bash\npython examples/01_molecule_roundtrip.py # SMILES <-> graph (lossless)\npython examples/02_polymer_roundtrip.py # polymers with ×n\npython examples/03_markush_roundtrip.py # abbreviation nodes & isomorphism\npython examples/04_understanding.py # count atoms / formula / rings ...\npython examples/05_generation.py # de novo design under constraints\npython examples/06_editing.py # local graph edits (add/del/substitute)\npython examples/07_reasoning.py # reaction-product prediction\npython examples/08_image_to_molecode.py # OCSR: molecule image -> MoleCode (vision model)\n```\n\nThe reusable ingredients:\n\n```python\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT # give this to the LLM as the system prompt\nfrom molecode.molecule import mol_to_mermaid # your molecule -> what the model reads\nfrom molecode.molecule import mermaid_to_mol # model output -> validated RDKit Mol\n```\n\n### Calling an LLM\n\nMoleCode is just a representation, so you can use **any** LLM SDK — the prompts\nare plain strings. For convenience the package also ships a tiny,\ndependency-free, **OpenAI-compatible** client (`molecode.llm.LLMClient`, built on\nstdlib `urllib`). You supply the API key and base URL — nothing is hard-coded, so\nit works with OpenAI, DeepSeek, Azure, Together, vLLM, Ollama, …\n\n```python\nfrom molecode import LLMClient\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT\nfrom molecode.molecule import mol_to_mermaid, mermaid_to_mol\nfrom rdkit import Chem\n\nclient = LLMClient(api_key=\"sk-...\", base_url=\"https://api.openai.com/v1\", model=\"\")\n# (or set MOLECODE_API_KEY / MOLECODE_BASE_URL / MOLECODE_MODEL and call LLMClient())\n\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nreply = client.chat(f\"How many carbons are in this molecule?\\n```mermaid\\n{graph}\\n```\",\n system=MOLECULE_SYSTEM_PROMPT)\nprint(reply)\n```\n\nPrefer the official `openai` SDK? Pass the same prompt strings straight to\n`openai.OpenAI().chat.completions.create(...)` — you don't need `LLMClient` at all.\n\nSee [docs/05-tasks.md](docs/05-tasks.md) for the full task catalog.\n\n| Domain | Understanding | Generation | Editing | Reasoning |\n| --- | :---: | :---: | :---: | :---: |\n| Molecules | ✅ | ✅ | ✅ | ✅ |\n| Polymers | ✅ | ✅ | ✅ | — |\n| Markush | ✅ | — | — | — |\n\n---\n\n## Repository layout\n\n```\nmolecode/ # the library (pip-installable)\n├── molecule/ # small-molecule <-> Mermaid (rdkit_to_mermaid, mermaid_to_rdkit)\n├── polymer/ # polymer <-> Mermaid (polymer_to_mermaid, mermaid_to_psmiles)\n├── markush/ # Markush <-> Mermaid + graph isomorphism + abbreviation_map\n├── prompts/ # LLM system prompts (molecule + markush grammars)\n└── llm.py # optional OpenAI-compatible client (you supply key + base_url)\nexamples/ # 7 runnable demos (round-trips + 4 task families)\ndocs/ # overview, syntax, polymers, markush, tasks, why-it-works\nAGENTS.md # entrypoint for coding agents\n.claude/skills/molecode/ # Agent Skill: SKILL.md + CLI + references (Claude Code / Codex)\n```\n\n---\n\n## Results at a glance\n\n| Generalization & reasoning | Goal-directed design | Scaling | Long molecules | General language |\n| :---: | :---: | :---: | :---: | :---: |\n| ![](docs/assets/results_1_main.png) | ![](docs/assets/results_2_chemistry.png) | ![](docs/assets/results_3_scaling.png) | ![](docs/assets/results_4_long_molecules.png) | ![](docs/assets/results_5_extension.png) |\n\n---\n\n## About AtomFlow\n\nMoleCode is built and maintained by **[AtomFlow](https://atomflow-ai.com/)**.\n\nAtomFlow builds **LLM-native AI for chemistry** — letting language models operate\ndirectly on molecular structure rather than on opaque strings. Our work centers on\nmolecule-grounded applications, including:\n\n- **Molecular chat & interaction** — converse with a molecule; select atoms, bonds,\n or fragments and edit them in natural language.\n- **Structure-aware editing** — auditable, graph-level molecular edits.\n- **Retrosynthesis** — LLM-native synthesis planning over explicit structures.\n- **Literature reading & structure parsing** — extracting structures from papers\n and patents, including optical chemical structure recognition (OCSR).\n\nMoleCode is the open representation layer underneath these products — making\nmolecular structure explicit, editable, and auditable for LLMs.\n\n🌐 Learn more at **[atomflow-ai.com](https://atomflow-ai.com/)**.\n\n## 📚 Citation\n\nIf you use MoleCode in your research, please cite the MoleCode technical report:\n\n```bibtex\n@article{yan2026molecode,\n title={MoleCode unlocks structural intelligence in large language models},\n author={Yan, Zhiyuan and Liu, Chen and Zhao, Boxuan and Lin, Kaiqing and Zhao, Jixiang and Wang, Yimi and Lv, Liuzhenghao and Li, Hao and Zhang, Shanzhuo and Yuan, Li and others},\n journal={arXiv preprint arXiv:2605.16480},\n year={2026}\n}\n```\n\n## License\n\n[MIT](LICENSE) © 2026 AtomFlow-AI\n"}, "ec4f25b1dfc2fc29e19e1026dd66315ee1166ac6": {"t": 1785771616.7349007, "n": 13033, "h": "07fb601c49f85a4e", "c": "<div align=\"center\">\n\n# 🧬 MoleCode\n\n### An LLM-native, graph-explicit molecular language\n\n**From molecular strings to structural code: enabling LLMs to operate on chemistry directly.**\n\n*Stop making language models reconstruct molecular structure from cryptic strings — let them read, write, and edit structure directly.*\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)\n[![Powered by RDKit](https://img.shields.io/badge/powered%20by-RDKit-green.svg)](https://www.rdkit.org/)\n[![Website](https://img.shields.io/badge/AtomFlow-atomflow--ai.com-0b7285.svg)](https://atomflow-ai.com/)\n\n[![Works with Claude Code](https://img.shields.io/badge/Works%20with-Claude%20Code-d97757.svg)](.claude/skills/molecode/)\n[![Works with Codex](https://img.shields.io/badge/Works%20with-Codex-412991.svg)](AGENTS.md)\n[![Agent Skill](https://img.shields.io/badge/Agent-Skill-blue.svg)](.claude/skills/molecode/SKILL.md)\n\n**English** | [中文](README.zh-CN.md)\n\n<img src=\"docs/assets/overview.png\" alt=\"MoleCode overview\" width=\"100%\">\n\n</div>\n\n---\n\n## What is MoleCode?\n\nA molecule **is** a graph: atoms are nodes, bonds are edges, and chemistry emerges from the topology. Yet large language models are almost always fed molecules as *linear strings* like SMILES, where the graph is **implicit** — connectivity is positional, branches are syntactic, and rings hide inside index digits. Before an LLM can do any chemistry, it must first *reconstruct the graph from the syntax*, spending reasoning budget on structural bookkeeping.\n\n**MoleCode makes the structure the language.** Every atom and bond is written as a typed declaration with a persistent identifier, serialized as a [Mermaid](https://mermaid.js.org/) graph. Topology becomes directly readable, editable, and auditable inside the context window — and the format is **deterministically and losslessly inter-convertible with SMILES / MOL via RDKit** (no learned model, no information loss).\n\n```mermaid\ngraph TB\n subgraph chlorophenol[\"para-chlorophenol\"]\n chlorophenol_C_1[C]\n chlorophenol_O_1[OH]\n chlorophenol_C_2[CH]\n chlorophenol_C_3[CH]\n chlorophenol_C_4[C]\n chlorophenol_Cl_1[Cl]\n chlorophenol_C_5[CH]\n chlorophenol_C_6[CH]\n chlorophenol_C_1 === chlorophenol_C_2\n chlorophenol_C_2 --- chlorophenol_C_3\n chlorophenol_C_3 === chlorophenol_C_4\n chlorophenol_C_4 --- chlorophenol_C_5\n chlorophenol_C_5 === chlorophenol_C_6\n chlorophenol_C_6 --- chlorophenol_C_1\n chlorophenol_C_1 --- chlorophenol_O_1\n chlorophenol_C_4 --- chlorophenol_Cl_1\n end\n```\n\n> The same `Subgraph → Node → Edge` grammar covers **small molecules, polymers, and Markush structures** — and extends to reaction mechanisms and multimodal document parsing.\n\n---\n\n## Why it matters\n\n| | SMILES | **MoleCode** |\n| --- | --- | --- |\n| Topology | implicit, positional | **explicit, named nodes & edges** |\n| Atom identity | none | **persistent IDs** (stable across prompt → reasoning → output) |\n| Editing | whole-string rewrite | **local graph op** (add a methyl = 1 node + 1 edge) |\n| Validation | fragile string parsing | **deterministic RDKit round-trip** |\n| Reasoning behavior | memorizes syntax | **generalizes over structure** |\n\nEmpirically (see the [MoleCode paper](#-citation) and [docs/06-why-it-works.md](docs/06-why-it-works.md)):\n\n- **Generalization, not memorization.** SMILES accuracy collapses from ~42% on familiar molecules to ~20% on novel ones; MoleCode holds **~76–80%** across all familiarity tiers.\n- **Cheaper reasoning.** MoleCode has longer *input* but its chain-of-thought grows **sub-linearly** with molecule size (~C^0.52) versus SMILES' super-linear ~C^1.65 — about a **5× lower total token cost** per query.\n- **Scales to big, repetitive objects.** Full-chain SMILES accuracy falls toward **0%** as polymer chains grow; MoleCode stays flat.\n- **Markush understanding** jumps from **38.1% → 84.0%**.\n\n---\n\n## Install\n\n```bash\ngit clone https://github.com/AtomFlow-AI/MoleCode.git\ncd MoleCode\npip install -e . # installs rdkit + networkx\n```\n\n## Quick start\n\n```python\nfrom rdkit import Chem\nfrom molecode import mol_to_mermaid, mermaid_to_mol, mol_to_smiles\n\n# SMILES -> MoleCode graph\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nprint(graph)\n\n# MoleCode graph -> SMILES (lossless round-trip)\nassert mol_to_smiles(mermaid_to_mol(graph)) == Chem.CanonSmiles(\"CC(=O)Oc1ccccc1C(=O)O\")\n```\n\n---\n\n## Works with your coding agent (Claude Code · Codex)\n\nMoleCode ships as a ready-to-use **[Agent Skill](https://docs.claude.com/en/docs/claude-code/skills)**,\nso coding agents can clone this repo and immediately reason over and edit\nmolecules at the explicit-graph level — no extra setup, no MCP server required.\n\n| Agent | How it picks MoleCode up |\n| --- | --- |\n| **Claude Code** | Auto-discovers the skill at [`.claude/skills/molecode/`](.claude/skills/molecode/). Just ask it to understand or edit a molecule. |\n| **Codex** (and other agents) | Reads [`AGENTS.md`](AGENTS.md) at the repo root and uses the bundled CLI; interface metadata in [`agents/openai.yaml`](.claude/skills/molecode/agents/openai.yaml). |\n\nInstead of asking the model to hand-write SMILES — error-prone for anything\nnon-trivial — the skill has it **convert → inspect the named atoms/bonds → edit\nthe graph → validate**, all through one stable CLI:\n\n```bash\npython .claude/skills/molecode/scripts/molecode_convert.py doctor\npython .claude/skills/molecode/scripts/molecode_convert.py smiles-to-molecode \"CCO\" --name Ethanol\npython .claude/skills/molecode/scripts/molecode_convert.py validate --input edited.mmd # formula, counts, round-trip\npython .claude/skills/molecode/scripts/molecode_convert.py molecode-to-smiles --input edited.mmd\n```\n\nThe skill bundles the six conversion forms (SMILES / PSMILES / Markush ↔\nMoleCode) plus `validate`, `compare` (Markush-aware isomorphism) and `doctor`, a\nsyntax reference for hand-editing graphs, and a file-based edit workflow built\nfor large molecules. See [`.claude/skills/molecode/SKILL.md`](.claude/skills/molecode/SKILL.md).\n\n## Three domains, one grammar\n\n### 🧪 Small molecules — [`molecode.molecule`](molecode/molecule)\n\nAtoms are `prefix_Element_Number[Label]` nodes; bonds are `---` (single), `===` (double), `-.-` (triple), with `===|E|`/`===|Z|` and `_R`/`_S` for stereochemistry. → [syntax reference](docs/02-syntax.md)\n\n### 🔗 Polymers — [`molecode.polymer`](molecode/polymer)\n\nThe repeat unit stays **explicit** as a subgraph carrying a symbolic `×n` count, with `TL`/`TR` terminus markers — so the graph does not blow up with chain length. → [polymer docs](docs/03-polymers.md)\n\n```python\nfrom molecode.polymer import polymer_to_mermaid, mermaid_to_psmiles\n\ngraph = polymer_to_mermaid(\"*NCCCCCC(=O)*\", n=8, name=\"Nylon-6\") # PSMILES -> graph\nmermaid_to_psmiles(graph) # -> '*NCCCCCC(=O)*'\n```\n\n### 🧩 Markush structures — [`molecode.markush`](molecode/markush)\n\nVariable R-groups and named substituents become **abbreviation nodes** in curly braces — `{R1}`, `{Boc}`, `{Ar}` — something plain SMILES cannot express. A built-in graph-isomorphism comparator scores predictions up to abbreviation expansion. → [Markush docs](docs/04-markush.md)\n\n```mermaid\ngraph TB\n subgraph Mol[\"molecule name\"]\n Mol_C_1[C]\n Mol_O_1[OH]\n Mol_X_1{Boc}\n Mol_X_2{R1}\n Mol_C_1 --- Mol_O_1\n Mol_C_1 --- Mol_X_1\n end\n```\n\n---\n\n## Run the tasks: understand · generate · edit · reason\n\nMoleCode is a **drop-in representation for any LLM** — feed the grammar as a system prompt, hand the model a graph, and validate its output deterministically. The [`examples/`](examples) folder has runnable scripts for all four task families (they run **offline by default**, printing the exact prompt; set `MOLECODE_API_KEY` to call a model):\n\n```bash\npython examples/01_molecule_roundtrip.py # SMILES <-> graph (lossless)\npython examples/02_polymer_roundtrip.py # polymers with ×n\npython examples/03_markush_roundtrip.py # abbreviation nodes & isomorphism\npython examples/04_understanding.py # count atoms / formula / rings ...\npython examples/05_generation.py # de novo design under constraints\npython examples/06_editing.py # local graph edits (add/del/substitute)\npython examples/07_reasoning.py # reaction-product prediction\n```\n\nThe reusable ingredients:\n\n```python\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT # give this to the LLM as the system prompt\nfrom molecode.molecule import mol_to_mermaid # your molecule -> what the model reads\nfrom molecode.molecule import mermaid_to_mol # model output -> validated RDKit Mol\n```\n\n### Calling an LLM\n\nMoleCode is just a representation, so you can use **any** LLM SDK — the prompts\nare plain strings. For convenience the package also ships a tiny,\ndependency-free, **OpenAI-compatible** client (`molecode.llm.LLMClient`, built on\nstdlib `urllib`). You supply the API key and base URL — nothing is hard-coded, so\nit works with OpenAI, DeepSeek, Azure, Together, vLLM, Ollama, …\n\n```python\nfrom molecode import LLMClient\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT\nfrom molecode.molecule import mol_to_mermaid, mermaid_to_mol\nfrom rdkit import Chem\n\nclient = LLMClient(api_key=\"sk-...\", base_url=\"https://api.openai.com/v1\", model=\"\")\n# (or set MOLECODE_API_KEY / MOLECODE_BASE_URL / MOLECODE_MODEL and call LLMClient())\n\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nreply = client.chat(f\"How many carbons are in this molecule?\\n```mermaid\\n{graph}\\n```\",\n system=MOLECULE_SYSTEM_PROMPT)\nprint(reply)\n```\n\nPrefer the official `openai` SDK? Pass the same prompt strings straight to\n`openai.OpenAI().chat.completions.create(...)` — you don't need `LLMClient` at all.\n\nSee [docs/05-tasks.md](docs/05-tasks.md) for the full task catalog.\n\n| Domain | Understanding | Generation | Editing | Reasoning |\n| --- | :---: | :---: | :---: | :---: |\n| Molecules | ✅ | ✅ | ✅ | ✅ |\n| Polymers | ✅ | ✅ | ✅ | — |\n| Markush | ✅ | — | — | — |\n\n---\n\n## Repository layout\n\n```\nmolecode/ # the library (pip-installable)\n├── molecule/ # small-molecule <-> Mermaid (rdkit_to_mermaid, mermaid_to_rdkit)\n├── polymer/ # polymer <-> Mermaid (polymer_to_mermaid, mermaid_to_psmiles)\n├── markush/ # Markush <-> Mermaid + egl_graph isomorphism + abbreviation_map\n├── prompts/ # LLM system prompts (molecule + markush grammars)\n└── llm.py # optional OpenAI-compatible client (you supply key + base_url)\nexamples/ # 7 runnable demos (round-trips + 4 task families)\ndocs/ # overview, syntax, polymers, markush, tasks, why-it-works\nAGENTS.md # entrypoint for coding agents\n.claude/skills/molecode/ # Agent Skill: SKILL.md + CLI + references (Claude Code / Codex)\n```\n\n---\n\n## Results at a glance\n\n| Generalization & reasoning | Goal-directed design | Scaling | Long molecules | General language |\n| :---: | :---: | :---: | :---: | :---: |\n| ![](docs/assets/results_1_main.png) | ![](docs/assets/results_2_chemistry.png) | ![](docs/assets/results_3_scaling.png) | ![](docs/assets/results_4_long_molecules.png) | ![](docs/assets/results_5_extension.png) |\n\n---\n\n## About AtomFlow\n\nMoleCode is built and maintained by **[AtomFlow](https://atomflow-ai.com/)**.\n\nAtomFlow builds **LLM-native AI for chemistry** — letting language models operate\ndirectly on molecular structure rather than on opaque strings. Our work centers on\nmolecule-grounded applications, including:\n\n- **Molecular chat & interaction** — converse with a molecule; select atoms, bonds,\n or fragments and edit them in natural language.\n- **Structure-aware editing** — auditable, graph-level molecular edits.\n- **Retrosynthesis** — LLM-native synthesis planning over explicit structures.\n- **Literature reading & structure parsing** — extracting structures from papers\n and patents, including optical chemical structure recognition (OCSR).\n\nMoleCode is the open representation layer underneath these products — making\nmolecular structure explicit, editable, and auditable for LLMs.\n\n🌐 Learn more at **[atomflow-ai.com](https://atomflow-ai.com/)**.\n\n## 📚 Citation\n\nIf you use MoleCode in your research, please cite the MoleCode technical report:\n\n```bibtex\n@article{yan2026molecode,\n title={MoleCode unlocks structural intelligence in large language models},\n author={Yan, Zhiyuan and Liu, Chen and Zhao, Boxuan and Lin, Kaiqing and Zhao, Jixiang and Wang, Yimi and Lv, Liuzhenghao and Li, Hao and Zhang, Shanzhuo and Yuan, Li and others},\n journal={arXiv preprint arXiv:2605.16480},\n year={2026}\n}\n```\n\n## License\n\n[MIT](LICENSE) © 2026 AtomFlow-AI\n"}, "2ff74351d23eb4d5596afb8279d2e7d40c43e746": {"t": 1785771618.179827, "n": 11973, "h": "019c7f61d2e1f579", "c": "<div align=\"center\">\n\n# 🧬 MoleCode\n\n### An LLM-native, graph-explicit molecular language\n\n**From molecular strings to structural code: enabling LLMs to operate on chemistry directly.**\n\n*Stop making language models reconstruct molecular structure from cryptic strings — let them read, write, and edit structure directly.*\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)\n[![Powered by RDKit](https://img.shields.io/badge/powered%20by-RDKit-green.svg)](https://www.rdkit.org/)\n\n[![Works with Claude Code](https://img.shields.io/badge/Works%20with-Claude%20Code-d97757.svg)](.claude/skills/molecode/)\n[![Works with Codex](https://img.shields.io/badge/Works%20with-Codex-412991.svg)](AGENTS.md)\n[![Agent Skill](https://img.shields.io/badge/Agent-Skill-blue.svg)](.claude/skills/molecode/SKILL.md)\n\n**English** | [中文](README.zh-CN.md)\n\n<img src=\"docs/assets/overview.png\" alt=\"MoleCode overview\" width=\"100%\">\n\n</div>\n\n---\n\n## What is MoleCode?\n\nA molecule **is** a graph: atoms are nodes, bonds are edges, and chemistry emerges from the topology. Yet large language models are almost always fed molecules as *linear strings* like SMILES, where the graph is **implicit** — connectivity is positional, branches are syntactic, and rings hide inside index digits. Before an LLM can do any chemistry, it must first *reconstruct the graph from the syntax*, spending reasoning budget on structural bookkeeping.\n\n**MoleCode makes the structure the language.** Every atom and bond is written as a typed declaration with a persistent identifier, serialized as a [Mermaid](https://mermaid.js.org/) graph. Topology becomes directly readable, editable, and auditable inside the context window — and the format is **deterministically and losslessly inter-convertible with SMILES / MOL via RDKit** (no learned model, no information loss).\n\n```mermaid\ngraph TB\n subgraph chlorophenol[\"para-chlorophenol\"]\n chlorophenol_C_1[C]\n chlorophenol_O_1[OH]\n chlorophenol_C_2[CH]\n chlorophenol_C_3[CH]\n chlorophenol_C_4[C]\n chlorophenol_Cl_1[Cl]\n chlorophenol_C_5[CH]\n chlorophenol_C_6[CH]\n chlorophenol_C_1 === chlorophenol_C_2\n chlorophenol_C_2 --- chlorophenol_C_3\n chlorophenol_C_3 === chlorophenol_C_4\n chlorophenol_C_4 --- chlorophenol_C_5\n chlorophenol_C_5 === chlorophenol_C_6\n chlorophenol_C_6 --- chlorophenol_C_1\n chlorophenol_C_1 --- chlorophenol_O_1\n chlorophenol_C_4 --- chlorophenol_Cl_1\n end\n```\n\n> The same `Subgraph → Node → Edge` grammar covers **small molecules, polymers, and Markush structures** — and extends to reaction mechanisms and multimodal document parsing.\n\n---\n\n## Why it matters\n\n| | SMILES | **MoleCode** |\n| --- | --- | --- |\n| Topology | implicit, positional | **explicit, named nodes & edges** |\n| Atom identity | none | **persistent IDs** (stable across prompt → reasoning → output) |\n| Editing | whole-string rewrite | **local graph op** (add a methyl = 1 node + 1 edge) |\n| Validation | fragile string parsing | **deterministic RDKit round-trip** |\n| Reasoning behavior | memorizes syntax | **generalizes over structure** |\n\nEmpirically (see the [MoleCode paper](#-citation) and [docs/06-why-it-works.md](docs/06-why-it-works.md)):\n\n- **Generalization, not memorization.** SMILES accuracy collapses from ~42% on familiar molecules to ~20% on novel ones; MoleCode holds **~76–80%** across all familiarity tiers.\n- **Cheaper reasoning.** MoleCode has longer *input* but its chain-of-thought grows **sub-linearly** with molecule size (~C^0.52) versus SMILES' super-linear ~C^1.65 — about a **5× lower total token cost** per query.\n- **Scales to big, repetitive objects.** Full-chain SMILES accuracy falls toward **0%** as polymer chains grow; MoleCode stays flat.\n- **Markush understanding** jumps from **38.1% → 84.0%**.\n\n---\n\n## Install\n\n```bash\ngit clone https://github.com/AtomFlow-AI/MoleCode.git\ncd MoleCode\npip install -e . # installs rdkit + networkx\n```\n\n## Quick start\n\n```python\nfrom rdkit import Chem\nfrom molecode import mol_to_mermaid, mermaid_to_mol, mol_to_smiles\n\n# SMILES -> MoleCode graph\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nprint(graph)\n\n# MoleCode graph -> SMILES (lossless round-trip)\nassert mol_to_smiles(mermaid_to_mol(graph)) == Chem.CanonSmiles(\"CC(=O)Oc1ccccc1C(=O)O\")\n```\n\n---\n\n## Works with your coding agent (Claude Code · Codex)\n\nMoleCode ships as a ready-to-use **[Agent Skill](https://docs.claude.com/en/docs/claude-code/skills)**,\nso coding agents can clone this repo and immediately reason over and edit\nmolecules at the explicit-graph level — no extra setup, no MCP server required.\n\n| Agent | How it picks MoleCode up |\n| --- | --- |\n| **Claude Code** | Auto-discovers the skill at [`.claude/skills/molecode/`](.claude/skills/molecode/). Just ask it to understand or edit a molecule. |\n| **Codex** (and other agents) | Reads [`AGENTS.md`](AGENTS.md) at the repo root and uses the bundled CLI; interface metadata in [`agents/openai.yaml`](.claude/skills/molecode/agents/openai.yaml). |\n\nInstead of asking the model to hand-write SMILES — error-prone for anything\nnon-trivial — the skill has it **convert → inspect the named atoms/bonds → edit\nthe graph → validate**, all through one stable CLI:\n\n```bash\npython .claude/skills/molecode/scripts/molecode_convert.py doctor\npython .claude/skills/molecode/scripts/molecode_convert.py smiles-to-molecode \"CCO\" --name Ethanol\npython .claude/skills/molecode/scripts/molecode_convert.py validate --input edited.mmd # formula, counts, round-trip\npython .claude/skills/molecode/scripts/molecode_convert.py molecode-to-smiles --input edited.mmd\n```\n\nThe skill bundles the six conversion forms (SMILES / PSMILES / Markush ↔\nMoleCode) plus `validate`, `compare` (Markush-aware isomorphism) and `doctor`, a\nsyntax reference for hand-editing graphs, and a file-based edit workflow built\nfor large molecules. See [`.claude/skills/molecode/SKILL.md`](.claude/skills/molecode/SKILL.md).\n\n## Three domains, one grammar\n\n### 🧪 Small molecules — [`molecode.molecule`](molecode/molecule)\n\nAtoms are `prefix_Element_Number[Label]` nodes; bonds are `---` (single), `===` (double), `-.-` (triple), with `===|E|`/`===|Z|` and `_R`/`_S` for stereochemistry. → [syntax reference](docs/02-syntax.md)\n\n### 🔗 Polymers — [`molecode.polymer`](molecode/polymer)\n\nThe repeat unit stays **explicit** as a subgraph carrying a symbolic `×n` count, with `TL`/`TR` terminus markers — so the graph does not blow up with chain length. → [polymer docs](docs/03-polymers.md)\n\n```python\nfrom molecode.polymer import polymer_to_mermaid, mermaid_to_psmiles\n\ngraph = polymer_to_mermaid(\"*NCCCCCC(=O)*\", n=8, name=\"Nylon-6\") # PSMILES -> graph\nmermaid_to_psmiles(graph) # -> '*NCCCCCC(=O)*'\n```\n\n### 🧩 Markush structures — [`molecode.markush`](molecode/markush)\n\nVariable R-groups and named substituents become **abbreviation nodes** in curly braces — `{R1}`, `{Boc}`, `{Ar}` — something plain SMILES cannot express. A built-in graph-isomorphism comparator scores predictions up to abbreviation expansion. → [Markush docs](docs/04-markush.md)\n\n```mermaid\ngraph TB\n subgraph Mol[\"molecule name\"]\n Mol_C_1[C]\n Mol_O_1[OH]\n Mol_X_1{Boc}\n Mol_X_2{R1}\n Mol_C_1 --- Mol_O_1\n Mol_C_1 --- Mol_X_1\n end\n```\n\n---\n\n## Run the tasks: understand · generate · edit · reason\n\nMoleCode is a **drop-in representation for any LLM** — feed the grammar as a system prompt, hand the model a graph, and validate its output deterministically. The [`examples/`](examples) folder has runnable scripts for all four task families (they run **offline by default**, printing the exact prompt; set `MOLECODE_API_KEY` to call a model):\n\n```bash\npython examples/01_molecule_roundtrip.py # SMILES <-> graph (lossless)\npython examples/02_polymer_roundtrip.py # polymers with ×n\npython examples/03_markush_roundtrip.py # abbreviation nodes & isomorphism\npython examples/04_understanding.py # count atoms / formula / rings ...\npython examples/05_generation.py # de novo design under constraints\npython examples/06_editing.py # local graph edits (add/del/substitute)\npython examples/07_reasoning.py # reaction-product prediction\n```\n\nThe reusable ingredients:\n\n```python\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT # give this to the LLM as the system prompt\nfrom molecode.molecule import mol_to_mermaid # your molecule -> what the model reads\nfrom molecode.molecule import mermaid_to_mol # model output -> validated RDKit Mol\n```\n\n### Calling an LLM\n\nMoleCode is just a representation, so you can use **any** LLM SDK — the prompts\nare plain strings. For convenience the package also ships a tiny,\ndependency-free, **OpenAI-compatible** client (`molecode.llm.LLMClient`, built on\nstdlib `urllib`). You supply the API key and base URL — nothing is hard-coded, so\nit works with OpenAI, DeepSeek, Azure, Together, vLLM, Ollama, …\n\n```python\nfrom molecode import LLMClient\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT\nfrom molecode.molecule import mol_to_mermaid, mermaid_to_mol\nfrom rdkit import Chem\n\nclient = LLMClient(api_key=\"sk-...\", base_url=\"https://api.openai.com/v1\", model=\"\")\n# (or set MOLECODE_API_KEY / MOLECODE_BASE_URL / MOLECODE_MODEL and call LLMClient())\n\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nreply = client.chat(f\"How many carbons are in this molecule?\\n```mermaid\\n{graph}\\n```\",\n system=MOLECULE_SYSTEM_PROMPT)\nprint(reply)\n```\n\nPrefer the official `openai` SDK? Pass the same prompt strings straight to\n`openai.OpenAI().chat.completions.create(...)` — you don't need `LLMClient` at all.\n\nSee [docs/05-tasks.md](docs/05-tasks.md) for the full task catalog.\n\n| Domain | Understanding | Generation | Editing | Reasoning |\n| --- | :---: | :---: | :---: | :---: |\n| Molecules | ✅ | ✅ | ✅ | ✅ |\n| Polymers | ✅ | ✅ | ✅ | — |\n| Markush | ✅ | — | — | — |\n\n---\n\n## Repository layout\n\n```\nmolecode/ # the library (pip-installable)\n├── molecule/ # small-molecule <-> Mermaid (rdkit_to_mermaid, mermaid_to_rdkit)\n├── polymer/ # polymer <-> Mermaid (polymer_to_mermaid, mermaid_to_psmiles)\n├── markush/ # Markush <-> Mermaid + egl_graph isomorphism + abbreviation_map\n├── prompts/ # LLM system prompts (molecule + markush grammars)\n└── llm.py # optional OpenAI-compatible client (you supply key + base_url)\nexamples/ # 7 runnable demos (round-trips + 4 task families)\ndocs/ # overview, syntax, polymers, markush, tasks, why-it-works\nAGENTS.md # entrypoint for coding agents\n.claude/skills/molecode/ # Agent Skill: SKILL.md + CLI + references (Claude Code / Codex)\n```\n\n---\n\n## Results at a glance\n\n| Generalization & reasoning | Goal-directed design | Scaling | Long molecules | General language |\n| :---: | :---: | :---: | :---: | :---: |\n| ![](docs/assets/results_1_main.png) | ![](docs/assets/results_2_chemistry.png) | ![](docs/assets/results_3_scaling.png) | ![](docs/assets/results_4_long_molecules.png) | ![](docs/assets/results_5_extension.png) |\n\n---\n\n## 📚 Citation\n\nIf you use MoleCode in your research, please cite the MoleCode technical report:\n\n```bibtex\n@article{yan2026molecode,\n title={MoleCode unlocks structural intelligence in large language models},\n author={Yan, Zhiyuan and Liu, Chen and Zhao, Boxuan and Lin, Kaiqing and Zhao, Jixiang and Wang, Yimi and Lv, Liuzhenghao and Li, Hao and Zhang, Shanzhuo and Yuan, Li and others},\n journal={arXiv preprint arXiv:2605.16480},\n year={2026}\n}\n```\n\n## License\n\n[MIT](LICENSE) © 2026 AtomFlow-AI\n"}, "527b9167e82e8e5b42d50bc114ed2065a68eddce": {"t": 1785771622.7588048, "n": 11984, "h": "5a8c3822dac17f7c", "c": "<div align=\"center\">\n\n# 🧬 MoleCode\n\n### An LLM-native, graph-explicit molecular language\n\n**From molecular strings to structural code: enabling LLMs to operate on chemistry directly.**\n\n*Stop making language models reconstruct molecular structure from cryptic strings — let them read, write, and edit structure directly.*\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)\n[![Powered by RDKit](https://img.shields.io/badge/powered%20by-RDKit-green.svg)](https://www.rdkit.org/)\n\n[![Works with Claude Code](https://img.shields.io/badge/Works%20with-Claude%20Code-d97757.svg)](.claude/skills/molecode/)\n[![Works with Codex](https://img.shields.io/badge/Works%20with-Codex-412991.svg)](AGENTS.md)\n[![Agent Skill](https://img.shields.io/badge/Agent-Skill-blue.svg)](.claude/skills/molecode/SKILL.md)\n\n**English** | [中文](README.zh-CN.md)\n\n<img src=\"docs/assets/overview.png\" alt=\"MoleCode overview\" width=\"100%\">\n\n</div>\n\n---\n\n## What is MoleCode?\n\nA molecule **is** a graph: atoms are nodes, bonds are edges, and chemistry emerges from the topology. Yet large language models are almost always fed molecules as *linear strings* like SMILES, where the graph is **implicit** — connectivity is positional, branches are syntactic, and rings hide inside index digits. Before an LLM can do any chemistry, it must first *reconstruct the graph from the syntax*, spending reasoning budget on structural bookkeeping.\n\n**MoleCode makes the structure the language.** Every atom and bond is written as a typed declaration with a persistent identifier, serialized as a [Mermaid](https://mermaid.js.org/) graph. Topology becomes directly readable, editable, and auditable inside the context window — and the format is **deterministically and losslessly inter-convertible with SMILES / MOL via RDKit** (no learned model, no information loss).\n\n```mermaid\ngraph TB\n subgraph chlorophenol[\"para-chlorophenol\"]\n chlorophenol_C_1[C]\n chlorophenol_O_1[OH]\n chlorophenol_C_2[CH]\n chlorophenol_C_3[CH]\n chlorophenol_C_4[C]\n chlorophenol_Cl_1[Cl]\n chlorophenol_C_5[CH]\n chlorophenol_C_6[CH]\n chlorophenol_C_1 === chlorophenol_C_2\n chlorophenol_C_2 --- chlorophenol_C_3\n chlorophenol_C_3 === chlorophenol_C_4\n chlorophenol_C_4 --- chlorophenol_C_5\n chlorophenol_C_5 === chlorophenol_C_6\n chlorophenol_C_6 --- chlorophenol_C_1\n chlorophenol_C_1 --- chlorophenol_O_1\n chlorophenol_C_4 --- chlorophenol_Cl_1\n end\n```\n\n> The same `Subgraph → Node → Edge` grammar covers **small molecules, polymers, and Markush structures** — and extends to reaction mechanisms and multimodal document parsing.\n\n---\n\n## Why it matters\n\n| | SMILES | **MoleCode** |\n| --- | --- | --- |\n| Topology | implicit, positional | **explicit, named nodes & edges** |\n| Atom identity | none | **persistent IDs** (stable across prompt → reasoning → output) |\n| Editing | whole-string rewrite | **local graph op** (add a methyl = 1 node + 1 edge) |\n| Validation | fragile string parsing | **deterministic RDKit round-trip** |\n| Reasoning behavior | memorizes syntax | **generalizes over structure** |\n\nEmpirically (see the [MoleCode paper](#-citation) and [docs/06-why-it-works.md](docs/06-why-it-works.md)):\n\n- **Generalization, not memorization.** SMILES accuracy collapses from ~42% on familiar molecules to ~20% on novel ones; MoleCode holds **~76–80%** across all familiarity tiers.\n- **Cheaper reasoning.** MoleCode has longer *input* but its chain-of-thought grows **sub-linearly** with molecule size (~C^0.52) versus SMILES' super-linear ~C^1.65 — about a **5× lower total token cost** per query.\n- **Scales to big, repetitive objects.** Full-chain SMILES accuracy falls toward **0%** as polymer chains grow; MoleCode stays flat.\n- **Markush understanding** jumps from **38.1% → 84.0%**.\n\n---\n\n## Install\n\n```bash\ngit clone https://github.com/AtomFlow-AI/MoleCode.git\ncd MoleCode\npip install -e . # installs rdkit + networkx\n```\n\n## Quick start\n\n```python\nfrom rdkit import Chem\nfrom molecode import mol_to_mermaid, mermaid_to_mol, mol_to_smiles\n\n# SMILES -> MoleCode graph\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nprint(graph)\n\n# MoleCode graph -> SMILES (lossless round-trip)\nassert mol_to_smiles(mermaid_to_mol(graph)) == Chem.CanonSmiles(\"CC(=O)Oc1ccccc1C(=O)O\")\n```\n\n---\n\n## Works with your coding agent (Claude Code · Codex)\n\nMoleCode ships as a ready-to-use **[Agent Skill](https://docs.claude.com/en/docs/claude-code/skills)**,\nso coding agents can clone this repo and immediately reason over and edit\nmolecules at the explicit-graph level — no extra setup, no MCP server required.\n\n| Agent | How it picks MoleCode up |\n| --- | --- |\n| **Claude Code** | Auto-discovers the skill at [`.claude/skills/molecode/`](.claude/skills/molecode/). Just ask it to understand or edit a molecule. |\n| **Codex** (and other agents) | Reads [`AGENTS.md`](AGENTS.md) at the repo root and uses the bundled CLI; interface metadata in [`agents/openai.yaml`](.claude/skills/molecode/agents/openai.yaml). |\n\nInstead of asking the model to hand-write SMILES — error-prone for anything\nnon-trivial — the skill has it **convert → inspect the named atoms/bonds → edit\nthe graph → validate**, all through one stable CLI:\n\n```bash\npython .claude/skills/molecode/scripts/molecode_convert.py doctor\npython .claude/skills/molecode/scripts/molecode_convert.py smiles-to-molecode \"CCO\" --name Ethanol\npython .claude/skills/molecode/scripts/molecode_convert.py validate --input edited.mmd # formula, counts, round-trip\npython .claude/skills/molecode/scripts/molecode_convert.py molecode-to-smiles --input edited.mmd\n```\n\nThe skill bundles the six conversion forms (SMILES / PSMILES / Markush ↔\nMoleCode) plus `validate`, `compare` (Markush-aware isomorphism) and `doctor`, a\nsyntax reference for hand-editing graphs, and a file-based edit workflow built\nfor large molecules. See [`.claude/skills/molecode/SKILL.md`](.claude/skills/molecode/SKILL.md).\n\n## Three domains, one grammar\n\n### 🧪 Small molecules — [`molecode.molecule`](molecode/molecule)\n\nAtoms are `prefix_Element_Number[Label]` nodes; bonds are `---` (single), `===` (double), `-.-` (triple), with `===|E|`/`===|Z|` and `_R`/`_S` for stereochemistry. → [syntax reference](docs/02-syntax.md)\n\n### 🔗 Polymers — [`molecode.polymer`](molecode/polymer)\n\nThe repeat unit stays **explicit** as a subgraph carrying a symbolic `×n` count, with `TL`/`TR` terminus markers — so the graph does not blow up with chain length. → [polymer docs](docs/03-polymers.md)\n\n```python\nfrom molecode.polymer import polymer_to_mermaid, mermaid_to_psmiles\n\ngraph = polymer_to_mermaid(\"*NCCCCCC(=O)*\", n=8, name=\"Nylon-6\") # PSMILES -> graph\nmermaid_to_psmiles(graph) # -> '*NCCCCCC(=O)*'\n```\n\n### 🧩 Markush structures — [`molecode.markush`](molecode/markush)\n\nVariable R-groups and named substituents become **abbreviation nodes** in curly braces — `{R1}`, `{Boc}`, `{Ar}` — something plain SMILES cannot express. A built-in graph-isomorphism comparator scores predictions up to abbreviation expansion. → [Markush docs](docs/04-markush.md)\n\n```mermaid\ngraph TB\n subgraph Mol[\"molecule name\"]\n Mol_C_1[C]\n Mol_O_1[OH]\n Mol_X_1{Boc}\n Mol_X_2{R1}\n Mol_C_1 --- Mol_O_1\n Mol_C_1 --- Mol_X_1\n end\n```\n\n---\n\n## Run the tasks: understand · generate · edit · reason\n\nMoleCode is a **drop-in representation for any LLM** — feed the grammar as a system prompt, hand the model a graph, and validate its output deterministically. The [`examples/`](examples) folder has runnable scripts for all four task families (they run **offline by default**, printing the exact prompt; set `MOLECODE_API_KEY` to call a model):\n\n```bash\npython examples/01_molecule_roundtrip.py # SMILES <-> graph (lossless)\npython examples/02_polymer_roundtrip.py # polymers with ×n\npython examples/03_markush_roundtrip.py # abbreviation nodes & isomorphism\npython examples/04_understanding.py # count atoms / formula / rings ...\npython examples/05_generation.py # de novo design under constraints\npython examples/06_editing.py # local graph edits (add/del/substitute)\npython examples/07_reasoning.py # reaction-product prediction\n```\n\nThe reusable ingredients:\n\n```python\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT # give this to the LLM as the system prompt\nfrom molecode.molecule import mol_to_mermaid # your molecule -> what the model reads\nfrom molecode.molecule import mermaid_to_mol # model output -> validated RDKit Mol\n```\n\n### Calling an LLM\n\nMoleCode is just a representation, so you can use **any** LLM SDK — the prompts\nare plain strings. For convenience the package also ships a tiny,\ndependency-free, **OpenAI-compatible** client (`molecode.llm.LLMClient`, built on\nstdlib `urllib`). You supply the API key and base URL — nothing is hard-coded, so\nit works with OpenAI, DeepSeek, Azure, Together, vLLM, Ollama, …\n\n```python\nfrom molecode import LLMClient\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT\nfrom molecode.molecule import mol_to_mermaid, mermaid_to_mol\nfrom rdkit import Chem\n\nclient = LLMClient(api_key=\"sk-...\", base_url=\"https://api.openai.com/v1\", model=\"gpt-4o-mini\")\n# (or set MOLECODE_API_KEY / MOLECODE_BASE_URL / MOLECODE_MODEL and call LLMClient())\n\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nreply = client.chat(f\"How many carbons are in this molecule?\\n```mermaid\\n{graph}\\n```\",\n system=MOLECULE_SYSTEM_PROMPT)\nprint(reply)\n```\n\nPrefer the official `openai` SDK? Pass the same prompt strings straight to\n`openai.OpenAI().chat.completions.create(...)` — you don't need `LLMClient` at all.\n\nSee [docs/05-tasks.md](docs/05-tasks.md) for the full task catalog.\n\n| Domain | Understanding | Generation | Editing | Reasoning |\n| --- | :---: | :---: | :---: | :---: |\n| Molecules | ✅ | ✅ | ✅ | ✅ |\n| Polymers | ✅ | ✅ | ✅ | — |\n| Markush | ✅ | — | — | — |\n\n---\n\n## Repository layout\n\n```\nmolecode/ # the library (pip-installable)\n├── molecule/ # small-molecule <-> Mermaid (rdkit_to_mermaid, mermaid_to_rdkit)\n├── polymer/ # polymer <-> Mermaid (polymer_to_mermaid, mermaid_to_psmiles)\n├── markush/ # Markush <-> Mermaid + egl_graph isomorphism + abbreviation_map\n├── prompts/ # LLM system prompts (molecule + markush grammars)\n└── llm.py # optional OpenAI-compatible client (you supply key + base_url)\nexamples/ # 7 runnable demos (round-trips + 4 task families)\ndocs/ # overview, syntax, polymers, markush, tasks, why-it-works\nAGENTS.md # entrypoint for coding agents\n.claude/skills/molecode/ # Agent Skill: SKILL.md + CLI + references (Claude Code / Codex)\n```\n\n---\n\n## Results at a glance\n\n| Generalization & reasoning | Goal-directed design | Scaling | Long molecules | General language |\n| :---: | :---: | :---: | :---: | :---: |\n| ![](docs/assets/results_1_main.png) | ![](docs/assets/results_2_chemistry.png) | ![](docs/assets/results_3_scaling.png) | ![](docs/assets/results_4_long_molecules.png) | ![](docs/assets/results_5_extension.png) |\n\n---\n\n## 📚 Citation\n\nIf you use MoleCode in your research, please cite the MoleCode technical report:\n\n```bibtex\n@article{yan2026molecode,\n title={MoleCode unlocks structural intelligence in large language models},\n author={Yan, Zhiyuan and Liu, Chen and Zhao, Boxuan and Lin, Kaiqing and Zhao, Jixiang and Wang, Yimi and Lv, Liuzhenghao and Li, Hao and Zhang, Shanzhuo and Yuan, Li and others},\n journal={arXiv preprint arXiv:2605.16480},\n year={2026}\n}\n```\n\n## License\n\n[MIT](LICENSE) © 2026 AtomFlow-AI\n"}, "8bfcd3bfc497869abf39be41ee7df3a0487274f1": {"t": 1785771624.6772091, "n": 11947, "h": "3cb8eb9ad8e69030", "c": "<div align=\"center\">\n\n# 🧬 MoleCode\n\n### An LLM-native, graph-explicit molecular language\n\n**From molecular strings to structural code: enabling LLMs to operate on chemistry directly.**\n\n*Stop making language models reconstruct molecular structure from cryptic strings — let them read, write, and edit structure directly.*\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)\n[![Powered by RDKit](https://img.shields.io/badge/powered%20by-RDKit-green.svg)](https://www.rdkit.org/)\n\n[![Works with Claude Code](https://img.shields.io/badge/Works%20with-Claude%20Code-d97757.svg)](.claude/skills/molecode/)\n[![Works with Codex](https://img.shields.io/badge/Works%20with-Codex-412991.svg)](AGENTS.md)\n[![Agent Skill](https://img.shields.io/badge/Agent-Skill-blue.svg)](.claude/skills/molecode/SKILL.md)\n\n<img src=\"docs/assets/overview.png\" alt=\"MoleCode overview\" width=\"100%\">\n\n</div>\n\n---\n\n## What is MoleCode?\n\nA molecule **is** a graph: atoms are nodes, bonds are edges, and chemistry emerges from the topology. Yet large language models are almost always fed molecules as *linear strings* like SMILES, where the graph is **implicit** — connectivity is positional, branches are syntactic, and rings hide inside index digits. Before an LLM can do any chemistry, it must first *reconstruct the graph from the syntax*, spending reasoning budget on structural bookkeeping.\n\n**MoleCode makes the structure the language.** Every atom and bond is written as a typed declaration with a persistent identifier, serialized as a [Mermaid](https://mermaid.js.org/) graph. Topology becomes directly readable, editable, and auditable inside the context window — and the format is **deterministically and losslessly inter-convertible with SMILES / MOL via RDKit** (no learned model, no information loss).\n\n```mermaid\ngraph TB\n subgraph chlorophenol[\"para-chlorophenol\"]\n chlorophenol_C_1[C]\n chlorophenol_O_1[OH]\n chlorophenol_C_2[CH]\n chlorophenol_C_3[CH]\n chlorophenol_C_4[C]\n chlorophenol_Cl_1[Cl]\n chlorophenol_C_5[CH]\n chlorophenol_C_6[CH]\n chlorophenol_C_1 === chlorophenol_C_2\n chlorophenol_C_2 --- chlorophenol_C_3\n chlorophenol_C_3 === chlorophenol_C_4\n chlorophenol_C_4 --- chlorophenol_C_5\n chlorophenol_C_5 === chlorophenol_C_6\n chlorophenol_C_6 --- chlorophenol_C_1\n chlorophenol_C_1 --- chlorophenol_O_1\n chlorophenol_C_4 --- chlorophenol_Cl_1\n end\n```\n\n> The same `Subgraph → Node → Edge` grammar covers **small molecules, polymers, and Markush structures** — and extends to reaction mechanisms and multimodal document parsing.\n\n---\n\n## Why it matters\n\n| | SMILES | **MoleCode** |\n| --- | --- | --- |\n| Topology | implicit, positional | **explicit, named nodes & edges** |\n| Atom identity | none | **persistent IDs** (stable across prompt → reasoning → output) |\n| Editing | whole-string rewrite | **local graph op** (add a methyl = 1 node + 1 edge) |\n| Validation | fragile string parsing | **deterministic RDKit round-trip** |\n| Reasoning behavior | memorizes syntax | **generalizes over structure** |\n\nEmpirically (see the [MoleCode paper](#-citation) and [docs/06-why-it-works.md](docs/06-why-it-works.md)):\n\n- **Generalization, not memorization.** SMILES accuracy collapses from ~42% on familiar molecules to ~20% on novel ones; MoleCode holds **~76–80%** across all familiarity tiers.\n- **Cheaper reasoning.** MoleCode has longer *input* but its chain-of-thought grows **sub-linearly** with molecule size (~C^0.52) versus SMILES' super-linear ~C^1.65 — about a **5× lower total token cost** per query.\n- **Scales to big, repetitive objects.** Full-chain SMILES accuracy falls toward **0%** as polymer chains grow; MoleCode stays flat.\n- **Markush understanding** jumps from **38.1% → 84.0%**.\n\n---\n\n## Install\n\n```bash\ngit clone https://github.com/AtomFlow-AI/MoleCode.git\ncd MoleCode\npip install -e . # installs rdkit + networkx\n```\n\n## Quick start\n\n```python\nfrom rdkit import Chem\nfrom molecode import mol_to_mermaid, mermaid_to_mol, mol_to_smiles\n\n# SMILES -> MoleCode graph\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nprint(graph)\n\n# MoleCode graph -> SMILES (lossless round-trip)\nassert mol_to_smiles(mermaid_to_mol(graph)) == Chem.CanonSmiles(\"CC(=O)Oc1ccccc1C(=O)O\")\n```\n\n---\n\n## Works with your coding agent (Claude Code · Codex)\n\nMoleCode ships as a ready-to-use **[Agent Skill](https://docs.claude.com/en/docs/claude-code/skills)**,\nso coding agents can clone this repo and immediately reason over and edit\nmolecules at the explicit-graph level — no extra setup, no MCP server required.\n\n| Agent | How it picks MoleCode up |\n| --- | --- |\n| **Claude Code** | Auto-discovers the skill at [`.claude/skills/molecode/`](.claude/skills/molecode/). Just ask it to understand or edit a molecule. |\n| **Codex** (and other agents) | Reads [`AGENTS.md`](AGENTS.md) at the repo root and uses the bundled CLI; interface metadata in [`agents/openai.yaml`](.claude/skills/molecode/agents/openai.yaml). |\n\nInstead of asking the model to hand-write SMILES — error-prone for anything\nnon-trivial — the skill has it **convert → inspect the named atoms/bonds → edit\nthe graph → validate**, all through one stable CLI:\n\n```bash\npython .claude/skills/molecode/scripts/molecode_convert.py doctor\npython .claude/skills/molecode/scripts/molecode_convert.py smiles-to-molecode \"CCO\" --name Ethanol\npython .claude/skills/molecode/scripts/molecode_convert.py validate --input edited.mmd # formula, counts, round-trip\npython .claude/skills/molecode/scripts/molecode_convert.py molecode-to-smiles --input edited.mmd\n```\n\nThe skill bundles the six conversion forms (SMILES / PSMILES / Markush ↔\nMoleCode) plus `validate`, `compare` (Markush-aware isomorphism) and `doctor`, a\nsyntax reference for hand-editing graphs, and a file-based edit workflow built\nfor large molecules. See [`.claude/skills/molecode/SKILL.md`](.claude/skills/molecode/SKILL.md).\n\n## Three domains, one grammar\n\n### 🧪 Small molecules — [`molecode.molecule`](molecode/molecule)\n\nAtoms are `prefix_Element_Number[Label]` nodes; bonds are `---` (single), `===` (double), `-.-` (triple), with `===|E|`/`===|Z|` and `_R`/`_S` for stereochemistry. → [syntax reference](docs/02-syntax.md)\n\n### 🔗 Polymers — [`molecode.polymer`](molecode/polymer)\n\nThe repeat unit stays **explicit** as a subgraph carrying a symbolic `×n` count, with `TL`/`TR` terminus markers — so the graph does not blow up with chain length. → [polymer docs](docs/03-polymers.md)\n\n```python\nfrom molecode.polymer import polymer_to_mermaid, mermaid_to_psmiles\n\ngraph = polymer_to_mermaid(\"*NCCCCCC(=O)*\", n=8, name=\"Nylon-6\") # PSMILES -> graph\nmermaid_to_psmiles(graph) # -> '*NCCCCCC(=O)*'\n```\n\n### 🧩 Markush structures — [`molecode.markush`](molecode/markush)\n\nVariable R-groups and named substituents become **abbreviation nodes** in curly braces — `{R1}`, `{Boc}`, `{Ar}` — something plain SMILES cannot express. A built-in graph-isomorphism comparator scores predictions up to abbreviation expansion. → [Markush docs](docs/04-markush.md)\n\n```mermaid\ngraph TB\n subgraph Mol[\"molecule name\"]\n Mol_C_1[C]\n Mol_O_1[OH]\n Mol_X_1{Boc}\n Mol_X_2{R1}\n Mol_C_1 --- Mol_O_1\n Mol_C_1 --- Mol_X_1\n end\n```\n\n---\n\n## Run the tasks: understand · generate · edit · reason\n\nMoleCode is a **drop-in representation for any LLM** — feed the grammar as a system prompt, hand the model a graph, and validate its output deterministically. The [`examples/`](examples) folder has runnable scripts for all four task families (they run **offline by default**, printing the exact prompt; set `MOLECODE_API_KEY` to call a model):\n\n```bash\npython examples/01_molecule_roundtrip.py # SMILES <-> graph (lossless)\npython examples/02_polymer_roundtrip.py # polymers with ×n\npython examples/03_markush_roundtrip.py # abbreviation nodes & isomorphism\npython examples/04_understanding.py # count atoms / formula / rings ...\npython examples/05_generation.py # de novo design under constraints\npython examples/06_editing.py # local graph edits (add/del/substitute)\npython examples/07_reasoning.py # reaction-product prediction\n```\n\nThe reusable ingredients:\n\n```python\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT # give this to the LLM as the system prompt\nfrom molecode.molecule import mol_to_mermaid # your molecule -> what the model reads\nfrom molecode.molecule import mermaid_to_mol # model output -> validated RDKit Mol\n```\n\n### Calling an LLM\n\nMoleCode is just a representation, so you can use **any** LLM SDK — the prompts\nare plain strings. For convenience the package also ships a tiny,\ndependency-free, **OpenAI-compatible** client (`molecode.llm.LLMClient`, built on\nstdlib `urllib`). You supply the API key and base URL — nothing is hard-coded, so\nit works with OpenAI, DeepSeek, Azure, Together, vLLM, Ollama, …\n\n```python\nfrom molecode import LLMClient\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT\nfrom molecode.molecule import mol_to_mermaid, mermaid_to_mol\nfrom rdkit import Chem\n\nclient = LLMClient(api_key=\"sk-...\", base_url=\"https://api.openai.com/v1\", model=\"gpt-4o-mini\")\n# (or set MOLECODE_API_KEY / MOLECODE_BASE_URL / MOLECODE_MODEL and call LLMClient())\n\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nreply = client.chat(f\"How many carbons are in this molecule?\\n```mermaid\\n{graph}\\n```\",\n system=MOLECULE_SYSTEM_PROMPT)\nprint(reply)\n```\n\nPrefer the official `openai` SDK? Pass the same prompt strings straight to\n`openai.OpenAI().chat.completions.create(...)` — you don't need `LLMClient` at all.\n\nSee [docs/05-tasks.md](docs/05-tasks.md) for the full task catalog.\n\n| Domain | Understanding | Generation | Editing | Reasoning |\n| --- | :---: | :---: | :---: | :---: |\n| Molecules | ✅ | ✅ | ✅ | ✅ |\n| Polymers | ✅ | ✅ | ✅ | — |\n| Markush | ✅ | — | — | — |\n\n---\n\n## Repository layout\n\n```\nmolecode/ # the library (pip-installable)\n├── molecule/ # small-molecule <-> Mermaid (rdkit_to_mermaid, mermaid_to_rdkit)\n├── polymer/ # polymer <-> Mermaid (polymer_to_mermaid, mermaid_to_psmiles)\n├── markush/ # Markush <-> Mermaid + egl_graph isomorphism + abbreviation_map\n├── prompts/ # LLM system prompts (molecule + markush grammars)\n└── llm.py # optional OpenAI-compatible client (you supply key + base_url)\nexamples/ # 7 runnable demos (round-trips + 4 task families)\ndocs/ # overview, syntax, polymers, markush, tasks, why-it-works\nAGENTS.md # entrypoint for coding agents\n.claude/skills/molecode/ # Agent Skill: SKILL.md + CLI + references (Claude Code / Codex)\n```\n\n---\n\n## Results at a glance\n\n| Generalization & reasoning | Goal-directed design | Scaling | Long molecules | General language |\n| :---: | :---: | :---: | :---: | :---: |\n| ![](docs/assets/results_1_main.png) | ![](docs/assets/results_2_chemistry.png) | ![](docs/assets/results_3_scaling.png) | ![](docs/assets/results_4_long_molecules.png) | ![](docs/assets/results_5_extension.png) |\n\n---\n\n## 📚 Citation\n\nIf you use MoleCode in your research, please cite the MoleCode technical report:\n\n```bibtex\n@article{yan2026molecode,\n title={MoleCode unlocks structural intelligence in large language models},\n author={Yan, Zhiyuan and Liu, Chen and Zhao, Boxuan and Lin, Kaiqing and Zhao, Jixiang and Wang, Yimi and Lv, Liuzhenghao and Li, Hao and Zhang, Shanzhuo and Yuan, Li and others},\n journal={arXiv preprint arXiv:2605.16480},\n year={2026}\n}\n```\n\n## License\n\n[MIT](LICENSE) © 2026 AtomFlow-AI\n"}, "5e1bf177d3357caa715466d12a00463fe27b7189": {"t": 1785771627.3306477, "n": 10923, "h": "ebc360fab66c70c1", "c": "<div align=\"center\">\n\n# 🧬 MoleCode\n\n### An LLM-native, graph-explicit molecular language\n\n**From molecular strings to structural code: enabling LLMs to operate on chemistry directly.**\n\n*Stop making language models reconstruct molecular structure from cryptic strings — let them read, write, and edit structure directly.*\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)\n[![Powered by RDKit](https://img.shields.io/badge/powered%20by-RDKit-green.svg)](https://www.rdkit.org/)\n\n<img src=\"docs/assets/overview.png\" alt=\"MoleCode overview\" width=\"100%\">\n\n</div>\n\n---\n\n## What is MoleCode?\n\nA molecule **is** a graph: atoms are nodes, bonds are edges, and chemistry emerges from the topology. Yet large language models are almost always fed molecules as *linear strings* like SMILES, where the graph is **implicit** — connectivity is positional, branches are syntactic, and rings hide inside index digits. Before an LLM can do any chemistry, it must first *reconstruct the graph from the syntax*, spending reasoning budget on structural bookkeeping.\n\n**MoleCode makes the structure the language.** Every atom and bond is written as a typed declaration with a persistent identifier, serialized as a [Mermaid](https://mermaid.js.org/) graph. Topology becomes directly readable, editable, and auditable inside the context window — and the format is **deterministically and losslessly inter-convertible with SMILES / MOL via RDKit** (no learned model, no information loss).\n\n```mermaid\ngraph TB\n subgraph chlorophenol[\"para-chlorophenol\"]\n chlorophenol_C_1[C]\n chlorophenol_O_1[OH]\n chlorophenol_C_2[CH]\n chlorophenol_C_3[CH]\n chlorophenol_C_4[C]\n chlorophenol_Cl_1[Cl]\n chlorophenol_C_5[CH]\n chlorophenol_C_6[CH]\n chlorophenol_C_1 === chlorophenol_C_2\n chlorophenol_C_2 --- chlorophenol_C_3\n chlorophenol_C_3 === chlorophenol_C_4\n chlorophenol_C_4 --- chlorophenol_C_5\n chlorophenol_C_5 === chlorophenol_C_6\n chlorophenol_C_6 --- chlorophenol_C_1\n chlorophenol_C_1 --- chlorophenol_O_1\n chlorophenol_C_4 --- chlorophenol_Cl_1\n end\n```\n\n> The same `Subgraph → Node → Edge` grammar covers **small molecules, polymers, and Markush structures** — and extends to reaction mechanisms and multimodal document parsing.\n\n---\n\n## Why it matters\n\n| | SMILES | **MoleCode** |\n| --- | --- | --- |\n| Topology | implicit, positional | **explicit, named nodes & edges** |\n| Atom identity | none | **persistent IDs** (stable across prompt → reasoning → output) |\n| Editing | whole-string rewrite | **local graph op** (add a methyl = 1 node + 1 edge) |\n| Validation | fragile string parsing | **deterministic RDKit round-trip** |\n| Reasoning behavior | memorizes syntax | **generalizes over structure** |\n\nEmpirically (see the [MoleCode paper](#-citation) and [docs/06-why-it-works.md](docs/06-why-it-works.md)):\n\n- **Generalization, not memorization.** SMILES accuracy collapses from ~42% on familiar molecules to ~20% on novel ones; MoleCode holds **~76–80%** across all familiarity tiers.\n- **Cheaper reasoning.** MoleCode has longer *input* but its chain-of-thought grows **sub-linearly** with molecule size (~C^0.52) versus SMILES' super-linear ~C^1.65 — about a **5× lower total token cost** per query.\n- **Scales to big, repetitive objects.** Full-chain SMILES accuracy falls toward **0%** as polymer chains grow; MoleCode stays flat.\n- **Markush understanding** jumps from **38.1% → 84.0%**.\n\n---\n\n## Install\n\n```bash\ngit clone https://github.com/AtomFlow-AI/MoleCode.git\ncd MoleCode\npip install -e . # installs rdkit + networkx\n```\n\n## Quick start\n\n```python\nfrom rdkit import Chem\nfrom molecode import mol_to_mermaid, mermaid_to_mol, mol_to_smiles\n\n# SMILES -> MoleCode graph\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nprint(graph)\n\n# MoleCode graph -> SMILES (lossless round-trip)\nassert mol_to_smiles(mermaid_to_mol(graph)) == Chem.CanonSmiles(\"CC(=O)Oc1ccccc1C(=O)O\")\n```\n\n---\n\n## Three domains, one grammar\n\n### 🧪 Small molecules — [`molecode.molecule`](molecode/molecule)\n\nAtoms are `prefix_Element_Number[Label]` nodes; bonds are `---` (single), `===` (double), `-.-` (triple), with `===|E|`/`===|Z|` and `_R`/`_S` for stereochemistry. → [syntax reference](docs/02-syntax.md)\n\n### 🔗 Polymers — [`molecode.polymer`](molecode/polymer)\n\nThe repeat unit stays **explicit** as a subgraph carrying a symbolic `×n` count, with `TL`/`TR` terminus markers — so the graph does not blow up with chain length. → [polymer docs](docs/03-polymers.md)\n\n```python\nfrom molecode.polymer import polymer_to_mermaid, mermaid_to_psmiles\n\ngraph = polymer_to_mermaid(\"*NCCCCCC(=O)*\", n=8, name=\"Nylon-6\") # PSMILES -> graph\nmermaid_to_psmiles(graph) # -> '*NCCCCCC(=O)*'\n```\n\n### 🧩 Markush structures — [`molecode.markush`](molecode/markush)\n\nVariable R-groups and named substituents become **abbreviation nodes** in curly braces — `{R1}`, `{Boc}`, `{Ar}` — something plain SMILES cannot express. A built-in graph-isomorphism comparator scores predictions up to abbreviation expansion. → [Markush docs](docs/04-markush.md)\n\n```mermaid\ngraph TB\n subgraph Mol[\"molecule name\"]\n Mol_C_1[C]\n Mol_O_1[OH]\n Mol_X_1{Boc}\n Mol_X_2{R1}\n Mol_C_1 --- Mol_O_1\n Mol_C_1 --- Mol_X_1\n end\n```\n\n---\n\n## Run the tasks: understand · generate · edit · reason\n\nMoleCode is a **drop-in representation for any LLM** — feed the grammar as a system prompt, hand the model a graph, and validate its output deterministically. The [`examples/`](examples) folder has runnable scripts for all four task families (they run **offline by default**, printing the exact prompt; set `MOLECODE_API_KEY` to call a model):\n\n```bash\npython examples/01_molecule_roundtrip.py # SMILES <-> graph (lossless)\npython examples/02_polymer_roundtrip.py # polymers with ×n\npython examples/03_markush_roundtrip.py # abbreviation nodes & isomorphism\npython examples/04_understanding.py # count atoms / formula / rings ...\npython examples/05_generation.py # de novo design under constraints\npython examples/06_editing.py # local graph edits (add/del/substitute)\npython examples/07_reasoning.py # reaction-product prediction\n```\n\nThe reusable ingredients:\n\n```python\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT # give this to the LLM as the system prompt\nfrom molecode.molecule import mol_to_mermaid # your molecule -> what the model reads\nfrom molecode.molecule import mermaid_to_mol # model output -> validated RDKit Mol\n```\n\n### Calling an LLM\n\nMoleCode is just a representation, so you can use **any** LLM SDK — the prompts\nare plain strings. For convenience the package also ships a tiny,\ndependency-free, **OpenAI-compatible** client (`molecode.llm.LLMClient`, built on\nstdlib `urllib`). You supply the API key and base URL — nothing is hard-coded, so\nit works with OpenAI, DeepSeek, Azure, Together, vLLM, Ollama, …\n\n```python\nfrom molecode import LLMClient\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT\nfrom molecode.molecule import mol_to_mermaid, mermaid_to_mol\nfrom rdkit import Chem\n\nclient = LLMClient(api_key=\"sk-...\", base_url=\"https://api.openai.com/v1\", model=\"gpt-4o-mini\")\n# (or set MOLECODE_API_KEY / MOLECODE_BASE_URL / MOLECODE_MODEL and call LLMClient())\n\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nreply = client.chat(f\"How many carbons are in this molecule?\\n```mermaid\\n{graph}\\n```\",\n system=MOLECULE_SYSTEM_PROMPT)\nprint(reply)\n```\n\nPrefer the official `openai` SDK? Pass the same prompt strings straight to\n`openai.OpenAI().chat.completions.create(...)` — you don't need `LLMClient` at all.\n\nSee [docs/05-tasks.md](docs/05-tasks.md) for the full task catalog.\n\n| Domain | Understanding | Generation | Editing | Reasoning |\n| --- | :---: | :---: | :---: | :---: |\n| Molecules | ✅ | ✅ | ✅ | ✅ |\n| Polymers | ✅ | ✅ | ✅ | — |\n| Markush | ✅ | — | — | — |\n\n---\n\n## Use with coding agents (Claude Code · Codex)\n\nMoleCode ships as a ready-to-use **Agent Skill** so a coding agent can grab this\nrepo and immediately understand and edit molecules at the graph level:\n\n- **Claude Code** auto-discovers the skill at [`.claude/skills/molecode/`](.claude/skills/molecode/) —\n just ask it to understand or edit a molecule.\n- **Codex / other agents** read [`AGENTS.md`](AGENTS.md) and use the bundled CLI.\n\n```bash\npython .claude/skills/molecode/scripts/molecode_convert.py doctor\npython .claude/skills/molecode/scripts/molecode_convert.py smiles-to-molecode \"CCO\" --name Ethanol\npython .claude/skills/molecode/scripts/molecode_convert.py validate --input edited.mmd\n```\n\nThe skill bundles a stable CLI (the six conversion forms + `validate`/`compare`/\n`doctor`), a syntax reference for hand-editing graphs, and a file-based edit\nworkflow — see [`.claude/skills/molecode/SKILL.md`](.claude/skills/molecode/SKILL.md).\n\n## Repository layout\n\n```\nmolecode/ # the library (pip-installable)\n├── molecule/ # small-molecule <-> Mermaid (rdkit_to_mermaid, mermaid_to_rdkit)\n├── polymer/ # polymer <-> Mermaid (polymer_to_mermaid, mermaid_to_psmiles)\n├── markush/ # Markush <-> Mermaid + egl_graph isomorphism + abbreviation_map\n├── prompts/ # LLM system prompts (molecule + markush grammars)\n└── llm.py # optional OpenAI-compatible client (you supply key + base_url)\nexamples/ # 7 runnable demos (round-trips + 4 task families)\ndocs/ # overview, syntax, polymers, markush, tasks, why-it-works\nAGENTS.md # entrypoint for coding agents\n.claude/skills/molecode/ # Agent Skill: SKILL.md + CLI + references (Claude Code / Codex)\n```\n\n---\n\n## Results at a glance\n\n| Generalization & reasoning | Goal-directed design | Scaling | Long molecules | General language |\n| :---: | :---: | :---: | :---: | :---: |\n| ![](docs/assets/results_1_main.png) | ![](docs/assets/results_2_chemistry.png) | ![](docs/assets/results_3_scaling.png) | ![](docs/assets/results_4_long_molecules.png) | ![](docs/assets/results_5_extension.png) |\n\n---\n\n## 📚 Citation\n\nIf you use MoleCode in your research, please cite the MoleCode technical report:\n\n```bibtex\n@article{yan2026molecode,\n title={MoleCode unlocks structural intelligence in large language models},\n author={Yan, Zhiyuan and Liu, Chen and Zhao, Boxuan and Lin, Kaiqing and Zhao, Jixiang and Wang, Yimi and Lv, Liuzhenghao and Li, Hao and Zhang, Shanzhuo and Yuan, Li and others},\n journal={arXiv preprint arXiv:2605.16480},\n year={2026}\n}\n```\n\n## License\n\n[MIT](LICENSE) © 2026 AtomFlow-AI\n"}, "970d5721ca9ed2f94624e139248bc1ae77f17f67": {"t": 1785771630.6211023, "n": 9830, "h": "fd2104f2fccc85a7", "c": "<div align=\"center\">\n\n# 🧬 MoleCode\n\n### An LLM-native, graph-explicit molecular language\n\n**From molecular strings to structural code: enabling LLMs to operate on chemistry directly.**\n\n*Stop making language models reconstruct molecular structure from cryptic strings — let them read, write, and edit structure directly.*\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)\n[![Powered by RDKit](https://img.shields.io/badge/powered%20by-RDKit-green.svg)](https://www.rdkit.org/)\n\n<img src=\"docs/assets/overview.png\" alt=\"MoleCode overview\" width=\"100%\">\n\n</div>\n\n---\n\n## What is MoleCode?\n\nA molecule **is** a graph: atoms are nodes, bonds are edges, and chemistry emerges from the topology. Yet large language models are almost always fed molecules as *linear strings* like SMILES, where the graph is **implicit** — connectivity is positional, branches are syntactic, and rings hide inside index digits. Before an LLM can do any chemistry, it must first *reconstruct the graph from the syntax*, spending reasoning budget on structural bookkeeping.\n\n**MoleCode makes the structure the language.** Every atom and bond is written as a typed declaration with a persistent identifier, serialized as a [Mermaid](https://mermaid.js.org/) graph. Topology becomes directly readable, editable, and auditable inside the context window — and the format is **deterministically and losslessly inter-convertible with SMILES / MOL via RDKit** (no learned model, no information loss).\n\n```mermaid\ngraph TB\n subgraph chlorophenol[\"para-chlorophenol\"]\n chlorophenol_C_1[C]\n chlorophenol_O_1[OH]\n chlorophenol_C_2[CH]\n chlorophenol_C_3[CH]\n chlorophenol_C_4[C]\n chlorophenol_Cl_1[Cl]\n chlorophenol_C_5[CH]\n chlorophenol_C_6[CH]\n chlorophenol_C_1 === chlorophenol_C_2\n chlorophenol_C_2 --- chlorophenol_C_3\n chlorophenol_C_3 === chlorophenol_C_4\n chlorophenol_C_4 --- chlorophenol_C_5\n chlorophenol_C_5 === chlorophenol_C_6\n chlorophenol_C_6 --- chlorophenol_C_1\n chlorophenol_C_1 --- chlorophenol_O_1\n chlorophenol_C_4 --- chlorophenol_Cl_1\n end\n```\n\n> The same `Subgraph → Node → Edge` grammar covers **small molecules, polymers, and Markush structures** — and extends to reaction mechanisms and multimodal document parsing.\n\n---\n\n## Why it matters\n\n| | SMILES | **MoleCode** |\n| --- | --- | --- |\n| Topology | implicit, positional | **explicit, named nodes & edges** |\n| Atom identity | none | **persistent IDs** (stable across prompt → reasoning → output) |\n| Editing | whole-string rewrite | **local graph op** (add a methyl = 1 node + 1 edge) |\n| Validation | fragile string parsing | **deterministic RDKit round-trip** |\n| Reasoning behavior | memorizes syntax | **generalizes over structure** |\n\nEmpirically (see the [MoleCode paper](#-citation) and [docs/06-why-it-works.md](docs/06-why-it-works.md)):\n\n- **Generalization, not memorization.** SMILES accuracy collapses from ~42% on familiar molecules to ~20% on novel ones; MoleCode holds **~76–80%** across all familiarity tiers.\n- **Cheaper reasoning.** MoleCode has longer *input* but its chain-of-thought grows **sub-linearly** with molecule size (~C^0.52) versus SMILES' super-linear ~C^1.65 — about a **5× lower total token cost** per query.\n- **Scales to big, repetitive objects.** Full-chain SMILES accuracy falls toward **0%** as polymer chains grow; MoleCode stays flat.\n- **Markush understanding** jumps from **38.1% → 84.0%**.\n\n---\n\n## Install\n\n```bash\ngit clone https://github.com/AtomFlow-AI/MoleCode.git\ncd MoleCode\npip install -e . # installs rdkit + networkx\n```\n\n## Quick start\n\n```python\nfrom rdkit import Chem\nfrom molecode import mol_to_mermaid, mermaid_to_mol, mol_to_smiles\n\n# SMILES -> MoleCode graph\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nprint(graph)\n\n# MoleCode graph -> SMILES (lossless round-trip)\nassert mol_to_smiles(mermaid_to_mol(graph)) == Chem.CanonSmiles(\"CC(=O)Oc1ccccc1C(=O)O\")\n```\n\n---\n\n## Three domains, one grammar\n\n### 🧪 Small molecules — [`molecode.molecule`](molecode/molecule)\n\nAtoms are `prefix_Element_Number[Label]` nodes; bonds are `---` (single), `===` (double), `-.-` (triple), with `===|E|`/`===|Z|` and `_R`/`_S` for stereochemistry. → [syntax reference](docs/02-syntax.md)\n\n### 🔗 Polymers — [`molecode.polymer`](molecode/polymer)\n\nThe repeat unit stays **explicit** as a subgraph carrying a symbolic `×n` count, with `TL`/`TR` terminus markers — so the graph does not blow up with chain length. → [polymer docs](docs/03-polymers.md)\n\n```python\nfrom molecode.polymer import polymer_to_mermaid, mermaid_to_psmiles\n\ngraph = polymer_to_mermaid(\"*NCCCCCC(=O)*\", n=8, name=\"Nylon-6\") # PSMILES -> graph\nmermaid_to_psmiles(graph) # -> '*NCCCCCC(=O)*'\n```\n\n### 🧩 Markush structures — [`molecode.markush`](molecode/markush)\n\nVariable R-groups and named substituents become **abbreviation nodes** in curly braces — `{R1}`, `{Boc}`, `{Ar}` — something plain SMILES cannot express. A built-in graph-isomorphism comparator scores predictions up to abbreviation expansion. → [Markush docs](docs/04-markush.md)\n\n```mermaid\ngraph TB\n subgraph Mol[\"molecule name\"]\n Mol_C_1[C]\n Mol_O_1[OH]\n Mol_X_1{Boc}\n Mol_X_2{R1}\n Mol_C_1 --- Mol_O_1\n Mol_C_1 --- Mol_X_1\n end\n```\n\n---\n\n## Run the tasks: understand · generate · edit · reason\n\nMoleCode is a **drop-in representation for any LLM** — feed the grammar as a system prompt, hand the model a graph, and validate its output deterministically. The [`examples/`](examples) folder has runnable scripts for all four task families (they run **offline by default**, printing the exact prompt; set `MOLECODE_API_KEY` to call a model):\n\n```bash\npython examples/01_molecule_roundtrip.py # SMILES <-> graph (lossless)\npython examples/02_polymer_roundtrip.py # polymers with ×n\npython examples/03_markush_roundtrip.py # abbreviation nodes & isomorphism\npython examples/04_understanding.py # count atoms / formula / rings ...\npython examples/05_generation.py # de novo design under constraints\npython examples/06_editing.py # local graph edits (add/del/substitute)\npython examples/07_reasoning.py # reaction-product prediction\n```\n\nThe reusable ingredients:\n\n```python\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT # give this to the LLM as the system prompt\nfrom molecode.molecule import mol_to_mermaid # your molecule -> what the model reads\nfrom molecode.molecule import mermaid_to_mol # model output -> validated RDKit Mol\n```\n\n### Calling an LLM\n\nMoleCode is just a representation, so you can use **any** LLM SDK — the prompts\nare plain strings. For convenience the package also ships a tiny,\ndependency-free, **OpenAI-compatible** client (`molecode.llm.LLMClient`, built on\nstdlib `urllib`). You supply the API key and base URL — nothing is hard-coded, so\nit works with OpenAI, DeepSeek, Azure, Together, vLLM, Ollama, …\n\n```python\nfrom molecode import LLMClient\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT\nfrom molecode.molecule import mol_to_mermaid, mermaid_to_mol\nfrom rdkit import Chem\n\nclient = LLMClient(api_key=\"sk-...\", base_url=\"https://api.openai.com/v1\", model=\"gpt-4o-mini\")\n# (or set MOLECODE_API_KEY / MOLECODE_BASE_URL / MOLECODE_MODEL and call LLMClient())\n\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nreply = client.chat(f\"How many carbons are in this molecule?\\n```mermaid\\n{graph}\\n```\",\n system=MOLECULE_SYSTEM_PROMPT)\nprint(reply)\n```\n\nPrefer the official `openai` SDK? Pass the same prompt strings straight to\n`openai.OpenAI().chat.completions.create(...)` — you don't need `LLMClient` at all.\n\nSee [docs/05-tasks.md](docs/05-tasks.md) for the full task catalog.\n\n| Domain | Understanding | Generation | Editing | Reasoning |\n| --- | :---: | :---: | :---: | :---: |\n| Molecules | ✅ | ✅ | ✅ | ✅ |\n| Polymers | ✅ | ✅ | ✅ | — |\n| Markush | ✅ | — | — | — |\n\n---\n\n## Repository layout\n\n```\nmolecode/ # the library (pip-installable)\n├── molecule/ # small-molecule <-> Mermaid (rdkit_to_mermaid, mermaid_to_rdkit)\n├── polymer/ # polymer <-> Mermaid (polymer_to_mermaid, mermaid_to_psmiles)\n├── markush/ # Markush <-> Mermaid + egl_graph isomorphism + abbreviation_map\n├── prompts/ # LLM system prompts (molecule + markush grammars)\n└── llm.py # optional OpenAI-compatible client (you supply key + base_url)\nexamples/ # 7 runnable demos (round-trips + 4 task families)\ndocs/ # overview, syntax, polymers, markush, tasks, why-it-works\n```\n\n---\n\n## Results at a glance\n\n| Generalization & reasoning | Goal-directed design | Scaling | Long molecules | General language |\n| :---: | :---: | :---: | :---: | :---: |\n| ![](docs/assets/results_1_main.png) | ![](docs/assets/results_2_chemistry.png) | ![](docs/assets/results_3_scaling.png) | ![](docs/assets/results_4_long_molecules.png) | ![](docs/assets/results_5_extension.png) |\n\n---\n\n## 📚 Citation\n\nIf you use MoleCode in your research, please cite the MoleCode technical report:\n\n```bibtex\n@article{yan2026molecode,\n title={MoleCode unlocks structural intelligence in large language models},\n author={Yan, Zhiyuan and Liu, Chen and Zhao, Boxuan and Lin, Kaiqing and Zhao, Jixiang and Wang, Yimi and Lv, Liuzhenghao and Li, Hao and Zhang, Shanzhuo and Yuan, Li and others},\n journal={arXiv preprint arXiv:2605.16480},\n year={2026}\n}\n```\n\n## License\n\n[MIT](LICENSE) © 2026 AtomFlow-AI\n"}, "2f04d49fed9ff7a32b0de59c372998295748fd63": {"t": 1785771632.867211, "n": 8486, "h": "9b1945a4806db16e", "c": "<div align=\"center\">\n\n# 🧬 MoleCode\n\n### An LLM-native, graph-explicit molecular language\n\n*Stop making language models reconstruct molecular structure from cryptic strings — let them read, write, and edit structure directly.*\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/)\n[![Powered by RDKit](https://img.shields.io/badge/powered%20by-RDKit-green.svg)](https://www.rdkit.org/)\n\n<img src=\"docs/assets/overview.png\" alt=\"MoleCode overview\" width=\"100%\">\n\n</div>\n\n---\n\n## What is MoleCode?\n\nA molecule **is** a graph: atoms are nodes, bonds are edges, and chemistry emerges from the topology. Yet large language models are almost always fed molecules as *linear strings* like SMILES, where the graph is **implicit** — connectivity is positional, branches are syntactic, and rings hide inside index digits. Before an LLM can do any chemistry, it must first *reconstruct the graph from the syntax*, spending reasoning budget on structural bookkeeping.\n\n**MoleCode makes the structure the language.** Every atom and bond is written as a typed declaration with a persistent identifier, serialized as a [Mermaid](https://mermaid.js.org/) graph. Topology becomes directly readable, editable, and auditable inside the context window — and the format is **deterministically and losslessly inter-convertible with SMILES / MOL via RDKit** (no learned model, no information loss).\n\n```mermaid\ngraph TB\n subgraph chlorophenol[\"para-chlorophenol\"]\n chlorophenol_C_1[C]\n chlorophenol_O_1[OH]\n chlorophenol_C_2[CH]\n chlorophenol_C_3[CH]\n chlorophenol_C_4[C]\n chlorophenol_Cl_1[Cl]\n chlorophenol_C_5[CH]\n chlorophenol_C_6[CH]\n chlorophenol_C_1 === chlorophenol_C_2\n chlorophenol_C_2 --- chlorophenol_C_3\n chlorophenol_C_3 === chlorophenol_C_4\n chlorophenol_C_4 --- chlorophenol_C_5\n chlorophenol_C_5 === chlorophenol_C_6\n chlorophenol_C_6 --- chlorophenol_C_1\n chlorophenol_C_1 --- chlorophenol_O_1\n chlorophenol_C_4 --- chlorophenol_Cl_1\n end\n```\n\n> The same `Subgraph → Node → Edge` grammar covers **small molecules, polymers, and Markush structures** — and extends to reaction mechanisms and multimodal document parsing.\n\n---\n\n## Why it matters\n\n| | SMILES | **MoleCode** |\n| --- | --- | --- |\n| Topology | implicit, positional | **explicit, named nodes & edges** |\n| Atom identity | none | **persistent IDs** (stable across prompt → reasoning → output) |\n| Editing | whole-string rewrite | **local graph op** (add a methyl = 1 node + 1 edge) |\n| Validation | fragile string parsing | **deterministic RDKit round-trip** |\n| Reasoning behavior | memorizes syntax | **generalizes over structure** |\n\nEmpirically (see the [MoleCode paper](#-citation) and [docs/06-why-it-works.md](docs/06-why-it-works.md)):\n\n- **Generalization, not memorization.** SMILES accuracy collapses from ~42% on familiar molecules to ~20% on novel ones; MoleCode holds **~76–80%** across all familiarity tiers.\n- **Cheaper reasoning.** MoleCode has longer *input* but its chain-of-thought grows **sub-linearly** with molecule size (~C^0.52) versus SMILES' super-linear ~C^1.65 — about a **5× lower total token cost** per query.\n- **Scales to big, repetitive objects.** Full-chain SMILES accuracy falls toward **0%** as polymer chains grow; MoleCode stays flat.\n- **Markush understanding** jumps from **38.1% → 84.0%**.\n\n---\n\n## Install\n\n```bash\ngit clone https://github.com/AtomFlow-AI/MoleCode.git\ncd MoleCode\npip install -e . # installs rdkit + networkx\n```\n\n## Quick start\n\n```python\nfrom rdkit import Chem\nfrom molecode import mol_to_mermaid, mermaid_to_mol, mol_to_smiles\n\n# SMILES -> MoleCode graph\ngraph = mol_to_mermaid(Chem.MolFromSmiles(\"CC(=O)Oc1ccccc1C(=O)O\"), name=\"Aspirin\")\nprint(graph)\n\n# MoleCode graph -> SMILES (lossless round-trip)\nassert mol_to_smiles(mermaid_to_mol(graph)) == Chem.CanonSmiles(\"CC(=O)Oc1ccccc1C(=O)O\")\n```\n\n---\n\n## Three domains, one grammar\n\n### 🧪 Small molecules — [`molecode.molecule`](molecode/molecule)\n\nAtoms are `prefix_Element_Number[Label]` nodes; bonds are `---` (single), `===` (double), `-.-` (triple), with `===|E|`/`===|Z|` and `_R`/`_S` for stereochemistry. → [syntax reference](docs/02-syntax.md)\n\n### 🔗 Polymers — [`molecode.polymer`](molecode/polymer)\n\nThe repeat unit stays **explicit** as a subgraph carrying a symbolic `×n` count, with `TL`/`TR` terminus markers — so the graph does not blow up with chain length. → [polymer docs](docs/03-polymers.md)\n\n```python\nfrom molecode.polymer import polymer_to_mermaid, mermaid_to_psmiles\n\ngraph = polymer_to_mermaid(\"*NCCCCCC(=O)*\", n=8, name=\"Nylon-6\") # PSMILES -> graph\nmermaid_to_psmiles(graph) # -> '*NCCCCCC(=O)*'\n```\n\n### 🧩 Markush structures — [`molecode.markush`](molecode/markush)\n\nVariable R-groups and named substituents become **abbreviation nodes** in curly braces — `{R1}`, `{Boc}`, `{Ar}` — something plain SMILES cannot express. A built-in graph-isomorphism comparator scores predictions up to abbreviation expansion. → [Markush docs](docs/04-markush.md)\n\n```mermaid\ngraph TB\n subgraph Mol[\"molecule name\"]\n Mol_C_1[C]\n Mol_O_1[OH]\n Mol_X_1{Boc}\n Mol_X_2{R1}\n Mol_C_1 --- Mol_O_1\n Mol_C_1 --- Mol_X_1\n end\n```\n\n---\n\n## Run the tasks: understand · generate · edit · reason\n\nMoleCode is a **drop-in representation for any LLM** — feed the grammar as a system prompt, hand the model a graph, and validate its output deterministically. The [`examples/`](examples) folder has runnable scripts for all four task families (they run **offline by default**, printing the exact prompt; set `MOLECODE_API_KEY` to call a model):\n\n```bash\npython examples/01_molecule_roundtrip.py # SMILES <-> graph (lossless)\npython examples/02_polymer_roundtrip.py # polymers with ×n\npython examples/03_markush_roundtrip.py # abbreviation nodes & isomorphism\npython examples/04_understanding.py # count atoms / formula / rings ...\npython examples/05_generation.py # de novo design under constraints\npython examples/06_editing.py # local graph edits (add/del/substitute)\npython examples/07_reasoning.py # reaction-product prediction\n```\n\nThe reusable ingredients:\n\n```python\nfrom molecode.prompts import MOLECULE_SYSTEM_PROMPT # give this to the LLM as the system prompt\nfrom molecode.molecule import mol_to_mermaid # your molecule -> what the model reads\nfrom molecode.molecule import mermaid_to_mol # model output -> validated RDKit Mol\n```\n\nSee [docs/05-tasks.md](docs/05-tasks.md) for the full task catalog.\n\n| Domain | Understanding | Generation | Editing | Reasoning |\n| --- | :---: | :---: | :---: | :---: |\n| Molecules | ✅ | ✅ | ✅ | ✅ |\n| Polymers | ✅ | ✅ | ✅ | — |\n| Markush | ✅ | — | — | — |\n\n---\n\n## Repository layout\n\n```\nmolecode/ # the library (pip-installable)\n├── molecule/ # small-molecule <-> Mermaid (rdkit_to_mermaid, mermaid_to_rdkit)\n├── polymer/ # polymer <-> Mermaid (polymer_to_mermaid, mermaid_to_psmiles)\n├── markush/ # Markush <-> Mermaid + egl_graph isomorphism + abbreviation_map\n└── prompts/ # LLM system prompts (molecule + markush grammars)\nexamples/ # 7 runnable demos (round-trips + 4 task families)\ndocs/ # overview, syntax, polymers, markush, tasks, why-it-works\n```\n\n---\n\n## Results at a glance\n\n| Generalization & reasoning | Goal-directed design | Scaling | Long molecules | General language |\n| :---: | :---: | :---: | :---: | :---: |\n| ![](docs/assets/results_1_main.png) | ![](docs/assets/results_2_chemistry.png) | ![](docs/assets/results_3_scaling.png) | ![](docs/assets/results_4_long_molecules.png) | ![](docs/assets/results_5_extension.png) |\n\n---\n\n## 📚 Citation\n\nIf you use MoleCode in your research, please cite the MoleCode technical report:\n\n```bibtex\n@article{yan2026molecode,\n title={MoleCode unlocks structural intelligence in large language models},\n author={Yan, Zhiyuan and Liu, Chen and Zhao, Boxuan and Lin, Kaiqing and Zhao, Jixiang and Wang, Yimi and Lv, Liuzhenghao and Li, Hao and Zhang, Shanzhuo and Yuan, Li and others},\n journal={arXiv preprint arXiv:2605.16480},\n year={2026}\n}\n```\n\n## License\n\n[MIT](LICENSE) © 2026 AtomFlow-AI\n"}}}}