Tachado

unlisted

by Lucia Adams

Colored daily/weekly/monthly task tokens with automatic carry-over, generated TO-DO reports, and GitHub activity import. One note per month.

Updated 2d agoMIT
View on GitHub

Tachado

Colored task tracking and automatic carry-over for Obsidian daily documentation

Write your work log as it happens. Let the plugin do the bookkeeping.

Obsidian License: MIT No build step Tests


What it does

Tachado turns plain-text markers like 1.D, 2.W and 3.M in your notes into live-colored, italicized tasks — and then keeps your daily, weekly and monthly TO-DO reports in sync automatically.

You write the log. Tachado handles numbering, carry-over, promotion, strikethrough and report generation.

3:45 p.m. : 2.D so I need a branch-specific bd until [[remargin]] has a task manager
3:50 p.m. : 3.D reescribir la solución de [[WispBridge]] lista para producción

Open the note tomorrow and the report has already updated itself:

### Daily TO-DO Report

- [ ] 0.1.D — so I need a branch-specific bd until [[remargin]] has a task manager
- [x] 1.D — ~~reescribir la solución de [[WispBridge]] lista para producción~~

The colors live in the plugin, not in your files

Your markdown stays plain text. No <span style="color:red">, no HTML pollution, no proprietary format.

2.D so I need a branch-specific bd

That's what's on disk. Greppable, diffable, portable, yours. The red-italic rendering is a CodeMirror decoration applied at display time — in both Live Preview and Reading view.


Features

✍️ You never number anythingWrite D :, W : or M : and the number is filled in for you, continuing from whatever is already there
🎨 Live coloringD red, W orange, M blue — token and task text, italic, as you type
♻️ Automatic carry-overAn unfinished task moves to today as 0.1.D, 0.2.D… once the clock reaches it — it never sits in two lists at once
🔢 Self-renumberingCarry-over slots are positional, always oldest-first. Insert an older task and everything below it shifts down
⬆️ Promotion & demotionRewrite the suffix to move a task between timeframes. Up = plain number, down = carry namespace
Generated reportsDaily, weekly and monthly TO-DO sections are rebuilt from your log, never typed by hand
🚫 Strikethrough & DROPPEDNative Obsidian checkboxes. - [x] strikes it, - [-] marks it [DROPPED]
📆 Closing datesTicking or dropping records the day you did it — [completed 17/09/2026], [DROPPED 17/09/2026] — written once and never recomputed
🔗 Automatic linkingMention a tool or project that exists and it becomes a real wikilink — backlinks and graph included
⌨️ @ pickerType @ for a dropdown of every tool and project, or keep typing to create a new one on the spot
🐙 GitHub importCommits, PRs, merges and reviews pulled in automatically as timestamped log lines, scoped to the orgs you allow
🗓️ Log to any past dayA calendar you click a day in, then a time and what happened. Future days are not selectable
📅 Month scaffoldingPick a month and year; the note arrives with every day already written out and grouped into calendar weeks
🕔 5-minute clockEvery time in the log is normalised to 9:15 a.m., rounded to the nearest five minutes
🗂️ Generated indexesA year note with live per-month counts, and a collapsible index inside every month
📄 One note per month2026/SEPTEMBER 2026.md holds every week, day and report. No file sprawl
📦 Zero dependencies~450 lines of plain JavaScript. No npm, no bundler, no build step

Install

Tachado isn't in the community plugin directory yet. Install it manually:

git clone https://github.com/maledadams/tachado.git "<your-vault>/.obsidian/plugins/tachado"

Then in Obsidian: Settings → Community plugins → turn off Restricted mode → enable Tachado.

Only main.js, manifest.json and styles.css are needed at runtime.


The syntax

Changing a task's timeframe

Promote or demote a task writes the line again, now, with the new scope — which is exactly how the format declares a change:

original: 3:15 p.m. … 5.D "task" → modified: 9:00 p.m. … 2.W "task"

The original line stays as the record of when it was first raised. The new number is filled in for you.

Just write the letter

You never work out a number yourself. Write the scope and a colon:

9:05 a.m. : D : revisar los comments de Eduardo
9:30 a.m. : W : terminar el blueprint

and the next rebuild fills them in:

9:05 a.m. : 1.D revisar los comments de Eduardo
9:30 a.m. : 2.W terminar el blueprint

Numbering runs per scope and per period — day for D, week for W, the note for M — and continues from the highest number already written there by hand. Lowercase works. Bare markers are colored live as you type, so you can see one registered before it has a number.

Written out in full, a marker is:

(0.)?N.SCOPE      1.D   2.W   3.M   0.1.D
SCOPE :           D :   W :   M :
TokenScopeColorMeaning
1.DDaily🔴 redA task for today
1.WWeekly🟠 orangeA task for this week
1.MMonthly🔵 blueA task for this month
0.1.DCarry🔴 redArrived from an earlier day, or demoted from a longer timeframe

Times are normalised on every rebuild: 12-hour, a.m./p.m., and rounded to the nearest five minutes. 9:13 a.m. becomes 9:15 a.m., 11:59 p.m. rolls to 12:00 a.m. Inline code and URLs are left alone.

Write the token anywhere on a line. Each token colors itself and the text that follows it, up to the next token or the end of the line — so a single line can carry two tasks:

3:50 p.m. : he said 3.D "rewrite the service" BUT 4.D "wait a week first"

Carry-over tracks the real clock, and it moves a task rather than copying it. An unfinished task appears in exactly one daily report: today's. It leaves the day it was raised on. A task you finished stays struck through on the day you closed it, and never travels.

A report for a day that hasn't arrived stays empty, even when the note already has a heading for it — scaffolding October doesn't project today's unfinished work across all thirty-one days.

Carry-over is a sort, not a queue

The 0.N namespace is positional and ordered by age. 0.1 is always the oldest open task.

Add a task older than the current 0.1 and it takes 0.1; everything below shifts down one. Numbers belong to positions, not to tasks — which is exactly why you shouldn't be maintaining them by hand.

Promotion and demotion

Declare a move by writing the line again later with a new suffix. Tachado links the two by text and updates the scope.

11:00 a.m. : 1.D reventar la barrita          ← raised as a daily task
 9:00 p.m. : 2.W reventar la barrita          ← moved to weekly
DirectionResult
PromoteD → W, D → M, W → MPlain next number in the target list (2.W)
DemoteM → W, M → D, W → DCarry namespace (0.1.D), arriving on the day you demoted it
Unfinished daily → next dayCarry namespace (0.1.D)

Logging to any day

Add a log entry opens a month grid. Click a day, type a time and what happened, press Enter.

 ‹      September 2026      ›
 Mo Tu We Th Fr Sa Su
     1  2  3  4  5  6
  7  8  9 10 11 12 13
 14 15 16 17 18 19 20
 21 22 23 24 25 26 27
 28 29 30

 [ 3:45 p.m. ] [ what happened — or 1.D a task ]

Future days are greyed out and unclickable, and you can't page past the current month — this is a log, not a planner.

The time box is forgiving: 3:45 p.m., 3:45pm, 3pm and 15:47 all work, and whatever you type is rounded to the nearest five minutes on the way in. Type a task token and it behaves like any other task.

If the day you pick has no heading yet, Tachado writes one — along with its week banner and that week's report — in the right place. If the whole month note doesn't exist, it gets scaffolded first.

Putting a misplaced entry right

Move a log entry to another day takes two passes over the same grid: pick the day you think it's on and click the entry, then pick the day it belongs on. Days holding entries are marked, so a line that landed somewhere odd is easy to spot.

The entry keeps its time and is re-filed in time order on the destination day. If that day has no heading yet, one is written — along with its week banner, if that is missing too.


Closing a task without hunting for it

Complete a task and Drop a task open the same grid. Days carrying open work are marked; click one and you get everything closeable from there — that day's tasks, that week's, and the month's, each with its number. Click a task and it's closed and dated.

 ‹      September 2026      ›
 Mo Tu We Th Fr Sa Su
  ...
 14 15 16 17 ...              ← days with open tasks are marked

 0.1.D   so I need a branch specific bd until remargin…
 0.2.D   "Dile que aquí el objetivo es reescribir…"
 1.W     nueva misión semanal: REVENTAR la barrita…

It flips the same checkbox you would click by hand, so the date lands exactly as it would otherwise. The row is matched on its text rather than its position, so editing the note while the picker is open can't close the wrong task.

Why not the Calendar plugin?

The Calendar plugin is built around one note per day: clicking a date calls openOrCreateDailyNote, and it exposes no hook to do anything else. Tachado is one note per month on purpose, so wiring the two together would scatter a file per day across your vault — the opposite of the point. Hence the small grid above.


Starting a month

New month note opens a picker that works like Obsidian's quick switcher — type to filter, Enter to create.

The note arrives complete: every day of that month, with its weekday, already grouped into weeks, each with its report heading.

# OCTOBER 2026

# WEEK 1 OF OCTOBER

## Thu, October, 1:

### Daily TO-DO Report

## Fri, October, 2:

### Daily TO-DO Report
...
## END OF WEEK 1 TO-DO REPORT

# WEEK 2 OF OCTOBER
...
# END OF OCTOBER TO-DO REPORT

Weeks start on Monday and are numbered within the month, so Monday 14 September 2026 falls in week 3. That means a month has five or six weeks as often as it has four — September 2026 has five: the 1st–6th, 7th–13th, 14th–20th, 21st–27th and 28th–30th.

Picking a month that already exists just opens it.


Vault structure

Year folders, one note per month, and a Tools/ folder for everything you link to.

your-vault/
├── 2026/
│   ├── 2026 Index.md          ← generated
│   ├── SEPTEMBER 2026.md
│   └── OCTOBER 2026.md
├── 2027/
│   └── 2027 Index.md          ← generated
├── Tools/
│   ├── Figma.md
│   └── Postgres.md
└── Projects/
    └── Checkout Rewrite.md

Inside a month note, headings define the skeleton. The TO-DO headings are the only markers Tachado needs — it owns everything between a report heading and the next heading.

# SEPTEMBER 2026

%% tachado:index %%            ← generated, invisible in Reading view
> [!abstract]- Index
> Year · [[2026 Index|2026]]
> **Weeks** · [[#WEEK 1 OF SEPTEMBER|Week 1]]
> **Days** · [[#Mon, September, 7:|Mon 7]] · [[#Tue, September, 8:|Tue 8]]
%% /tachado:index %%

# WEEK 1 OF SEPTEMBER           ← week banner

## Mon, September, 7:           ← day
9:30 a.m. : kicked off the sprint
11:00 a.m. : 1.D write the migration

### Daily TO-DO Report          ← generated

## END OF WEEK 1 TO-DO REPORT   ← generated

# END OF SEPTEMBER TO-DO REPORT ← generated

See example/ for a full worked month, its year index and two tool notes.


Tools, projects and automatic linking

Everything you reference is its own note. Tools live in Tools/, projects in Projects/ — same machinery for both: mention one anywhere in your log and Tachado turns it into a real wikilink, so backlinks and the graph view actually work.

11:00 a.m. : 1.D write the migration in postgres for the checkout rewrite
                                        ↓
11:00 a.m. : 1.D write the migration in [[Postgres|postgres]] for the [[Checkout Rewrite|checkout rewrite]]

Your original casing is preserved through the alias. Frontmatter aliases are matched too, so psql and postgresql both resolve to the same note.

KindFolderFrontmatter
ToolTools/type: tool, aliases, url
ProjectProjects/type: project, aliases, status, started, repo

Adding a third kind is one row in the KINDS array at the top of main.js.

The @ picker

Type @ anywhere to get a dropdown of every tool and project, each labelled with its kind. Keep typing to filter. If the name doesn't exist yet, you get one create option per kind — pick Project or Tool and it writes the note from the right template and links it in one keystroke.

Linking is deliberately conservative — it skips inline code, URLs, markdown links, existing wikilinks, blockquotes, generated report rows, and anything shorter than three characters.


GitHub activity

Commits, pull requests, merges and reviews land in your log as timestamped lines, linked back to the action on GitHub.

1:45 p.m. : commit [acme/app@a9d2477](https://github.com/acme/app/commit/a9d2477…) — docs: add the structure
2:40 p.m. : PR [acme/app#5](https://github.com/acme/app/pull/5) opened — docs structure · `docs/x``master` · 57 files +5190 −31
4:00 p.m. : PR [acme/app#5](https://github.com/acme/app/pull/5) merged into `master`
10:15 a.m. : reviewed [acme/app#12](https://github.com/acme/app/pull/12) — approved

Each entry is placed under the day it happened on, in chronological order among your other timestamped lines. Prose you wrote by hand is never reordered.

Generated lines are records, not prose: they are never autolinked, so a commit subject like docs(wispbridge): … keeps the scope the commit actually has. Re-running never duplicates, because entries are matched on a signature that survives a PR's file counts changing while it is open — and a URL you merely mentioned in a sentence never blocks the real entry from arriving.

No token, ever

Tachado shells out to the GitHub CLI, which is already authenticated on your machine. No personal access token is stored in your vault, so nothing leaks if you sync or push it.

brew install gh && gh auth login

Paste a link, get an entry

Drop a bare commit or PR URL on a line and run Expand GitHub links. Tachado fetches the title, stats, branches and the real timestamp, then rewrites the line as a full entry.

https://github.com/acme/app/pull/5
                    ↓
2:40 p.m. : PR [acme/app#5](…) opened — docs structure · `docs/x` → `master` · 57 files +5190 −31

Settings

SettingWhat it does
Organisation allowlistOnly import activity from these GitHub owners. Empty means all of them.
GitHub usernameWhose activity to import. Left blank, Tachado asks gh who you are.
Import on openPull new activity every time you open a month note.

Why the PR endpoints and not /events? GitHub's events feed trims pull-request payloads to nulls and never sees commits on branches that haven't merged — so half your work would go missing.


Indexes

IndexWhereContents
Year2026/2026 Index.mdEvery month in that year, with live open / done / dropped counts and totals
MonthTop of each month noteCollapsible callout linking back to the year, plus every week and day in the note

Both regenerate whenever you open a month note. The month index lives inside an Obsidian comment block, so it's invisible in Reading view and never clutters your writing.


Commands

CommandWhat it does
Rebuild TO-DO reports and indexReparses the note, relinks tools, regenerates every report and the index
Rebuild year indexRecounts every month in the current year folder
Promote or demote a taskPick a task, pick Daily / Weekly / Monthly
Reopen a taskPut a completed or dropped task back
Export this month to .docxWord file with the colors re-applied
Go to todayJump the cursor to today's heading
Complete a taskCalendar picker, then the list of what's open — click one to tick it
Drop a taskThe same, but marks it [DROPPED]
Move a log entry to another dayPick the entry, pick the day it belongs on
Add a log entryCalendar picker; writes a timestamped line into any past day
New month notePick a month and year; creates it fully scaffolded, or opens it
New tool or project noteDrops an @ at the cursor to open the picker
Import GitHub activityPulls commits, PRs, merges and reviews into this month
Expand GitHub linksTurns bare commit/PR URLs in this note into full entries

All of it also runs automatically whenever you open a month note — so carry-over, linking and indexes just happen.


Customizing colors

Edit styles.css. Three variables, light and dark:

.theme-light { --tl-D:#ff0000; --tl-W:#ff9900; --tl-M:#4a86e8; }
.theme-dark  { --tl-D:#ff6b6b; --tl-W:#ffb84d; --tl-M:#7fb3f5; }

Development

There's no build step. main.js is what Obsidian loads.

node check.js

314 assertions covering the 0.N sort order, promotion, demotion arrival day, checkbox-state preservation, multiple tasks per line, autolinking guards, index generation, bare markers, closing stamps, task pickers, both entity kinds, time rounding, GitHub entry mapping, month skeletons, generated-line handling, the calendar grid, future-day suppression and idempotence. No test framework.

Known limitation

A task's identity is its text. Reword a task substantially and Tachado treats it as new, resetting its checkbox. This is a deliberate trade: it keeps hidden IDs out of your markdown. The upgrade path (Obsidian block references) is noted in main.js.


Exporting to Word

Export this month to .docx writes a Word file beside the note, with everything the markdown deliberately leaves out put back:

  • Week banners as Title at Arial 26, days as Heading 1 at Arial 20, reports as Heading 2 and 3
  • Task markers and their text italic and colored — red, orange, blue by scope
  • Completed and dropped rows struck through, with their closing date
  • Checkboxes as ☐ ☑ ☒, links live, wikilinks flattened to their label
  • The generated index block omitted

No pandoc and no python-docxscripts/tachado2docx.py writes the file with the standard library, the same way docx2tachado.py reads one. Pandoc could not do this job anyway: markdown has no way to say "this span is red italic", which is the whole reason the colors live in the plugin.

python3 scripts/tachado2docx.py "2026/SEPTEMBER 2026.md"

Importing from Word

Already keeping this log in Word or Google Docs? scripts/docx2tachado.py converts a .docx export into a month note.

python3 scripts/docx2tachado.py "My log.docx" --year 2026 --out ~/my-vault \
        --tools Remargin WispBridge Dolt

It maps Word's outline styles onto Tachado's heading skeleton (Title → #, Heading 1 → ##, Heading 3 → ###), keeps hyperlinks, turns Google Docs' green inline-code color into backticks, and converts mentions of the tools you name into wikilinks. Report bodies are left empty on purpose — Tachado regenerates them from the log the first time you open the note.

Standard library only: no pandoc, no python-docx.


Roadmap

  • Settings tab for colors, folder names and heading levels
  • More entity kinds (people, clients) — currently one line of code, no UI
  • Community plugin directory submission

Why "Tachado"

Spanish for struck through — what happens to a task when you finally finish it.


License

MIT © Lucia Adams

For plugin developers

Search results and similarity scores are powered by semantic analysis of your plugin's README. If your plugin isn't appearing for searches you'd expect, try updating your README to clearly describe your plugin's purpose, features, and use cases.