| name | codex-refs |
| description | Search academic references for a manuscript and export them to a verified refs CSV, then optionally hand off to cec-sheet. Uses Codex CLI as the search driver, but Codex calls a bundled deterministic PubMed tool (scripts/pubmed_search.py) instead of writing its own E-utilities code â bibliography is fetched live from PubMed so PMIDs are never fabricated. Triggers: "è«ææ€çŽ¢", "æç®æ€çŽ¢", "æèæ€çŽ¢", "ã³ã³ããã¹ãæ€çŽ¢", "åçš¿ã®åŒçšãæ¢ããŠ", "refs.csv", "codex-refs", "/codex-refs". |
Codex Ref Finder (v2 â bundled PubMed tool)
ããã¯äœã
åçš¿ã®äž»åŒµ(claim)ãè£ä»ããåŠè¡æç®ãæ€çŽ¢ããæ€èšŒæžã¿ã®æžèªã€ã CSV (refs.csv) ãäœãã¹ãã«ã
æ€çŽ¢ã®é§åã¯åŸæ¥ã©ãã Codex CLI ã«ä»»ããããCodex ã«ã¯ PubMed ãå©ã Python ãæžãããªãã
代ããã«ãã³ãã«æžã¿ã®æ±ºå®è«çããŒã« scripts/pubmed_search.py ãåŒã°ããã
v1 ããã®å€æŽç¹ïŒãªãå€ãããïŒ
v1 ã¯ãPubMed E-utilities ãå©ã Python ã Codex ã«æ¯åãŒãããæžããããèšèšã§ã以äžã®å£ã«ç¹°ãè¿ãã¶ã€ãã£ãŠããŒã¯ã³ã浪費ããŠãã:
| å£ | v2 ã§ã®è§£æ¶ |
|---|
| PowerShell ã® here-string / ãã€ãå®è¡ã®æ§æåŽ©å£ | ã¹ã¯ãªãããåŒã¶ã ããåŒæ°ã¯åçŽæååã®ã¿ |
ãã¹ã®ã¹ããŒã¹ã»æ¥æ¬èªã§ is not recognized | é
管ãã¹ã¯ãªããã«åºå®ã--cd ã§äœæ¥ dir ãž |
| NCBI 429 ã¬ãŒãå¶éã»ã¿ã€ã ã¢ãŠã | ã¹ã¯ãªããã API ããŒïŒææ°ããã¯ãªãïŒä»¶æ°äºåç¢ºèª |
| XML ããŒã¹å€±æã»æžèªã®åãããŒã | ãã¹ãæžã¿ã® efetch è§£æãæµçš |
| PMID æé ïŒèšæ¶ã§æžããŠå¥è«æãæ¿å
¥ããéå€§äºæ
ïŒ | PMID 㯠esearch/efetch ã®å®ååŸã®ã¿ãCodex ã¯æžããªã |
| æ¯åã¹ã¯ãªãããæžãçŽã reasoning ã³ã¹ã | ãŒãïŒåŒã¶ã ãïŒ |
stdin ç¡éãã³ã°ïŒReading additional input from stdin... ã§åºãŸãïŒ | èµ·åã³ãã³ãã« < /dev/null å¿
é ïŒã¢ãŒã B åç
§ïŒ |
| éå°å埩ïŒå®çªæç®ã§ 20+ åæ€çŽ¢ãåæããçŒããïŒ | å®çªã¯ã¢ãŒã A ã§çãæã¡ïŒæ¢çŽ¢ã¯ã3ã4 åã§åæããšæç€º |
--full-auto éæšå¥šèŠå | ãã©ã°ããå€ãïŒ--sandbox danger-full-access ã®ã¿ïŒ |
æ žå¿ã«ãŒã«ïŒ3ã€ïŒ:
- ã¢ãŒããåããã å®çªã»æ¢ç¥æç®ã¯ Claude ãçãæã¡ïŒã¢ãŒã AïŒãæ¢çŽ¢çãªåãã ã Codex ã« agentic ã«åãïŒã¢ãŒã BïŒãå®çªã agentic ã«æµããšéå°å埩ã§çŒããã
- Codex 㯠agentic ãªæ€çŽ¢è
ã®ãŸãŸïŒã¢ãŒã BïŒã ãããã¯ãæž¡ãã° Codex èªèº«ãã¯ãšãªãèšèšã»å埩ã»éžå¥ããããã ãã3ã4 åã§åæã»å®ç§ã远ããªãã§ãã€ããã
- Codex ã« PubMed E-utilities ã®ã³ãŒããæžãããªãã æ€çŽ¢ã®"èšåš"ã¯å¿
ã
pubmed_search.pyãagentic å埩ãããŠã plumbing ã§ flailing ããªãã
ãã³ãã«ããŒã« scripts/pubmed_search.py
絶察ãã¹ïŒCodex ã«æž¡ããšãã¯å¿
ãããã«ã¯ãªãŒãã§å²ããã¹ããŒã¹ãå«ãïŒ:
Claude Code ããã®ã¹ãã«ã ~/.claude/skills/codex-refs/ ã«ã€ã³ã¹ããŒã«ããå Žåã
ãã¹ã¯èªåã§è§£æ±ºããããæåã§æå®ããå Žå㯠<SKILL_DIR> ãå®éã®ãã¹ã«çœ®ãæãã:
"<SKILL_DIR>\scripts\pubmed_search.py"
äœ¿ãæ¹:
python "<äžèšãã¹>" --query "migraine global burden GBD prevalence disability" --retmax 6 --peek
python "<äžèšãã¹>" --keep 38493795,28919117 \
--note "38493795=GBD2021 ç¥çµçŸæ£ã®äžçè² è·ã®åºæº; 28919117=GBD2016 æç
ç/YLDã®å®çª" \
--out _tmp_refs_01.csv
python "<äžèšãã¹>" --query "..." --out _tmp_refs_01.csv --note "ããŒãã®äžèš"
python "<äžèšãã¹>" --selftest
- çµäºã³ãŒã:
0=æå / 3=ããã0ä»¶ïŒâæ€çŽ¢èªãåºããïŒ/ 4=æ¥ç¶ã»ããŒç°åžž / 1=ãã®ä»ã
- CSV å:
PubMed_ID, Author, Year, Title, Journal, Volume, Issue, Pages, doi, abstract, whats_interesting1..5ã
- DOI/PMID éè€ã¯èªåæé€ãæ¢å PMID ã«ã¯æ¬¡ã®ç©ºã
whats_interesting åãžçç±ã远èšã
API ããŒïŒä»»æã»åŒ·ãæšå¥šïŒ
.secrets/ncbi_api_key.txt ã«ããŒ1è¡ã眮ããš 3â~9 req/s ã«ãªã 429 ãã»ãŒæ¶ãã(.secrets/ 㯠.gitignore æžã¿ãå
±æã»å
¬éããŠãæŒããªã)ãç¡ããŠãåäœããã
ç°å¢å€æ° NCBI_API_KEY ã§ãå¯ïŒãã¡ããåªå
ïŒãååŸã¯ç¡æã»å³æïŒNCBI account â API Key ManagementïŒã
ã¯ãŒã¯ãããŒ
0. ãŸãã¢ãŒããèŠæ¥µããïŒæéèŠïŒ
æç®ã 2 çš®é¡ã«åããåãã«è¡ãæ¹ãå€ããã宿ž¬ã§ãå®çªæç®ã agentic æ¢çŽ¢ããããš codex ããå®ç§ãªèšãåããã远ã£ãŠ 20 å以äžå埩ãåæãã倧éããŒã¯ã³ãçŒãäžæ¹ãçãæã¡ã¯äžçºã§åœããã
| çš®é¡ | äŸ | ã¢ãŒã | æ
åœ |
|---|
| å®çªã»æ¢ç¥ïŒæ¬²ããç©ãåãã£ãŠããïŒ | GBD é çè² è· / Felitti ãªãªãžãã« ACE / Hughes ã¡ã¿ / HIT-6ã»K6ã»ACE 尺床ã®åŠ¥åœæ§ / Hazumi 2025 | A. çãæã¡ | Claude æ¬äœãèšåšãçŽæ¥å©ãïŒcodex äžèŠã»äœããŒã¯ã³ïŒ |
| æ¢çŽ¢çïŒã©ã®è«æãã¯æªç¥ïŒ | ãX ãš Y ã®é¢é£ã瞊æã§èŠãè«æãããã®ç¥èŠã®ææ°ã®èгå¯ç ç©¶ã | B. agentic æ¢çŽ¢ | Codex ã«èªç±ã«æ€çŽ¢ããã |
ã¢ãŒã A: çãæã¡ååŸïŒClaude ãèšåšãçŽæ¥å©ãïŒ
å®çªæç®ã¯å埩äžèŠãClaude ã pubmed_search.py ãçŽæ¥åŒã¶:
python "<SKILL_DIR>\scripts\pubmed_search.py" --query "<çã£ãã¯ãšãª>" --retmax 6 --peek
python "<SKILL_DIR>\scripts\pubmed_search.py" --keep <PMID,...> --note "PMID=çç±" --out refs_YYYYMMDD.csv
ãã㯠codex ã䜿ããªãã®ã§æéã»æå°ããŒã¯ã³ãå®çªã¯ããã§ååã
ã¢ãŒã B: agentic æ¢çŽ¢ïŒCodex ã«å§ããïŒ
æ¢çŽ¢çãªåãã ã Codex ã«åããæé ã¯çžããªãããåæã¯ãã€ããïŒãããªããšéå°å埩ã§çŒããïŒã
0-1. Codex èªèšŒããªãã©ã€ãïŒèµ·ååã«å¿
ããv1 ã¯å€±å¹ã«æ°ã¥ããå
šæ»
ããïŒ:
codex exec --model gpt-5.4-mini --sandbox danger-full-access --skip-git-repo-check --cd "<project>" "PRINT_OK ãšã ãåºåããŠçµäºããŠã" < /dev/null
401 / token_invalidated / refresh_token_reused ãåºãã ! codex login ãäŸé ŒããæååŸã«èµ·åã
0-2. Codex èµ·åã³ãã³ãã®å®åïŒâ
éå»ã«èžãã çœ ãåé¿ïŒ:
timeout 220 codex exec --model gpt-5.4-mini --sandbox danger-full-access --skip-git-repo-check \
--cd "<project>" "<äžã®ããã³ãã>" < /dev/null 2>&1
< /dev/null å¿
é : ä»ããªããš codex ããReading additional input from stdin...ãã§ç¡éãã³ã°ããïŒç¹ã« run_in_background æïŒã
--full-auto ã¯äœ¿ããªãïŒéæšå¥šã--sandbox danger-full-access ã ãã§ããïŒã
| tail ã§ãã€ãããªã: çµäºãŸã§åºåãèŠããã©ã€ãç£èŠäžèœã«ãªããåºåã¯ãã¡ã€ã«ãžã
timeout ãä»ãã: éå°å埩ã®ä¿éºã
- 1 ããã㯠= 1 Codexãåèª
_tmp_refs_NN.csv ã®ã¿ã«æžãïŒå
±æ CSV äžŠåæžèŸŒã¯ããŒã¿æ¶å€±ïŒã
0-3. ããã³ããé圢ïŒagentic ãªè£é + åæã®ãã€ãïŒ:
ããªã㯠PubMed æ€çŽ¢ãšãŒãžã§ã³ãã§ããäžã®ãããã¯ã«æé©ãªåŒçšæç®ãèŠã€ããŠç¢ºå®ããŠãã ããã
## ãããã¯ïŒè£ä»ããã䞻匵ïŒ
ã<èªç¶æã®äž»åŒµã»ãããã¯>ã
## 䜿ããå¯äžã®æ€çŽ¢èšåšïŒPubMed ãå©ãã³ãŒãã¯èªåã§æžããªãïŒ
python "<SKILL_DIR>\scripts\pubmed_search.py" --query "<ä»»æ>" --peek
python "<SKILL_DIR>\scripts\pubmed_search.py" --keep <PMID,...> --note "PMID=çç±" --out _tmp_refs_<NN>.csv
## é²ãæ¹ïŒè£éã§å埩ããããå¿
ãåæãããïŒ
- ãŸãåºãã®ã¯ãšãªã§ --peekãabstract ãèªãã§ relevance ã倿ã
- ãããŠããã°å矩èªã»MeSHã»AND/ORã»å¹Žæå®ãå€ããŠå --peekã
- â
åæã«ãŒã«: **æ€çŽ¢ã¯å€ããŠã 3ã4 åãŸã§**ãå®ç§ãªèšãåãã远ããªãã
代衚çã§åŠ¥åœãª 1ãæ°ä»¶ãèŠã€ãã£ãããããä»¥äžæ¢ããå³ --keep ã§ç¢ºå®ããã
- è¯ãåè£ãç¡ãïŒ0ä»¶(exit 3)ãç¶ããªããæåã®åè£ã確å®ããŠçç±ã«ã代衚çããšèšãã
ä¿åå
_tmp_refs_<NN>.csv ã®ã¿ã確å®ããã PMID ãšçç±ã 1 è¡ã§å ±åã
èšèšã®èŠç¹: æ¢çŽ¢æŠç¥ã¯ Codex ã«å§ããŠéå£ãä¿ã¡ã€ã€ãã3ã4 åã§åæã»å®ç§ã远ããªãã§éå°å埩ãé²ãã
å®çªãããã«æµããªãïŒã¢ãŒã A ã§çãæã€ïŒã
3. ããŒãžïŒClaude æ¬äœãé æ¬¡å®è¡ïŒ
å
šãããå®äºåŸã_tmp_refs_*.csv ãã¡ã€ã³ refs_YYYYMMDD.csv ã« DOI éè€ãã§ãã¯ããªããçµ±åããäžæãã¡ã€ã«ãåé€ãããäžã®ãã³ãã¬ãŒãåç
§ã
4. PMID 空æ¬ãã§ãã¯ïŒâ
ãã«ã·ããŒã·ã§ã³æçµé²å£ïŒ
ããŒãžåŸãã¡ã€ã³ CSV ã® PubMed_ID åã«ç©ºæ¬ãç¡ããæ€æ»ã空æ¬ãããã°æ€çŽ¢/ããŒãžæŒããªã®ã§è£å®ããŠããæ¬¡å·¥çšãžã
ïŒpubmed_search.py çµç±ãªã PMID ã¯å¿
ãå®åšããããæåç·šéãæ··ãã£ãå Žåã«åãããïŒ
æç®éžå®ã®å質ã«ãŒã«
pubmed_search.py ãæžèªã®æ£ç¢ºæ§ãä¿èšŒããã®ã§ãCodex/Claude 㯠æå³çãªéžå¥ã«éäžãã:
- ä»¶æ°ãæå®ããªããã代衚çã»å®çªãã§å質ãæå®ããïŒæ åãã®ç²æªè«æãé¿ããïŒã
- ãšããã³ã¹ã¬ãã«ã¯æèãã倿: åºãèªç¥ãããäºå®âã¡ã¿ã¢ããªã·ã¹/ã·ã¹ãããã£ãã¯ã¬ãã¥ãŒãæ²»ç广âRCTãçšãªç¥èŠâ芳å¯ç ç©¶ãå¯ã
- abstract ã®ã¡ã€ã³ããŒãã䞻匵ãšåèŽããããå¿
ã確èªãããŒã¯ãŒããããã£ãŠããã ãã®è«æã¯é€å€ã
whats_interesting1 ã«ããªããã®è«æãéžãã ãããå¿
ãæžãããïŒéžå®çç±ïŒåŸã®æ€èšŒææïŒã
ããŒãžåŠçãã³ãã¬ãŒãïŒClaude æ¬äœãå®è¡ïŒ
import csv, glob, os
MAIN_CSV = 'refs_YYYYMMDD.csv'
TMP_PATTERN = '_tmp_refs_*.csv'
FIELDNAMES = ['PubMed_ID','Author','Year','Title','Journal','Volume','Issue','Pages','doi','abstract',
'whats_interesting1','whats_interesting2','whats_interesting3','whats_interesting4','whats_interesting5']
WI = FIELDNAMES[10:]
rows, doi_index, pmid_index = [], {}, {}
if os.path.exists(MAIN_CSV):
with open(MAIN_CSV, encoding='utf-8-sig') as f:
for r in csv.DictReader(f):
rows.append(r)
if r.get('doi'): doi_index[r['doi'].lower()] = len(rows)-1
if r.get('PubMed_ID'): pmid_index[r['PubMed_ID']] = len(rows)-1
for tmp in sorted(glob.glob(TMP_PATTERN)):
with open(tmp, encoding='utf-8-sig') as f:
for nr in csv.DictReader(f):
doi = (nr.get('doi') or '').lower(); pmid = nr.get('PubMed_ID','')
idx = doi_index.get(doi) if doi else None
if idx is None and pmid: idx = pmid_index.get(pmid)
if idx is not None:
ex = rows[idx]
for c in WI:
if not ex.get(c):
ex[c] = nr.get('whats_interesting1',''); break
else:
rows.append(nr)
if doi: doi_index[doi] = len(rows)-1
if pmid: pmid_index[pmid] = len(rows)-1
with open(MAIN_CSV, 'w', encoding='utf-8', newline='') as f:
w = csv.DictWriter(f, fieldnames=FIELDNAMES); w.writeheader()
for r in rows: w.writerow({k: r.get(k,'') for k in FIELDNAMES})
for tmp in glob.glob(TMP_PATTERN): os.remove(tmp)
empty = [r for r in rows if not (r.get('PubMed_ID') or '').strip()]
print(f'Total {len(rows)} entries. Empty PMID: {len(empty)}')
CEC è¡šãæ¬²ãããšã
æ¬ã¹ãã«ã®è²¬å㯠refs.csv ã®äœæãŸã§ãäž»åŒµâæ ¹æ âåŒçšã®å¯Ÿå¿è¡šã¯ cec-sheet ã¹ãã«ã«æž¡ã
ïŒPubMed efetch ããæžèªãåååŸã㊠HTML 衚ãçæããæé ãé²ãïŒã
çŽæžãçŠæ¢ã®åŸ¹åº
- API ããŒã SKILL.mdã»ã¹ã¯ãªããã»CSVã»ããã¥ã¡ã³ãã«çŽæžãããªããå¿
ã
.secrets/ïŒgitignore æžïŒãç°å¢å€æ°ã
- PMID ãèšæ¶ã»æšæž¬ã§æžããªããå¿
ã
pubmed_search.py ã®åºåããåãã