AS Notes is a VS Code extension that turns your editor into a Personal Knowledge Management System (PKMS).
(Click for 1 minute Youtube video demo)
- Privacy focused - does not send your data anywhere
- Version control friendly (e.g. Git)
- Lightweight indexing of your notes (local sqlite3 WASM)
- Automatic wikilink / file rename tracking
- Logseq / Roam / Obsidian style
[[wikilinks]]with nested link support e.g.[[[[AS Notes]] Page]] - Links resolve to the target page anywhere in your workspace
- Renaming a link updates the target file and all matching references across the workspace
Toggle markdown TODOs with a keyboard shortcut:
- [ ] Marker for todo added
- [x] Marker for todo marked done
Marker for todo removed
Ctrl+Shift+Enter (Windows/Linux) / Cmd+Shift+Enter (macOS). Keybinding is configurable.
Note: Todo toggling requires an initialised workspace (
.asnotes/directory). See Getting started.
Ctrl+Alt+B (Windows/Linux) / Cmd+Alt+B (macOS)
Press Ctrl+Alt+J (Cmd+Alt+J on macOS) to create or open today's daily journal page.
Journal files are created as YYYY_MM_DD.md in a dedicated journals/ folder (configurable). New pages are generated from a journal_template.md template — edit it to add your own sections and prompts. The YYYY-MM-DD placeholder in the template is replaced with today's date on creation.
Note: Daily journal requires an initialised workspace (
.asnotes/directory). See Getting started.
AS Notes can work with knowledge bases created in Obsidian or Logseq due to similar file structures. There are format differences — Obsidian does not support nested wikilinks, and AS Notes does not use a block structure like Logseq. Front matter in AS Notes uses YAML.
A Pro licence unlocks premium features. Enter your licence key in VS Code settings under as-notes.licenceKey. When a valid key is active the status bar shows AS Notes (Pro).
Pro users can store sensitive notes in encrypted files. Any file with the .enc.md extension is treated as an encrypted note — it is excluded from the search index and never read as plain text by the extension.
Getting started with encryption:
- Run AS Notes: Set Encryption Key from the Command Palette. Your passphrase is stored securely in the OS keychain (VS Code SecretStorage) — it is never written to disk or settings files.
- Create an encrypted note with AS Notes: Create Encrypted Note (or AS Notes: Create Encrypted Journal Note for a dated journal entry).
- Write your note in the editor. When you want to lock it, run AS Notes: Encrypt All Notes — all plaintext
.enc.mdfiles will be encrypted in place. - To read a note, run AS Notes: Decrypt All Notes — files are decrypted in place using your stored passphrase.
Encryption details:
- Algorithm: AES-256-GCM with a per-encryption random 12-byte nonce
- Key derivation: PBKDF2-SHA256 (100,000 iterations) from your passphrase
- File format: a single-line
ASNOTES_ENC_V1:<base64url payload>marker — easily detectable by tooling - A git pre-commit hook is automatically installed at
.git/hooks/pre-committo prevent accidentally committing an unencrypted.enc.mdfile. The hook is self-updating — if AS Notes detects a stale version it replaces it automatically on the nextRebuild Indexor periodic scan. If a commit is unexpectedly blocked, run AS Notes: Encrypt All Notes first.
Commands:
AS Notes: Set Encryption Key— save passphrase to OS keychainAS Notes: Clear Encryption Key— remove the stored passphraseAS Notes: Encrypt All Notes— encrypt all plaintext.enc.mdfilesAS Notes: Decrypt All Notes— decrypt all encrypted.enc.mdfilesAS Notes: Create Encrypted Note— create a new named.enc.mdfileAS Notes: Create Encrypted Journal Note— create today's journal entry as.enc.mdAS Notes: Encrypt Current Note— encrypt the active.enc.mdfile (reads unsaved editor content)AS Notes: Decrypt Current Note— decrypt the active.enc.mdfile (reads from disk)
Planned Pro features:
- HTML/wiki export
- UI password lock
To obtain a licence key, contact appsoftware.com.
https://marketplace.visualstudio.com/items?itemName=appsoftwareltd.as-notes
For a sample knowledge base, clone https://github.com/appsoftwareltd/as-notes-demo-notes and follow the instructions there to initialise.
AS Notes activates when it finds a .asnotes/ directory in your workspace root (similar to .git/ or .obsidian/). Without it, the extension runs in passive mode — you'll see a status bar item inviting you to initialise.
To initialise:
- Open the Command Palette (
Ctrl+Shift+P) - Run AS Notes: Initialise Workspace
This creates the .asnotes/ directory, builds a SQLite index of all markdown files, and activates all features. The index file (.asnotes/index.db) is excluded from git by an auto-generated .gitignore.
If the index becomes stale or corrupted, run AS Notes: Rebuild Index from the Command Palette. This drops and recreates the entire index with a progress indicator.
Every [[wikilink]] in a markdown file is highlighted in blue. When your cursor is inside a link, that specific link is highlighted with a brighter blue, bold, and underlined — so you always know which link you're about to interact with.
Links can contain other links:
[[Specific [[Topic]] Details]]
[[Specific [[[[Topic]] Variant]] Details]]This creates three navigable targets:
| You click on... | You navigate to... |
|---|---|
[[Topic]] |
Topic.md |
[[Specific or Details]] (the outer portions) |
Specific [[Topic]] Details.md |
[[[[Topic]] Variant]] (the outer portions) |
[[Topic]] Variant.md |
Nesting works to arbitrary depth. The extension always identifies the innermost link under your cursor for highlighting, hover, and click targets.
Ctrl+Click (Cmd+Click on macOS) on any wikilink to open the target .md file. Links resolve globally across the workspace (see Subfolder link resolution).
Navigating to a page that doesn't exist creates it automatically, so you can write forward-references before the target page exists.
Hover over any wikilink to see:
- The target filename (e.g.
My Page.md) - Whether the file already exists or will be created on click
- The number of backlinks (other pages that link to this target)
When you edit a wikilink's text and move your cursor away (or switch files), AS Notes detects the change and offers to:
- Rename the corresponding
.mdfile (if it exists) - Update every matching link across all markdown files in the workspace
A single confirmation dialog covers all affected nesting levels. For example, editing [[Inner]] inside [[Outer [[Inner]] text]] offers to rename both the inner and outer pages.
You can decline — the link text change is kept but files and other links are left untouched.
[[my page]] resolves to My Page.md regardless of OS. On case-sensitive filesystems (Linux), a directory scan finds the match. On Windows and macOS the filesystem handles it natively.
Invalid filename characters (/ ? < > \ : * | ") are replaced with _:
[[What is 1/2 + 1/4?]] → What is 1_2 + 1_4_.mdDefine alternative names for a page using YAML front matter at the top of any markdown file:
---
aliases:
- Short Name
- Another Name
---Or inline array style:
---
aliases: [Short Name, Another Name]
---Linking to [[Short Name]] or [[Another Name]] navigates to the page that declares those aliases — no extra file is created.
- Hover tooltips show alias resolution:
Short Name.md → ActualPage.md - Rename tracking is alias-aware — editing an alias link offers to update front matter and all matching references
- Backlink counts include both direct and alias references
- Alias values are plain strings; accidental
[[/]]brackets are stripped automatically
Wikilinks resolve globally across the workspace, not just in the current directory. The extension uses the persistent index to find matching files anywhere in the folder tree.
Resolution order:
- Direct filename match —
[[My Page]]findsMy Page.mdanywhere in the workspace - Alias match — if no file matches, check page aliases
- Auto-create — if nothing matches, create the file in the same directory as the source
Disambiguation — when multiple files share the same name (e.g. notes/Topic.md and archive/Topic.md):
- A file in the same directory as the source always wins
- Otherwise, the closest folder is preferred (measured by directory distance)
Type [[ in any markdown file to trigger autocomplete, listing all indexed pages and aliases. The list filters as you type.
- Page suggestions show the page name (without
.md), with folder paths for disambiguation when names collide - Alias suggestions show the alias with an arrow to the canonical page (e.g.
→ ActualPage) - Auto-close — selecting a suggestion inserts the name and appends
]] - Nested wikilinks —
[[inside an unclosed[[...starts a new autocompletion for the inner link - Completions are suppressed inside front matter blocks
AS Notes maintains a SQLite database (.asnotes/index.db) that indexes all markdown files in the workspace. The index tracks:
- Pages — file paths, filenames, titles (extracted from the first
# heading) - Links — every wikilink in every file, with line, column, nesting depth, and parent references
- Aliases — alternative names declared in YAML front matter, with sanitised filenames
- Backlinks — reverse lookups for hover tooltips (including alias references)
The index is kept up-to-date automatically:
- On file save, create, delete, or rename
- On editor switch (captures unsaved edits)
- Via a configurable periodic background scan
Press Ctrl+Shift+Enter (Cmd+Shift+Enter on macOS) on any line in a markdown file to cycle through todo states:
| Current state | After toggle |
|---|---|
buy milk |
- [ ] buy milk |
- [ ] buy milk |
- [x] buy milk |
- [x] buy milk |
buy milk |
- List-aware:
- some textbecomes- [ ] some text(no re-wrapping) - Indentation preserved: works correctly on indented/nested lines
- Multi-cursor: each cursor's line is toggled independently
- Configurable keybinding: search for "AS Notes: Toggle Todo" in Keyboard Shortcuts (
Ctrl+K Ctrl+S)
The AS Notes Tasks panel appears in the Explorer sidebar when the workspace is initialised. It provides a tree view of all todo items across your markdown files, grouped by page.
- Show TODO only (default: on) — filters the list to show only unchecked (
- [ ]) tasks. Toggle this with the filter icon in the panel title bar or via the AS Notes: Toggle Show TODO Only command. - Click to navigate — clicking a task opens the file and scrolls to the exact line.
- Inline toggle — each task has a check button that toggles its done/todo state directly from the panel, without stealing focus from your active editor.
- Keyboard shortcut — press
Ctrl+Alt+T(Cmd+Alt+T on macOS) to toggle the task panel's visibility. - Live sync — the panel refreshes automatically on file save, edit, create, delete, rename, todo toggle, and periodic background scans.
The Backlinks panel shows all incoming links to the active markdown file. Open it with Ctrl+Alt+B (Cmd+Alt+B on macOS), or click the references icon in the editor title bar.
- Rich context — each backlink shows the surrounding line with the wikilink highlighted.
- Grouped by page — organised by source file with page title and path.
- Click to navigate — click any backlink entry to jump directly to the source file and line.
- Alias-aware — includes links that target the page via its aliases, not just direct filename references.
- Live sync — the panel auto-updates when you switch files, save, or when the index changes.
- Editor-side display — opens beside your active editor (like Markdown Preview), giving you a spacious view of backlink context.
Press Ctrl+Alt+J (Cmd+Alt+J on macOS) to create or open today's daily journal. The extension creates a dated markdown file in a dedicated journal folder — one file per day.
- Filename format:
YYYY_MM_DD.md(e.g.2026_03_02.md) - Journal folder: defaults to
journals/(configurable viaas-notes.journalFolder) - Template-based: new files are created from
journal_template.md, withYYYY-MM-DDreplaced by the current date. Edit the template to customise future pages. - Auto-setup: the journal folder and default template are created on first use
- Instant indexing: new journal files are indexed immediately for wikilink completion and backlinks
- Idempotent: pressing the shortcut again on the same day opens the existing file
| Setting | Default | Description |
|---|---|---|
as-notes.periodicScanInterval |
300 |
Seconds between automatic background scans for file changes. Set to 0 to disable. Minimum: 30. |
as-notes.journalFolder |
journals |
Folder for daily journal files, relative to workspace root. |
as-notes.licenceKey |
(empty) | AS Notes Pro licence key. Scope: machine (not synced). |
The extension activates for files with .md and .markdown extensions.
A wikilink is any text enclosed in double square brackets:
See [[Page Name]] for details.The text between the brackets becomes both the display text and the page name. The target file is Page Name.md in the same directory.
Wikilinks can be nested by adding more bracket pairs:
[[Outer [[Inner]] text]]The parser uses a stack-based bracket matching algorithm. Each pair of [[ and ]] that balances correctly forms a valid wikilink. See docs/TECHNICAL.md for a detailed explanation of the parsing algorithm and edge cases.
# Install dependencies
npm install
# Build the extension
npm run build
# Watch mode (rebuilds on changes)
npm run watch
# Run unit tests
npm test
# Type-check
npm run lintPress F5 in VS Code to launch the Extension Development Host with the extension loaded.
The debug version takes precedence over the marketplace install, so both can coexist.
VS Code remembers the last folder opened in the Extension Development Host. The demo knowledge base is designed to cover common usage scenarios.
Unit tests use vitest and cover the wikilink parser, offset-based lookup, segment computation, index service CRUD, title extraction, rename detection data flow, and nested link indexing. Run with npm test.
| File | Purpose |
|---|---|
src/extension.ts |
Entry point — activation model (passive/full mode), commands, index triggers |
src/Wikilink.ts |
Model class — positions, page name, filename sanitisation |
src/WikilinkService.ts |
Stack-based parser, innermost-offset lookup, segment computation |
src/WikilinkDecorationManager.ts |
Editor decorations (default + active highlight) |
src/WikilinkDocumentLinkProvider.ts |
Ctrl+Click navigation via non-overlapping segments (alias-aware tooltips) |
src/WikilinkHoverProvider.ts |
Hover tooltips with target file existence, alias indicator, backlink count |
src/WikilinkFileService.ts |
File resolution — index-aware global matching, alias resolution, subfolder disambiguation |
src/WikilinkRenameTracker.ts |
Rename detection (index-backed), alias vs direct rename classification, workspace-wide updates |
src/WikilinkCompletionProvider.ts |
Wikilink autocomplete — [[ trigger, page + alias suggestions, auto-close, nested link support |
src/CompletionUtils.ts |
Pure utilities for completion logic — bracket detection, front matter detection |
src/IndexService.ts |
SQLite data layer — schema, CRUD, content indexing, alias management, task indexing, nesting detection |
src/IndexScanner.ts |
VS Code filesystem scanning — file indexing, full scan, stale scan |
src/FrontMatterService.ts |
Lightweight YAML front matter parser — alias extraction, in-place alias updates |
src/PathUtils.ts |
Pure utilities — path distance calculation, filename sanitisation |
src/TodoToggleService.ts |
Pure todo toggle logic — three-state cycle (plain / unchecked / done) |
src/TaskPanelProvider.ts |
Explorer tree view — task list grouped by page, todo-only filter, click-to-navigate |
src/BacklinkPanelProvider.ts |
Webview panel — backlinks display with context, grouped by source page, click-to-navigate |
src/JournalService.ts |
Pure journal logic — date formatting, template processing, path construction |
src/LicenceService.ts |
Pure licence key validation logic — no VS Code imports |
src/LicenceActivationService.ts |
Licence activation stub — SecretStorage token management, server call placeholder |
build.mjs |
Custom esbuild script — bundles extension, copies WASM binary |
src/test/ |
Unit tests (vitest) |
For a deep dive into the technical design, see docs/TECHNICAL.md.
Releases are published to the VS Code Marketplace manually, then a GitHub Release is created automatically when a version tag is pushed.
Step 1 — bump the version
Update version in package.json and add an entry to CHANGELOG.md.
Step 2 — publish to the VS Code Marketplace
npm run build
npx @vscode/vsce package
npx @vscode/vsce login appsoftwareltd # enter PAT token if auth expired
npx @vscode/vsce publishStep 3 — tag and push
git add package.json CHANGELOG.md README.md
git commit -m "Release v1.x.x" # change version
git tag v1.x.x # change version
git push origin main --tagsPushing the tag triggers the Release workflow, which creates a GitHub Release automatically with auto-generated release notes and the VS Code Marketplace install link.
This software is provided "as is", without warranty of any kind, express or implied. The authors and contributors accept no responsibility or liability for any loss, corruption, or damage to data, files, or systems arising from the use or misuse of this extension, including but not limited to operations that create, rename, move, or modify files in your workspace.
You are solely responsible for maintaining backups of your data. It is strongly recommended to use version control (e.g. git) or another backup strategy for any notes or files you manage with this extension.
This extension is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License (CC BY-NC-SA 4.0).
You are free to use, share, and adapt this extension for non-commercial purposes with attribution. Commercial use requires a separate commercial license. See LICENSE for full terms or contact us https://www.appsoftware.com/contact.



