Jump to a section. Keep the lines that matter.
A lightweight, open-source reading companion for X/Twitter long-form articles.
English · 中文
A star won't fix bugs, but it makes the person fixing them happy.
XTOC helps you navigate structured X Articles, save useful passages with their source context, and move your clips into an open format when you are done reading.
x-toc-demo.mp4
Watch the 40-second demo: navigate an article, save passages, edit tags and notes, and export clips.
- Navigate the article. Open a long-form article and its contents appear in X's right column, above the recommendations, and stay in view while you read. In Focus mode they sit beside the article. Jump to any section from there or from the popup.
- Save a passage. Select text and click
save to xtoc. XTOC stores the passage locally with its article, author when available, timestamps, and surrounding context. - Organize and export. Open Library to search clips, add tags or notes, delete items, and export all or selected clips as Markdown or JSON.
- Article navigation — heading detection for X.com and Twitter.com long-form articles. Articles with two or more sections show a quiet contents module that follows X's Default or Lights out theme and accent color, highlights the current section, and collapses to one line. Its menu pops it out as a draggable floating panel that remembers its position, or hides it on articles (turn it back on in the popup or Settings). Narrow windows without X's right column show no module; use the popup or the floating panel there.
- Clips — select text and save it locally with one click, together with its article, author when available, timestamps and surrounding context.
- Bookmarks — save the current article or post with Save to Bookmarks in the popup, or import from your X Bookmarks page. Imports only read loaded previews and never change your X bookmarks. Repeat imports can stop at the previous import for the same account and list. Scan all bookmarks in the import menu checks older bookmarks too. The first run, an unrecognized list, or an invalid import record requires a full scan; page loading failures can still require a retry. On the Bookmarks page, the XTOC popup offers the same import controls and progress, so you can start again after closing the import bar. Keep the tab visible while importing; it waits while the tab is in the background.
- No reload after updates — X tabs that were already open keep working when XTOC is installed or updated.
Open Library from the popup or the contents menu. It has three pages:
- Clips — search, tag, annotate, delete and export your saved passages.
- Bookmarks — search, tag, annotate, delete and export saved articles and posts.
- Settings — article contents display, optional AI and local storage usage.
Clips and bookmarks export as Obsidian-style Markdown: a ZIP with one note per article or post, YAML properties, tags, and clips as quote callouts. Clips can also be exported as JSON v1. You can export everything or only selected items.
Optional AI suggests up to three tags and a short summary for one bookmark at a time. In Settings, pick a provider (OpenAI, Anthropic Claude, Google Gemini, DeepSeek, OpenRouter, Qwen, Moonshot Kimi, or any OpenAI-compatible URL), paste your API key and connect; XTOC lists that provider's models and preselects a fast one. It sends only that bookmark's saved text and your existing tag names; notes are never sent. Nothing changes until you choose Apply. By default the key is kept only for the browser session; turn on Remember on this device to keep it encrypted in the extension's own storage on this device. It is never synced, exported or readable by X pages. Provider charges apply.
Everything stays in your browser, with no separate XTOC account. XTOC saves passages for later review; it does not restore highlights in the original article or sync clips to a cloud service.
Install XTOC from the Chrome Web Store, Microsoft Edge Add-ons, or Firefox Add-ons.
Install from source
git clone https://github.com/HiAriesZhou/xtoc.git
cd xtoc/apps/extension
npm install
npm run buildThen open chrome://extensions/, enable Developer mode, choose Load unpacked, and select dist/chromium.
Run extension commands, including DashBye, from apps/extension/. Paths below are relative to that directory. The website lives in apps/web/; each app has its own npm lockfile, with no root workspace.
npm run dev
npm test
npm run build
npm run build:firefox
npm run build:edgeFor day-to-day debugging, npm run build:dev additionally writes dist/chromium-dev at the repository root (other builds stay in apps/extension/dist/): the same build renamed XTOC (Development) with an orange, striped toolbar icon, so it is easy to tell apart from the store version. Load that folder instead of dist/chromium; it gets its own extension ID and local storage, which stay with that folder path, so later build:dev runs update it in place. Release ZIPs always use the unbranded builds.
npm run build:zip builds all three targets and writes the store packages to release/: xtoc-chrome-v<version>.zip, xtoc-edge-v<version>.zip, xtoc-firefox-v<version>.zip, plus xtoc-source-v<version>.zip (the committed source, for Firefox Add-ons review). Commit first; the source archive is skipped when there are uncommitted extension changes.
Chrome, Edge and Firefox are available from their respective stores. Chromium, Firefox and Edge have separate build targets and should be tested in their own browsers before distribution.
Saved text, clips, tags, notes, settings and bookmark import progress (your X handle and recent bookmark IDs, so repeat imports can stop early) remain in chrome.storage.local; the unlimitedStorage permission keeps saved article bodies from hitting the default local quota and grants no site access. The scripting permission lets XTOC restart itself in X tabs that were already open when it is installed or updated, so they work without a reload; it adds no sites beyond X/Twitter. Exports are user-triggered downloads. Optional AI sends one bookmark's saved text and your tag names directly to the configured provider, only when you ask. AI host access is requested for that provider only; page scripts remain limited to X/Twitter. The API key lives in extension session storage, or, if you choose Remember on this device, encrypted (AES-GCM, non-extractable browser key) in the extension's IndexedDB; this keeps it out of plain-text files but does not protect against someone who controls the device. It is never synced, exported or saved with your library. Remove key deletes it everywhere and revokes that provider permission. There is no telemetry, X credential collection, cloud library storage or automatic upload.
Product website · Project story · Contributing
MIT. See LICENSE.