NoteCast is a macOS Markdown notes app with a full notes window, a fast menu bar companion, and a scriptable cast command-line tool.
video.mp4
- Normal macOS app window with a left sidebar and large note editor.
- Menu bar extra for quick capture, recent notes, and Start at Login control.
- Folder support backed by SwiftData.
- Drag notes onto folders, or onto Unfiled to remove them from a folder.
- Markdown-friendly plain-text editor with
Cmd+Ssave in the main window. - In-place Markdown preview powered by Swift Markdown and rendered in a WebKit view.
- Basic fuzzy note search in the sidebar and through the
castCLI. - Compact quick-note window from the menu bar with
Cmd+Returnsave. - Shared persistent store for the app and CLI.
- Bundled
castCLI for terminal, scripts, pipes, and coding agents. - Bundled Agent Skills helper so agents can discover safe
castworkflows from the app package.
flowchart LR
User["User"] --> Browser["Main window<br/>NoteBrowserView"]
User --> Menu["Menu bar extra<br/>NoteMenuView"]
User --> Finder["Open Markdown file<br/>Finder / Dock"]
Scripts["Terminal, scripts, agents"] --> CLI["cast CLI"]
subgraph App["NoteCast app target"]
AppEntry["NoteCastApp<br/>shared ModelContainer"]
Browser --> BrowserStore["NoteBrowserStore<br/>manual refetching context"]
Menu --> MenuContext["Recent-note fetch<br/>fresh ModelContext"]
Menu --> Utility["NoteWindowManager<br/>entry/display windows"]
Utility --> EntryDisplay["NoteEntryView / NoteDisplayView"]
Finder --> Importer["NoteFileImporter"]
Browser --> SearchUI["NoteSearch<br/>sidebar ranking"]
end
subgraph Shared["Shared model and persistence"]
Persistence["NotePersistence<br/>schema + store URL"]
Models["Note + NoteFolder<br/>SwiftData models"]
Search["NoteSearch<br/>fuzzy scorer"]
Signal["NoteExternalChangeSignal<br/>cross-process refresh"]
end
subgraph Storage["On-disk user data"]
Store["~/Library/Application Support/NoteCast/NoteCast.store"]
Revision["NoteCast external-change revision file"]
end
subgraph CastTarget["cast target"]
CLI --> CastContext["ModelContext"]
CLI --> SearchCLI["NoteSearch<br/>list/search ranking"]
end
AppEntry --> Persistence
BrowserStore --> Models
MenuContext --> Models
EntryDisplay --> Models
Importer --> Models
CastContext --> Models
SearchUI --> Search
SearchCLI --> Search
Persistence --> Store
Models --> Store
CLI -- writes after mutations --> Signal
Signal --> Revision
Revision -- observed by --> Utility
Utility -- increments notesRevision --> BrowserStore
Utility -- increments notesRevision --> MenuContext
The app and CLI deliberately meet at the shared SwiftData layer. App windows and
the cast process create their own ModelContexts, but they all use
NotePersistence to open the same schema and store. App-side changes increment
NoteWindowManager.notesRevision; CLI changes publish NoteExternalChangeSignal
so the running app can refresh the main browser and menu bar recent-note list.
- Launch NoteCast from Xcode or Finder.
- Use the sidebar to select All Notes, Unfiled, a folder, or an individual note.
- Click New Note to create a note in the selected folder context.
- Click New Folder to organize notes.
- Drag note rows/cards onto folders to move them.
- Edit title/body/folder in the main note pane and press
Cmd+Sor click Save. - Right-click a note row or note card for note-level actions such as Copy Markdown and Delete Note.
The menu bar extra remains available while the full app is running. Use it for quick notes, recent-note access, or reopening the main NoteCast window.
The app embeds the CLI and its Agent Skills helper at:
NoteCast.app/Contents/Resources/bin/cast
NoteCast.app/Contents/Resources/skills/notecast-cast/SKILL.md
Install a convenient shell command:
ln -sf "/Applications/NoteCast.app/Contents/Resources/bin/cast" /usr/local/bin/castExamples:
cast add --title "Release idea" "Ship folder drag and drop"
ls -1 | cast # quick command-output capture, saved as a Markdown code block
echo "Piped markdown" | cast add --json # exact piped body for scripts/agents
cast list --json
cast search "relese noets" --json # fuzzy/ranked search
cast read NOTE_ID --raw
cast update NOTE_ID --title "Better title" "Updated body"
cast delete NOTE_ID --json
cast pathcast search TEXT and cast list --query TEXT use the same lightweight fuzzy
ranking as the app sidebar search. They search note titles, folder names, note
bodies, ids, MIME types, and creation source metadata, with title matches ranked
highest. The matcher handles exact matches, word prefixes, small typos, acronyms,
and subsequence-style matches. It is intentionally app-side search over the
SwiftData notes, not SQLite FTS.
This repository includes an Agent Skills-compatible helper at skills/notecast-cast/ so coding agents know how to use the cast CLI safely. App builds also package the same skill at:
/Applications/NoteCast.app/Contents/Resources/skills/notecast-cast
Install it by symlinking or copying the packaged skill into your agent's skills directory:
APP_SKILL="/Applications/NoteCast.app/Contents/Resources/skills/notecast-cast"
mkdir -p ~/.codex/skills ~/.claude/skills ~/.pi/agent/skills
ln -sfn "$APP_SKILL" ~/.codex/skills/notecast-cast # Codex
ln -sfn "$APP_SKILL" ~/.claude/skills/notecast-cast # Claude
ln -sfn "$APP_SKILL" ~/.pi/agent/skills/notecast-cast # PiWhen developing from a checkout, you can link the source copy instead:
ln -sfn "$PWD/skills/notecast-cast" ~/.codex/skills/notecast-castRestart the agent after installing. The skill expects either cast to be on PATH or the bundled command to exist at /Applications/NoteCast.app/Contents/Resources/bin/cast.
After restarting the agent, either ask for a NoteCast-related task naturally or name the skill explicitly in the prompt.
Example:
Create a note listing your three favorite scripting languages. For each one, add a brief explanation of why you like it.
Other useful prompts:
Use NoteCast to remember this decision: keep the CLI JSON output stable for scripts.
List my 10 most recent NoteCast notes.
Search my NoteCast notes for release decisions.
Read the NoteCast note with id NOTE_ID.
Update NOTE_ID with this new Markdown body: ...
The main editor defaults to Preview mode. Use the compact Preview/Edit segmented control in the window titlebar, the Editor menu, Cmd+1 for Preview, or Cmd+2 for Edit to switch between rendered HTML and Markdown source editing. Cmd+0 toggles the sidebar. Preview mode parses the current Markdown with Apple's Swift Markdown package, generates HTML, and displays it inside the existing editor pane using WKWebView. The default preview stylesheet is vendored from github-markdown-css at NoteCast/Preview/github-markdown.css, with a small NoteCast wrapper for readable width and app integration. It does not open a separate preview window.
NoteCast intentionally uses one shared SwiftData store for the app and CLI:
~/Library/Application Support/NoteCast/NoteCast.store
xcodebuild -project NoteCast.xcodeproj -scheme NoteCast -configuration Debug build
xcodebuild -project NoteCast.xcodeproj -scheme cast -configuration Debug buildBuilding the NoteCast scheme packages both Contents/Resources/bin/cast and Contents/Resources/skills/notecast-cast into the app bundle.
Run tests:
xcodebuild test -project NoteCast.xcodeproj -scheme NoteCast -configuration Debug -destination 'platform=macOS,arch=arm64'The Xcode project uses file-system-synchronized groups, so these logical folders are real folders on disk and are mirrored in Xcode's project navigator.
