README file from
GithubHarry Toolkit
English | 繁體中文
Requires Obsidian 1.8.7 or later.
A personal toolkit for Obsidian that bundles a few small, self-contained tools for writers. Every feature can be turned on or off individually in settings — a disabled feature adds no commands, no views and no notices.
All data lives inside your vault, as note frontmatter, plain Markdown and JSON files. Everything remains readable if you disable or remove the plugin.
Network use: only the Threads analytics feature connects to the internet. It calls Meta's official Threads API to read your own account's data. It never posts. Every other feature is fully offline, with one opt-in exception: the Home page's AI titles option runs Claude Code or Codex installed on your computer, and those tools go online (off by default).
| Feature | What it does |
|---|---|
| Home | A start page: what to work on today, what needs attention, and a box to jot down an idea |
| Scrolling | Scroll the document with a hotkey while the cursor stays put on screen |
| Copy as social post | Turn a note into plain text you can paste into Facebook without losing the blank lines |
| Threads analytics | Pull your own post metrics from the official API into a sortable dashboard |
Home
A start page. Open Obsidian and see what to work on today and what needs attention, and
jot down an idea the moment it comes. It is built around a specific folder layout (a handover
file, an inbox, ideas, topics and weekly reviews); every location can be changed in settings.
The Home page changes your files in only a few places: quick capture adds an idea note; the plans
tab adds, ticks and dates lines in Todo.md; the inbox section ticks messages, archives ticked ones
and can clean out the archive; and the library section changes a book's status. Everything else is
read-only.
Open it from the 🏠 ribbon button or the Open Home command. By default it also opens when Obsidian starts.
The greeting and quick capture always stay at the top:
- Greeting: today's date and weekday, plus a line of your own. The gear button opens settings.
- Quick capture: type a thought and press Save as idea or Enter (Shift+Enter for a new line).
It is saved to
文章/靈感/asdate-title.md, titled with the first sentence of your thought (up to 15 characters). Existing files are never overwritten; a-2,-3suffix is added. Works on mobile too.
Below them is a row of tabs, each showing one section: 計畫 (Plans: everything to do and reminders on one page), 隨手記 (Inbox), 書庫 (Library), 交接本 (Handover), 選題 (Topics), 文章 (Articles), 技能 (Skills) and 檔案 (Files). Tabs show counts (open plans, pending messages, books to read, unfinished topics, unpublished drafts); the plans count is highlighted when something is overdue (plans due today are not overdue). The page remembers the last tab you used. Anything on the page that opens a note (cards, list rows, links) opens in a new tab with a middle-click or Ctrl+click; a plain click opens it in the current tab. Drag tabs to reorder them; right-click the tab row to restore the default order (dragging isn't available on mobile, which uses the order set on desktop). Tabs wrap onto a second line when the window is too narrow.
- Plans is the one page to check each day. The add box sits on top: type, optionally pick a date,
and press Enter or 加入. Below it are two columns (stacked on narrow panes, timeline first):
- Left, the timeline: dated plans grouped into overdue, today, tomorrow, this week (to Sunday) and
later (empty groups are hidden), each with its date, weekday and "today" / "N days left" /
"N days overdue" (overdue ones in red, today's in the accent colour); then undated intentions ("有打算") and a
collapsible list of completed ones. Tick to complete. 排日期 schedules an intention; 改日期
changes or removes a date.
[[links]]in a plan are clickable. Plans that have notes in交接本/手上的事.mdshow a 說明 tag: hover for the "接下來" (next step) line, click to jump to the notes (it reads "說明・N 天沒動" after 7 idle days). Those plans get 交給 AI (copies "繼續「…」" to paste into Claude Code); the others get 變成手上的事 (copies a request asking the AI to start notes for it). These buttons only appear while the mouse is over the plan (checkbox, date and 說明 always stay; always shown on touch devices). - Right, reminders (see below).
- Plans live in
Todo.md, one per line in Obsidian's native checkbox format:- [ ] text 📅 2026-10-20(no 📅 when undated). To edit or delete a plan, just editTodo.md; the page follows. Dated plans that are due or overdue trigger a notification (see Due reminders). The file is created on the first add if it doesn't exist.Todo.mdis the only to-do list: every item in the handover file has a line with the same name there (dated = now, undated = later); the handover file only holds notes for some items, written by the AI and read-only here. The two are matched by name, so the handover heading must match the Todo line exactly. Tick a plan and the AI moves its notes to收掉的事at the end of the day.
- Left, the timeline: dated plans grouped into overdue, today, tomorrow, this week (to Sunday) and
later (empty groups are hidden), each with its date, weekday and "today" / "N days left" /
"N days overdue" (overdue ones in red, today's in the accent colour); then undated intentions ("有打算") and a
collapsible list of completed ones. Tick to complete. 排日期 schedules an intention; 改日期
changes or removes a date.
- Reminders (right column of the plans tab): only what needs attention, each one clickable (the
inbox and handover lines switch to their tab):
- handover items with no Todo line of the same name
- plans ticked off whose handover notes haven't been closed yet
- pending inbox items (notes in
收件匣/隨手記/whose處理完is nottrue) - ideas due for tending (seed ideas never researched, updated since last researched, or last researched 30+ days ago)
- the date of the last weekly review, highlighted after 7 days, or a note that there is none
- when nothing needs attention, a single quiet line says so
- Inbox (隨手記): every message sent from Telegram that is still in
收件匣/隨手記/, newest first. Each shows the first line of the message (hover for the full text), its type (text or link) and when it arrived. 取新訊息 (desktop only) runs my-AI-System'sscripts/inbox.mjs pull, the same program the AI runs at the start of the day: it fetches new Telegram messages and archives ticked ones, then shows its one-line summary. The inbox must already be paired in my-AI-System; if node can't be found, set Node 位置 in settings. Click to open the note; a message that is just a link has a button that opens it in your browser. Tick the box in front of a message once you've dealt with it (this sets處理完: truein the note; untick to undo); ticked messages fade out but stay listed. 封存 (archive) moves every ticked message into收件匣/隨手記/已處理/. Nothing is deleted, and a message is left in place if the archive already holds a file with the same name. 清理封存 (clean archive) first asks for confirmation, naming the folder and how many messages will be deleted; deleted files follow Obsidian's Settings → Files and links → Deleted files choice (system trash by default). - Library (書庫): the books in
知識/書庫/, either to read (待讀) or finished (讀完); no reading progress is tracked. Books to read are listed with title and author and a 讀完 (finished) button; finished books sit in a collapsible list with a button to move them back. The buttons only change thestatusline in the book note's front matter. Click a title to open the book. - Handover: buttons that open the handover files (
手上的事,認識我,寫作語氣,收掉的事), then every item in手上的事with its status in the plans (date, "有打算", "ticked, not closed" or "not found in plans"), when it last moved (highlighted after 7 idle days) and its "接下來" line. Clicking an item opens the file at its heading. - Topics: every unfinished topic from
文章/選題/, newest first by creation date (the topic's日期). Each row shows "has N drafts" (unpublished only) or "not written yet" and the creation date. Below each topic, its drafts and its published posts are listed on separate lines and open with a click. Finished and dropped topics sit in a collapsible list. A draft belongs to a topic when its front matter says選題: "[[topic file name]]", or when the topic's## 草稿section links to it. Drafts can live anywhere under文章/(except文章/選題/and文章/靈感/), so a new platform doesn't need its own folder first. Adding or dropping topics is done elsewhere; the Home page only shows them. Each topic has a +打算 button that switches to the plans tab with a link to the topic filled in, so you only type "write the FB version". Open plans that link to a topic are listed under it. Each unpublished draft has a 排時間 (schedule) button: enter what to do (default "發布", publish) and a date, and a plan "發布 [[draft]]" is added, so it shows on the plans timeline, due reminders and the AI's start-of-day report. Scheduled drafts show the action and date, e.g. "發布 10/15" (red when overdue, accent colour when due today), and the button becomes 改時間; the date on the topic's own row is its creation date, shown in faint grey (hover for details), so the two kinds of date don't get mixed up. A published draft whose plan is still open is flagged, with a button to tick the plan. To save space, +打算, 排時間 and 改時間 only appear while the mouse is over that topic (scheduled dates always stay visible); on touch devices they are always shown. - Articles: buttons for the article index and best-posts files, the number of drafts and
published posts for each platform, unpublished drafts (each with the same 排時間 button; newest first,
up to 8) and the 5 most recent articles. Every note under
文章/(except 選題 and 靈感) counts; its platform comes from the平台property, or from its folder if that's missing. 脆, 部落格, FB and 電子報 come first, other platforms (X, 小紅書, IG…) follow, and platforms with no posts are skipped. Notes at the top of文章/without a platform (such as the index) aren't counted. A status starting with已發布counts as published; anything else, including no status, counts as a draft. - Skills: every skill in
技能/, one per line with its name and a short description, sorted by name. Short descriptions come from技能/技能清單.md(- name:description, one per line); skills missing there fall back to the first sentence of theirSKILL.mddescription, shown in grey italics as a reminder. Hover for the full description, click to open theSKILL.md, and 用這個 copies "用 … 技能" to paste into Claude Code. - Files: browse folders without switching to the file explorer. A folder tree grown from the vault
root on the left, the selected folder's files on the right, using most of the page height. The two
columns always stay side by side; in a narrow pane both get narrower and long names are shortened
with "…" (hover for the full path).
- Click a folder to expand or collapse it and show its files on the right (click the small arrow to only expand). Expanded folders are remembered
- ★ favourite folders jump straight to a folder without shrinking the tree; 將目前資料夾加入常用 at the bottom of that menu adds the current one
- The filter box searches the selected folder and all its subfolders by file name (not note contents); files found in subfolders show their relative location
- The sort button next to the filter switches between name, modified and created time, ascending or descending. Each folder remembers its own sort, and 設為其他資料夾的預設 sets the default for the rest. The tree itself is always sorted by name
- Click a file to open it here;
Ctrl/Cmd-click or middle-click opens a new tab - Drag files or folders onto a folder in the tree to move them; links to them are updated. Hovering over a collapsed folder for half a second expands it; an existing file with the same name is never overwritten
- Right-click a folder to create a note or folder in it (you're asked for the name first); files and folders also have open in new tab, open to the right, rename, duplicate and delete, followed by other plugins' items. Rename updates links; delete asks first, then follows your Files and links → Deleted files setting
- The 檔案分頁只列 Markdown 檔 setting limits the file list to notes
If a file or folder can't be found, that section says so and the rest of the page still works. The page refreshes itself when files in the vault change. Dates use Taiwan time.
AI titles (optional, desktop only)
With AI for titles set to Claude Code or Codex, quick capture first saves the idea with its first-sentence title (no waiting), then asks the AI in the background for a title of up to 15 characters and renames the note and its heading when one arrives (links to it are updated). If the AI fails, takes more than 60 seconds or replies with something that isn't a title, the original title stays and nothing interrupts you.
- Claude Code or Codex must be installed and signed in on your computer. Auto tries Claude Code first, then Codex.
- If Obsidian can't find the program, enter its full path in settings.
- The AI runs in the system temp folder, not in your vault, and only sees the one thought.
- On mobile this option is ignored and ideas are saved with the first-sentence title.
Scheduling from a note
Schedule a piece right after you finish it, without going back to Home:
- Right-click a note (file explorer, tab header, editor, or Home's files tab) → 排發布時間, or run the 排發布時間(目前筆記) command (bind a hotkey in Settings → Hotkeys if you like)
- The same dialog as the 排時間 button on Home's drafts: what to do (default "發布", publish) and a
date. It adds a plan "發布 [[this note]]", so it shows on the plans tab, in due reminders and in the
AI's start-of-day report. Pieces under
文章/are named "platform・title" in the plan; other notes use the file name - For a note that already has a plan, the menu reads 改發布時間(10/15) and only changes that plan's date instead of adding another line; 拿掉日期 in the dialog turns it back into an undated plan
Due reminders
- When Obsidian starts, and every hour after that,
Todo.mdis checked: open plans due today or overdue pop up in one notification - Each plan is reported once, so you aren't spammed; a new one coming due triggers a new notification
- The Check plan due reminders now command runs the check on demand (and tells you when nothing is due)
- Turn off 計畫到期提醒 in the settings if you don't want the notifications
Settings
- Greeting: the line under the date; leave empty to hide it
- Open Home when Obsidian starts (on by default)
- Show Home in new empty tabs (off by default): if another start-page plugin also takes over new tabs, enable only one of them
- Plan due reminders (on by default): see above
- AI for titles: none (default) / Claude Code / Codex / auto
- Claude Code / Codex location: shown only when an AI is selected; leave empty to use the system path
- Node location (desktop only): the node used by the inbox's 取新訊息; leave empty to use the system path
- Folder locations (under advanced): handover file, inbox, ideas, topics, weekly reviews, library, skills,
plans file (default
Todo.md), plus the shortcut buttons above the handover and article sections (one file path per line)
Scrolling
While drafting or proofreading a long document, the cursor stays at a fixed position on screen and the text flows past it line by line — your eyes don't have to chase the cursor and your hands never leave the keyboard. Similar to typewriter mode, but you control the pace.
Two commands, bindable under Settings → Hotkeys (search for "Harry Toolkit"):
| Command | Effect |
|---|---|
| Move content up (cursor stays in place) | Text flows upward; the cursor lands on the line that just arrived |
| Move content down (cursor stays in place) | Text flows downward |
- The cursor's on-screen position never moves; its document position follows, so you can start editing at the new spot immediately
- Hold the hotkey to scroll continuously, or tap it to move line by line
- Wrapped lines are measured correctly, and the target column is preserved so the cursor doesn't drift sideways when passing short lines
- At the top or bottom of the document the cursor simply settles on the first or last line
- Works in Source mode and Live Preview; Reading mode has no cursor, so it doesn't apply
- Works on both desktop and mobile
Settings
- Lines per scroll — how many lines one keypress moves (default 1, max 20)
- Smooth scrolling — animate the scroll (off by default; keep it off if you hold the key down)
Copy as social post
Turns a finished note into plain text you can paste straight into Facebook. It only touches the clipboard — the note itself is never modified.
Facebook drops blank lines when you paste: a note reading "one, blank line, two" arrives as two
adjacent lines. It also collapses runs of spaces, and it doesn't understand Markdown, so
**bold** shows up with the asterisks. This feature deals with all of that at the moment you
copy.
Two entry points (both use the same settings):
- The command Copy as Facebook post — if there is a selection in the editor, only the selection is copied, since a post is often just one section of a longer piece. Bind a hotkey under Settings → Hotkeys
- Right-click a note → Copy as Facebook post (file explorer, tab title, editor menu and link right-click all work)
What the conversion does:
- Strips the frontmatter, so
publish_statusand friends never reach the post - Protects blank lines by putting a character on them that is invisible but does not count as whitespace, which stops Facebook collapsing the line. The default is a zero-width space; if that ever stops working, settings offer a braille blank instead
- Protects runs of spaces, so indentation and deliberate gaps survive
- Strips Markdown (optional):
**bold**,*italic*,~~strikethrough~~,==highlight==,`code`→ text only## Heading→ the heading text;#tagis left alone (that's a Facebook hashtag)[text](url)→text (url)— the URL is always kept, since Facebook needs it to build the link preview[[wikilinks]]and[[link|alias]]→ the displayed text- Lists → a
•prefix, flattened (Facebook strips leading whitespace anyway) ---rules →———- Images and
%%comments%%are removed entirely — upload images on Facebook itself, and Obsidian comments are private notes to yourself
A notice reports the character count, excluding line breaks and the invisible characters.
Settings: strip Markdown (on/off), blank-line character (zero-width space / braille blank / none), protect runs of spaces (on/off).
Threads analytics
Reads your own Threads post metrics through Meta's official API and shows them as a sortable dashboard inside Obsidian. Post-level metrics only.
Read-only. This feature has no ability to post, and never will.
Getting an access token
- Create an app of type Threads API in the Meta developer console
- Find the User Token Generator under the app's Threads API settings
- When generating the token, tick
threads_basicandthreads_manage_insights— without the second one you get posts but no metrics. Addthreads_read_repliesif you also want your replies - Paste the token under Settings → Harry Toolkit → Threads analytics and press Test connection
⚠️ The token is stored in plain text, in
<vault>/.obsidian/plugins/harry-toolkit/data.json— Obsidian plugins have no access to the operating system's secure storage. If your vault is synced or pushed to Git, the token travels with it. The token is read-only, cannot post, and expires after 60 days, but please weigh that up for yourself.
Tokens last 60 days. The plugin refreshes yours automatically once it has fewer than 10 days left (Meta requires a token to be at least 24 hours old before it can be extended). If one does expire, generate a new one and paste it in.
The dashboard
Open it from the bar-chart ribbon icon or the Open Threads dashboard command.
- Account summary — name, separate post and reply counts, and last-updated time
- Update recent posts — fetch metrics for posts from the last N days (30 by default)
- Refetch everything — fetch metrics for every post
- Sort and search — by views, likes, replies, reposts, quotes, shares or publish date, with full-text search over post content
- Include replies — off by default. This checkbox only controls display; replies have to be fetched first (see below)
- Each row shows its text preview and publish time down to the minute (e.g.
2026/9/17 21:13). The text is clamped to two lines; hover it to see the whole post - Each row shows six numbers — views, likes, replies, reposts, quotes, shares — with the current sort column highlighted. Click a row to open the post in your browser
How long a fetch takes
Post metrics must be requested one post at a time — the API has no batch endpoint — with a 0.18 s pause between posts to stay within Meta's limits:
| Posts | Roughly |
|---|---|
| 200 | 1 minute |
| 500 | 2–3 minutes |
| 1000 | 5 minutes |
Progress is shown throughout and Stop is always available; whatever has been fetched is still saved. Day to day, Update recent posts is enough. Refetch everything asks for confirmation first, with a time estimate based on your post count.
Closing the dashboard tab does not stop a fetch — it runs on the plugin, not the view. Reopening the dashboard reconnects to the same progress. Quitting Obsidian or disabling the plugin does abort it, and since saving happens once at the end, that run is lost.
Refetching never damages existing data
The data file is append-and-update only: posts that weren't queried this round keep their existing numbers. So stopping halfway, individual failures, and repeated refetches are all safe, and posts deleted on Threads stay in your records.
Changing tokens or accounts
Regenerating a token for the same account is transparent — paste it in, test the connection, and your existing data carries on.
The data file records which account it belongs to. If a new token belongs to a different
account, you get a warning before fetching, because mixing two accounts' posts into one file
makes the rankings meaningless. To track both, point the data folder setting somewhere
else, or move the existing posts.json aside.
To start over, delete posts.json and fetch again — post metrics can always be refetched.
Fetching your replies
Replies come from a different endpoint (me/replies, not me/threads), so they're a
separate switch:
- The token needs the
threads_read_repliespermission - Turn on Also fetch my replies in settings
- Fetch again
- Tick Include replies on the dashboard
Replies usually far outnumber posts, so fetching takes noticeably longer — hence the default.
The reply-count column shows "—" for replies. That's not a failure: Meta's API returns 0 for reply-type posts regardless of reality, so the number is meaningless. Views, likes, reposts and quotes are all reported normally.
Data files
One JSON file in the folder you choose (Threads 數據 by default): posts.json, holding
post content and their latest metrics.
It lives in your vault, not in the plugin folder, so it survives uninstalling the plugin and travels with your backups. It is ordinary JSON you can read or feed to other tools.
What this feature can't give you
- Followers gained per post — not exposed by the official API. The Threads website shows it, but scraping it would need an automated browser, which an Obsidian plugin can't do
- Other people's accounts — the API only covers your own
- Audience demographics and link clicks — available from the API, but deliberately not implemented: demographics need 100+ followers, and link clicks are aggregated per URL at the account level, so they can't be attributed to a post
Settings
- Access token — see above
- Test connection — verifies the token and records the account id
- Data folder — where the JSON file goes (empty means the vault root)
- Days for "Update recent posts" — default 30
- Also fetch my replies — off by default; needs
threads_read_replies - Dashboard location — where to open the dashboard when it isn't open yet
Enabling and disabling features
Settings → Harry Toolkit has one section per feature, each starting with an
Enable this feature toggle. A disabled feature's commands, views and notices all
disappear; the others are unaffected. Toggling requires a reload to take effect — disable
and re-enable the plugin under Community plugins, or press Ctrl+R / Cmd+R.
Installation
From Community plugins
Settings → Community plugins → Browse, search for Harry Toolkit, then Install and Enable.
Manually
Download main.js, manifest.json and styles.css from the
latest release into
<your vault>/.obsidian/plugins/harry-toolkit/, reload Obsidian with Ctrl+R / Cmd+R, and
enable the plugin under Community plugins.
Afterwards, bind the two scrolling commands under Settings → Hotkeys (search for "Harry Toolkit").
Development
npm install
npm run dev # watch and rebuild
npm run build # production build, writes main.js
npm test # Home rule tests (compared against my-AI-System's scripts when it sits next to this repo)
Type-check with npx tsc --noEmit.
Project structure
src/
├─ main.ts entry point: load settings, run the feature list, mount the settings tab
├─ core/ the Feature interface, settings merging, the shared settings tab
└─ features/
├─ index.ts the feature registry — adding a feature means adding one line here
├─ home/ start page: parsing rules, quick capture, AI titles, plans and due reminders, files tab, the view
├─ scroll/
└─ threads/ API client, storage, sync, dashboard
Features never import the plugin class; they receive everything they need through a
FeatureContext, so each one can be added or removed without touching the others.