Save your AI conversations to Obsidian or Notion. Turn ephemeral chats into a searchable second brain.
Type /stock after any Claude Code response and AI2Stock will:
- Save it as an Atomic Note in your chosen backend — Obsidian (Markdown file), Notion (page), or both
- Auto-classify it: decision / snippet / learning / reference
- File it under the current Claude Code session (folder in Obsidian, sub-page in Notion)
- Auto-link to related notes by shared tags (Obsidian)
- Update a project Map-of-Content (Obsidian)
Append, replace, edit a single section, or delete — all by natural-language commands.
LLM conversations flow past and disappear. AI2Stock turns that flow into stock — a searchable knowledge base you own. Local Markdown (Obsidian), team-shared workspace (Notion), or both in parallel.
/stockslash command for Claude Code- Natural language:
/stock update the spec atom with the current contentetc. - Two backends: Obsidian (Markdown + YAML frontmatter) and Notion (pages tree, sidebar-visible)
- Per-call backend override:
/stock --to=obsidian|notion|all - Per-session folders / sub-pages auto-created
- Auto-classification: decision / snippet / learning / reference
- Same-tag backlinks + Project MOC (Obsidian)
- Symlink-safe paths, atomic writes, TOCTOU race protection (Obsidian)
- Node.js 20+ — nodejs.org
- git
- At least one backend:
- Obsidian Vault — any folder of
.mdfiles (the Obsidian app itself is optional), OR - Notion workspace + Internal Integration token
- Obsidian Vault — any folder of
- Claude Code — to use the
/stockslash command
curl -fsSL https://raw.githubusercontent.com/hyoshi/ai2stock/main/install.sh | bashThe script will:
- Check Node.js 20+, npm, git
npm install -g github:hyoshi/ai2stock(TypeScript builds viaprepare)- Run
ai2stock initto set:- Obsidian Vault path
- Default project name (optional)
- Notion enable + Parent Page ID (optional — see Notion Adapter)
/stockslash command into~/.claude/commands/
/stock is then ready in Claude Code.
npm install -g github:hyoshi/ai2stock
ai2stock initgit clone https://github.com/hyoshi/ai2stock.git
cd ai2stock
npm install
npm run build
npm link
ai2stock init| Symptom | Fix |
|---|---|
ai2stock: command not found |
npm config get prefix's bin/ must be on your PATH |
Node.js 20+ required |
Upgrade Node.js — e.g. nvm or fnm |
EACCES on npm install -g |
Use a Node version manager or set a user-writable npm prefix. Do not use sudo |
/stock not found in Claude Code |
Re-run ai2stock init |
npm install -g github:hyoshi/ai2stockRe-running pulls the latest commit from main.
npm uninstall -g @yoshinaga/ai2stock
rm -f ~/.claude/commands/stock.md
rm -rf ~/.config/ai2stock # config + recent.json (your Vault is not deleted)ai2stock initInteractive prompts:
- Obsidian Vault path — auto-detected if in a common location
- Default project name (optional)
- Enable Notion? — token env + Parent Page ID (see Notion Adapter)
- Install the
/stockslash command to~/.claude/commands/?
In any Claude Code session, after the assistant gives a response you want to keep:
/stock
The previous assistant response is saved to your configured backend(s) (Obsidian by default, Notion too if enabled). Override per call with /stock --to=notion or /stock --to=all.
- Obsidian: open the Vault →
<Vault>/10-Atoms/<session-name>/→ find your note - Notion: open the parent page →
<session-name>sub-page → atom page (visible in the sidebar)
Or use the CLI:
ai2stock list --recent=10
ai2stock list --tag=naming
ai2stock list --project=ai2stock| Command | Action |
|---|---|
/stock |
Save the previous assistant response as a new atom |
/stock 追記 |
Append to the most recent atom |
/stock 置換 |
Replace the most recent atom |
/stock <atom name>を更新 |
Find and replace a specific atom (with confirmation) |
/stock update the spec atom with the current content |
Update an existing atom using the current conversation |
/stock <atom name>削除 |
Delete a specific atom (with confirmation) |
/stock --dry-run |
Preview without saving |
| Command | Action |
|---|---|
ai2stock init |
Set up vault path and slash command |
ai2stock add [content] |
Save a new atom |
ai2stock add --append --id=<id> |
Append to a specific atom |
ai2stock add --replace --id=<id> |
Replace a specific atom |
ai2stock list |
List recent atoms |
ai2stock delete --id=<id> --force |
Delete an atom |
<vault>/
├── 10-Atoms/
│ └── <session-name>/ # auto-detected from Claude Code session
│ └── <id>.md
├── 00-MOC/
│ └── projects/
│ └── <project>.md # auto-generated project index
└── 20-Sessions/ # reserved for future use
Every atom has structured frontmatter:
id: 2026-04-26-1943-example
type: reference
created: 2026-04-26T19:43:00+09:00
ai-generated: true
session_name: AI2Stock
session_dir: /Users/.../my-project
project: ai2stock
tags: [spec, oss]
source: claude-code
confidence: medium~/.config/ai2stock/config.yml:
version: 1
adapters: [obsidian] # add 'notion' to also write to Notion
obsidian:
enabled: true
vault_path: /path/to/your/vault
folders:
atoms: 10-Atoms
sessions: 20-Sessions
moc: 00-MOC
notion: # optional, only if you want Notion
enabled: true
token_env: NOTION_TOKEN
# parent_page_id: 1a2b3c... # OPTIONAL. If absent, session pages are
# created/found at workspace top level.
defaults:
source: claude-code
confidence: medium
primary_adapter: obsidian
write_strategy: primary_only # primary_only | all | sequential
default_project: my-projectAI2Stock organizes atoms in Notion as a 2-level tree:
<session-name page> ← under parent_page_id (parent mode), or workspace top-level (workspace mode)
└── <atom-id page> ← each atom; sidebar visibility
Frontmatter (type / tags / project / session / confidence / etc.) is embedded as a callout block at the top of each atom page.
There are two layouts:
- Parent mode (recommended — Obsidian-equivalent): set
parent_page_idin config to a single Notion page you create once (e.g. "AI2Stock"). AI2Stock auto-creates a session sub-page per Claude Code session under that parent — no per-session manual work, mirroring Obsidian's10-Atoms/<session>/folders. - Workspace-top-level mode (fallback for restricted workspaces): no
parent_page_id. Session pages live at the workspace top level. You must manually create one Notion top-level page per session name you intend to use and connect the integration to each. Use this only when you can't add a single shared parent page.
Migration note: if you upgrade from v0.5.0–v0.5.2 (atoms under
parent_page_idin either flat or session-tree layout) and switch to workspace mode (dropparent_page_id), pre-existing atoms become unreachable via--id/delete. Either keepparent_page_idset, or migrate atoms manually before switching modes.
Workspace-mode security note: AI2Stock will operate on any workspace-top-level page that matches a session name and that the integration can access. Avoid sharing the AI2Stock integration with unrelated top-level pages.
- Create a Notion Integration at https://www.notion.so/my-integrations and copy the Internal Integration Token (
secret_xxxorntn_xxx). - In Notion, create either:
- Parent mode (recommended): any page that will hold session sub-pages (e.g. "AI2Stock"). Created once; sub-pages are auto-generated per session. OR
- Workspace mode (fallback): a top-level page titled exactly your session name (e.g. "AI2Stock"). Repeat for each session name you'll use.
- Open the page, click
... → Connections → <your integration>to grant access. - (Parent mode) Copy the Parent Page ID (the last 32 characters in its URL, before
?v=if any). - Set the token in your shell:
# bash (macOS Terminal opens login shell → .bash_profile) echo 'export NOTION_TOKEN=ntn_xxx' >> ~/.bash_profile source ~/.bash_profile # or zsh echo 'export NOTION_TOKEN=ntn_xxx' >> ~/.zshrc source ~/.zshrc
- Either run
ai2stock initagain (and answer yes to Notion), or edit~/.config/ai2stock/config.ymlto add thenotion:section above.
| You want | What to do |
|---|---|
| Obsidian only (default) | Default config |
| Both at once | write_strategy: all in config |
| Obsidian primary, Notion sometimes | Default + /stock --to=notion per call |
| This call: Notion only | /stock --to=notion |
| This call: Obsidian only | /stock --to=obsidian |
| This call: both | /stock --to=all |
| Operation | Obsidian | Notion |
|---|---|---|
--append (add to end) |
✅ | ✅ |
--replace (full body replace) |
✅ | ✅ |
--section (replace one heading section) |
✅ | ✅ |
delete |
✅ unlink | ✅ archive |
For Notion edits, an explicit --id <atom-id> is required (Notion lookup queries the Title property). For Obsidian, the most-recently-added atom is used by default if --id is omitted.
Note on delete defaults: Unlike
/stock(writes to all enabled adapters by default),deletedefaults to the primary adapter only (safer). To delete from both, pass--to=allexplicitly. Otherwise you may leave a Notion-only orphan.
Examples:
echo "more" | ai2stock add --from-stdin --append --to=notion --id=2026-04-26-1943-spec
echo "new body" | ai2stock add --from-stdin --replace --to=notion --id=2026-04-26-1943-spec
ai2stock delete --to=notion --id=2026-04-26-1943-spec --forcenpm test # vitest, 56 tests
npm run build # tsc → dist/
npm run dev # tsx (no build needed)TDD with vitest. All current tests pass; new features land with tests.
MIT