glushchenko/fsnotes
Notes manager for macOS/iOS
Single-maintainer risk — review before adopting
worst of 4 axestop contributor handles 94% of recent commits; no tests detected
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 2w ago
- ✓4 active contributors
- ✓MIT licensed
Show 4 more →Show less
- ✓CI configured
- ⚠Small team — 4 contributors active in recent commits
- ⚠Single-maintainer risk — top contributor 94% of recent commits
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Mixed → Healthy if: diversify commit ownership (top <90%)
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/glushchenko/fsnotes)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/glushchenko/fsnotes on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: glushchenko/fsnotes
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/glushchenko/fsnotes shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Single-maintainer risk — review before adopting
- Last commit 2w ago
- 4 active contributors
- MIT licensed
- CI configured
- ⚠ Small team — 4 contributors active in recent commits
- ⚠ Single-maintainer risk — top contributor 94% of recent commits
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live glushchenko/fsnotes
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/glushchenko/fsnotes.
What it runs against: a local clone of glushchenko/fsnotes — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in glushchenko/fsnotes | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 46 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of glushchenko/fsnotes. If you don't
# have one yet, run these first:
#
# git clone https://github.com/glushchenko/fsnotes.git
# cd fsnotes
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of glushchenko/fsnotes and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "glushchenko/fsnotes(\\.git)?\\b" \\
&& ok "origin remote is glushchenko/fsnotes" \\
|| miss "origin remote is not glushchenko/fsnotes (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "FSNotes iOS/AppDelegate.swift" \\
&& ok "FSNotes iOS/AppDelegate.swift" \\
|| miss "missing critical file: FSNotes iOS/AppDelegate.swift"
test -f ".swiftlint.yml" \\
&& ok ".swiftlint.yml" \\
|| miss "missing critical file: .swiftlint.yml"
test -f "FSNotes iOS Share/ShareViewController.swift" \\
&& ok "FSNotes iOS Share/ShareViewController.swift" \\
|| miss "missing critical file: FSNotes iOS Share/ShareViewController.swift"
test -f "FSNotes iOS/Assets.xcassets/Colors/fsColor.colorset/Contents.json" \\
&& ok "FSNotes iOS/Assets.xcassets/Colors/fsColor.colorset/Contents.json" \\
|| miss "missing critical file: FSNotes iOS/Assets.xcassets/Colors/fsColor.colorset/Contents.json"
test -f ".github/ISSUE_TEMPLATE/bug_report.yml" \\
&& ok ".github/ISSUE_TEMPLATE/bug_report.yml" \\
|| miss "missing critical file: .github/ISSUE_TEMPLATE/bug_report.yml"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 46 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~16d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/glushchenko/fsnotes"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
FSNotes is a dual-platform (macOS/iOS) markdown-first notes manager written in Swift that emphasizes speed, keyboard navigation, and offline-first syncing via iCloud Drive or Dropbox. It handles 10k+ note files efficiently with features like syntax highlighting, cross-note linking via [[double brackets]], inline images, AES-256 encryption, and optional Git versioning—fundamentally solving the problem of managing large personal knowledge bases without cloud lock-in. Dual-app monorepo structure: FSNotes iOS/ contains the iOS SwiftUI/UIKit app with AppDelegate and Assets, FSNotes iOS Share/ contains the iOS 13+ share extension with its own bundle, and the top-level project includes macOS app files (.plist configs). State is managed via platform-native patterns (no Redux visible); localization uses Xcode .xcstrings and .lproj bundles (bartycrouch for i18n automation).
👥Who it's for
Power users and knowledge workers on Apple platforms who want a fast, privacy-respecting notes app with markdown support and sync flexibility; developers contributing to the macOS/iOS ecosystem seeking a real-world Swift codebase example with dual-platform architecture.
🌱Maturity & risk
Production-ready and actively maintained. The project is published on both the macOS App Store (ID 1277179284) and iOS App Store (ID 1346501102), has comprehensive localization across 5+ languages (es, pt, ru, uk, zh), and demonstrates stable architecture patterns (.swiftlint.yml enforced code quality, .travis.yml CI setup). However, the repo does not expose public metrics (stars, last commit date) in provided data; the 2M+ lines of Swift code and multi-version plist configurations suggest a mature, production application.
Low-to-medium risk. The codebase is single-language Swift (no external npm/CocoaPods dependency graph visible in file list), reducing supply-chain attack surface. Primary risks: (1) single maintainer (glushchenko) visible in repo name—no backup contributors listed; (2) iOS Share extension and encryption features are security-sensitive subsystems requiring careful code review; (3) Git integration and file sync logic are complex and could introduce data loss if broken. No public issue backlog or PR metrics provided to assess active community engagement.
Active areas of work
Active maintenance focused on iOS/macOS feature parity and localization: the repo includes recent string localization files for Simplified Chinese (zh-Hans-CN), Portuguese (pt), Russian (ru), and Ukrainian (uk), and has .bartycrouch.toml config in both iOS app and Share extension directories, indicating ongoing translation automation. The presence of FSNotes Info (Notarized).plist suggests recent macOS notarization work for App Store compliance.
🚀Get running
git clone https://github.com/glushchenko/fsnotes.git
cd fsnotes
# Open in Xcode (no package manager visible; use native Xcode build)
open FSNotes.xcodeproj
# Or via xcodebuild:
xcodebuild -scheme "FSNotes" -configuration Release
Daily commands:
Open FSNotes.xcodeproj in Xcode → Select target (FSNotes iOS or macOS variant) → Cmd+R to run. For iOS Share extension testing, build the app target first, then run the share extension scheme separately. No external build server required (native Xcode project).
🗺️Map of the codebase
FSNotes iOS/AppDelegate.swift— iOS app entry point and lifecycle management — all contributors must understand how the app initializes and handles background tasks..swiftlint.yml— Code style and linting rules enforced across the codebase — essential for maintaining consistency in all pull requests.FSNotes iOS Share/ShareViewController.swift— iOS share extension entry point — critical for understanding the iOS app's external integration layer and data handling.FSNotes iOS/Assets.xcassets/Colors/fsColor.colorset/Contents.json— Centralized color theming configuration — affects all UI styling across light/dark modes..github/ISSUE_TEMPLATE/bug_report.yml— Issue reporting standardization — guides contributors on expected bug report structure and triage process.
🛠️How to make changes
Add a new localization language
- Create a new
.lprojfolder inFSNotes iOS Share/with language code (e.g.,de.lprojfor German) (FSNotes iOS Share/) - Copy
Localizable.stringsfrom an existing language folder and update all translations (FSNotes iOS Share/es.lproj/Localizable.strings) - Copy
InfoPlist.stringsand localize the app-level strings (FSNotes iOS Share/es.lproj/InfoPlist.strings) - Update
.bartycrouch.tomlto register the new language for the share extension (FSNotes iOS Share/.bartycrouch.toml)
Add new UI assets (icons, images)
- Navigate to the appropriate imageset folder in
FSNotes iOS/Assets.xcassets/(e.g.,Icons,Editor,Sidebar) (FSNotes iOS/Assets.xcassets/Icons/) - Add image files at 1x, 2x, and 3x scales (or 76, 152, 167pt for iPad) with appropriate naming conventions (
FSNotes iOS/Assets.xcassets/Sidebar/sidebar_notes.imageset/Notes-76.png) - Update the
Contents.jsonfile in the imageset folder with image references and scale factors (FSNotes iOS/Assets.xcassets/Sidebar/sidebar_notes.imageset/Contents.json)
Update color theme (light/dark mode)
- Open
FSNotes iOS/Assets.xcassets/Colors/fsColor.colorset/Contents.jsonin a text editor (FSNotes iOS/Assets.xcassets/Colors/fsColor.colorset/Contents.json) - Add or modify color entries with separate definitions for
LightandDarkappearances (FSNotes iOS/Assets.xcassets/Colors/fsColor.colorset/Contents.json) - Reference the new color in UI code using
UIColor(named: "colorName")in Swift (FSNotes iOS/AppDelegate.swift)
🔧Why these technologies
- Swift / SwiftUI — Native iOS development language; direct access to Apple frameworks for efficient note management and file system integration
- Share Extension (AppKit/UIKit) — OS-level mechanism for seamless content capture from other apps without user friction
- File-based storage (iCloud Drive / Dropbox sync) — Enables cloud synchronization without database dependency; supports multi-device access and version control
- Markdown format — Human-readable, portable, widely supported; enables syntax highlighting and cross-note linking without binary lock-in
- SwiftLint — Enforces consistent code style across contributors; prevents technical debt accumulation in large codebases
- Bartycrouch — Automates localization management; reduces manual translation key maintenance across multiple languages
⚖️Trade-offs already made
-
File-based storage over embedded database (SQLite/Realm)
- Why: Simplifies iCloud/Dropbox sync and allows external editor compatibility; users own their data
- Consequence: Requires file system polling for change detection; less efficient for large-scale queries; indexing must be manual
-
iOS Share Extension as separate app target
- Why: Allows content capture without foregrounding main app; quick interaction
- Consequence: Code duplication between main app and extension; requires separate localization and asset management
-
Multi-language support with separate
.lprojfolders per language- Why: Leverages native iOS localization system; familiar to Apple developers
- Consequence: Scales linearly with languages; requires translation management tooling (Bartycrouch)
-
Markdown-first with optional plaintext support
- Why: Markdown is rich enough for note-taking but lightweight; enables syntax highlighting and advanced formatting
- Consequence: Users must learn Markdown syntax; limited WYSIWYG editing experience
🚫Non-goals (don't propose these)
- Real-time collaborative editing (no presence/conflict resolution)
- Server-side storage or authentication (file-system native only)
- Cross-platform (macOS/iOS only; no Android or web clients in this repo)
- Enterprise encryption key management (AES-256 is client-only, no key server)
- Full WYSIWYG rich text editor (Markdown-first, not rich text)
- Offline-first data synchronization with conflict resolution (relies on iCloud/Dropbox native sync)
🪤Traps & gotchas
No CocoaPods/SPM manifest visible: app likely uses Apple frameworks only, but verify Xcode build settings for any vendored frameworks. Share extension signing: the iOS Share extension has its own entitlements file (FSNotes iOS Share/.entitlements), which must match the main app's team ID and provisioning profile—mismatches cause silent failures. Localization automation: bartycrouch is configured but not a visible dependency; ensure it's installed (gem install bartycrouch) before running build phases. Git integration: the app advertises Git versioning as a feature, but no .git or Git framework configuration visible in top 60—implementation likely in unexposed files; may require libgit2 or subprocess calls. iCloud Drive sync: requires proper entitlements and testing on physical devices; simulator testing will fail silently for CloudKit operations.
🏗️Architecture
💡Concepts to learn
- TextBundle and EncryptedTextBundle containers — FSNotes' primary file format for iOS sync and sharing; understanding the directory structure (
.textbundlewithtext.markdown+ attachments) is required for implementing import/export and share extension logic - AES-256 encryption (symmetric cryptography) — FSNotes advertises encrypted notes as a core feature; contributors touching encryption must understand key derivation, IV handling, and secure deletion to avoid data loss or security breaches
- iCloud Drive CloudKit sync — The primary sync mechanism for iOS/macOS apps on Apple platforms; understanding CloudKit's document-based sync, conflict resolution, and entitlements is essential for debugging sync failures
- iOS Share Extension / Action Extension — FSNotes iOS includes a dedicated share extension (
FSNotes iOS Share/); contributors must understand extension bundle IDs, entitlements inheritance, and memory constraints (extensions run in sandboxed processes) - Code syntax highlighting with 30+ language support — A marquee feature; likely implemented via a tokenizer/lexer (possibly TreeSitter or custom regex-based); changing highlighting requires careful testing across multiple languages
- Wikilink-style cross-note linking ([[double brackets]]) — FSNotes uses the PKM convention
[[note-title]]for backlinks; implementing this requires link parsing, note resolution, and graph visualization logic - macOS App Notarization — The presence of
FSNotes Info (Notarized).plistindicates the macOS app is notarized for Gatekeeper; new macOS builds must pass notarization or users will see security warnings
🔗Related repos
apple/swift-markdown— Official Swift markdown parsing library; FSNotes likely uses this or a similar parser for rendering markdown syntaxjpsim/SwiftLint— The.swiftlint.ymlfile in this repo delegates to SwiftLint; understanding its rules is essential for contributing code that passes CICarthage/Carthage— If FSNotes uses any binary frameworks (likely for encryption or Git), Carthage or SPM manages them; check build phasesgitpub/GitPub— Alternative Git-aware notes manager; shares similar feature set (markdown, sync, encryption) and could provide design inspirationobsidianmd/obsidian-releases— Market-leading cross-platform notes app with PKM features (tags, links, graph); FSNotes' feature roadmap likely references Obsidian's capabilities
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add localization string validation tests for iOS Share extension
The repo has multiple language localizations (es, pt, ru, uk, zh-Hans, zh-Hans-CN) across FSNotes iOS Share extension with .strings and .xcstrings files, but no automated validation ensures all keys are translated consistently across languages. This prevents missing translations and key mismatches that could crash the share extension at runtime.
- [ ] Create Tests/ directory with LocalizationValidationTests.swift
- [ ] Parse all .lproj/Localizable.strings files in FSNotes iOS Share/
- [ ] Verify all language files contain the same keys
- [ ] Add test to CI workflow (.travis.yml or new GitHub Action) to run on PRs
- [ ] Document findings in CONTRIBUTING.md
Add GitHub Actions workflow for SwiftLint enforcement with PR annotations
.swiftlint.yml exists but .travis.yml is outdated (Travis CI). No modern GitHub Actions workflow enforces linting on PRs. This means code style violations slip through and maintainer must manually catch them. A SwiftLint GitHub Action would catch issues before review.
- [ ] Create .github/workflows/swiftlint.yml
- [ ] Configure SwiftLint to run on all .swift files in FSNotes iOS, FSNotes iOS Share, and FSNotes macOS (if present)
- [ ] Use github-actions-swiftlint or similar to annotate PR lines with violations
- [ ] Reference .swiftlint.yml configuration in workflow
- [ ] Update CONTRIBUTING.md with local lint run instructions
Add unit tests for ShareViewController.swift integration with NSMutableAttributedString extension
ShareViewController.swift in FSNotes iOS Share imports and uses NSMutableAttributedString+.swift extension, but no tests verify that shared content (formatted text, images, links) is correctly parsed and formatted before passing to the main app. This is error-prone given the complexity of attributed string handling.
- [ ] Create FSNotes iOS Share/ShareViewControllerTests.swift
- [ ] Add test cases for: plain text sharing, formatted text sharing, shared images, shared links
- [ ] Test NSMutableAttributedString+ extension methods directly with various input types
- [ ] Mock necessary UIActivityViewController dependencies
- [ ] Add tests to CI workflow to run on each commit to FSNotes iOS Share/
🌿Good first issues
- Add unit tests for NSMutableAttributedString+.swift: The share extension's
NSMutableAttributedString+.swift(line processing for TextBundle) has no visible test file in the repo. Add XCTest cases covering edge cases like nested bold/italic, links, and code spans. - Expand localization coverage to Japanese and German: Current
.lprojfolders cover es, pt, ru, uk, zh-Hans-CN, zh-Hans, but not ja or de. Addja.lproj/andde.lproj/directories with translatedLocalizable.stringsfiles and run bartycrouch to sync. - Document macOS app encryption feature in README: The README lists AES-256 encryption as a feature, but no explanation of how to enable/configure it for users. Add a section with screenshots or steps in
README.mdand linked language translations.
⭐Top contributors
Click to expand
Top contributors
- @glushchenko — 94 commits
- @hackmajoris — 3 commits
- @afaden — 2 commits
- @jdve — 1 commits
📝Recent commits
Click to expand
Recent commits
d50663d— Merge pull request #1937 from glushchenko/hotfix-pins (glushchenko)24b9f54— - Fixed an issue with printing images (glushchenko)593ad79— Merge pull request #1935 from glushchenko/hotfix-pins (glushchenko)7b9bc90— - fixes pins loading on iOS and some cases on macOS (glushchenko)6662aa5— fix: pinned notes getting lost in iCloud build (jdve)8142b69— #1928 (glushchenko)d20c46f— #1915 (glushchenko)3adbe07— #1906 (glushchenko)d512ec3— #1911 (glushchenko)1499360— #1905 (glushchenko)
🔒Security observations
FSNotes is a notes management application with moderate security posture. Key concerns include: (1) inability to audit dependencies due to missing lock files, (2) potential unencrypted data storage for sensitive note content, (3) limited visible security hardening in configuration files, and (4) no explicit security testing in CI/CD. The application appears well-structured for a native iOS/macOS project, but explicit data protection mechanisms and dependency vulnerability scanning should be implemented. The project should prioritize implementing end-to-end encryption for notes and establishing automated security scanning in the build pipeline.
- Medium · Missing Dependency Lock File Analysis —
Package management configuration (not provided). No Package.resolved, Podfile.lock, or similar dependency lock file was provided for analysis. This makes it impossible to verify if the project uses vulnerable dependency versions. Swift Package Manager, CocoaPods, or Carthage dependencies cannot be audited for known CVEs. Fix: Ensure all dependency lock files are committed to version control. Regularly run 'swift package update' with vulnerability scanning, or use tools like OWASP Dependency-Check to identify known vulnerable dependencies. - Medium · Potential Unencrypted Data Storage —
FSNotes iOS/Info.plist, FSNotes Info (Notarized).plist, app data storage. The application handles notes and appears to support cloud sync (iCloud Drive, Dropbox). Without explicit encryption configuration in the provided files, sensitive note content may be stored in plaintext in app sandboxes or sync services. The Info.plist files don't show explicit data protection class configurations. Fix: Implement NSFileProtectionComplete or NSFileProtectionCompleteUnlessOpen for all sensitive data. Use CryptoKit for local encryption. Enable App Transport Security (ATS) and verify all cloud sync connections use TLS 1.2+. - Low · Missing Code Signing Configuration Details —
FSNotes iOS Share/FSNotes iOS Share.entitlements. While a notarization plist exists (FSNotes Info (Notarized).plist), the entitlements files lack explicit security hardening details visible in the provided structure. Entitlements should be minimal and restrictive. Fix: Review and minimize entitlements to only what is strictly necessary. Ensure Data Protection, File Access, and Network configurations are explicitly defined and restrictive. - Low · No Visible Security Testing Configuration —
.travis.yml. No security scanning tools (e.g., static analysis, dynamic analysis, or SAST) are evident in CI/CD configuration (.travis.yml). The project should enforce security checks in the build pipeline. Fix: Integrate SwiftLint (already present) with security-focused rules. Add SAST tools like Sonarqube, MobSF, or Fortify to the CI/CD pipeline. Consider adding runtime security checks for iOS. - Low · Localization Files May Contain Sensitive Strings —
FSNotes iOS/*/Localizable.strings, FSNotes iOS Share/*/Localizable.strings. Multiple localization files (.strings) are present across multiple languages. If these contain hardcoded API keys, endpoints, or sensitive configuration, they could be exposed. Executable strings in Localizable files should be reviewed. Fix: Audit all .strings files to ensure no secrets, API keys, or sensitive endpoints are hardcoded. Use environment variables or secure configuration management for dynamic values.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.