Add Moss Pikachu macOS app (projects) - #335
Conversation
Introduce a floating desktop pet search launcher that indexes ~/Downloads via Moss SessionIndex and supports natural-language local file search. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Samanyu Goyal seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
Limit SessionIndex watching to ~/Downloads/cwp-stuff, revert the custom search field to SwiftUI focus handling, and fix floating pet dragging with screen-coordinate tracking. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Pull request overview
Adds a new macOS-only app under apps/moss-pikachu/ that runs a SwiftUI floating “desktop pet” and uses a bundled Python worker (moss_worker.py) to build/query a Moss Session-based semantic index over a scoped Downloads folder.
Changes:
- Introduces a SwiftUI/NSPanel-based UI (floating pet, search overlay, settings window) plus global hotkey support.
- Adds a Swift↔Python line-delimited JSON bridge (
MossBridge.swift↔moss_worker.py) and file monitoring/index manifest persistence. - Adds developer scripts/docs for venv setup, worker runs, and a basic smoke test for indexing/querying.
Reviewed changes
Copilot reviewed 44 out of 49 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/moss-pikachu/README.md | Setup, dev workflow, and architecture notes for the app |
| apps/moss-pikachu/.env.example | Template for Moss credentials |
| apps/moss-pikachu/.gitignore | Ignores Xcode build output, venv, and env files |
| apps/moss-pikachu/scripts/setup-moss-venv.sh | Creates venv and installs Moss + document parsers |
| apps/moss-pikachu/scripts/run-moss-worker.sh | Convenience runner for the Python worker |
| apps/moss-pikachu/scripts/smoke-test-indexing.sh | Minimal end-to-end indexing/query smoke test |
| apps/moss-pikachu/MossPikachu/MossPikachuApp.swift | App entrypoint (LSUIElement-style settings-only scene) |
| apps/moss-pikachu/MossPikachu/AppDelegate.swift | App lifecycle wiring: hotkey, overlay, pet, settings, service init |
| apps/moss-pikachu/MossPikachu/Models/IndexScope.swift | Defines the indexed folder scope (currently ~/Downloads/cwp-stuff) |
| apps/moss-pikachu/MossPikachu/Models/SearchResult.swift | Search result model returned to the UI |
| apps/moss-pikachu/MossPikachu/Models/UserSettings.swift | Stored user settings (cloud sync, etc.) |
| apps/moss-pikachu/MossPikachu/Models/PetState.swift | Pet animation state model |
| apps/moss-pikachu/MossPikachu/Models/FileSystemEvent.swift | Index manifest record/structure |
| apps/moss-pikachu/MossPikachu/Services/SearchService.swift | High-level indexing + querying orchestration |
| apps/moss-pikachu/MossPikachu/Services/MossBridge.swift | Subprocess management + JSON request/response plumbing |
| apps/moss-pikachu/MossPikachu/Services/FileMonitor.swift | FSEvents file watching + debouncing |
| apps/moss-pikachu/MossPikachu/Services/IndexManager.swift | Tracks indexed file mtimes via Application Support manifest |
| apps/moss-pikachu/MossPikachu/Services/HotKeyManager.swift | Registers global ⌘⇧M hotkey via Carbon |
| apps/moss-pikachu/MossPikachu/Services/NotificationManager.swift | Lightweight toast notifications |
| apps/moss-pikachu/MossPikachu/Services/AppLogger.swift | Debug logging to console + file |
| apps/moss-pikachu/MossPikachu/Services/DotEnvLoader.swift | .env discovery/parsing for dev credentials |
| apps/moss-pikachu/MossPikachu/Services/CapvoltSticker.swift | Loads sticker image asset (bundle + dev fallbacks) |
| apps/moss-pikachu/MossPikachu/Resources/moss_worker.py | Python worker: extraction, chunking, Session operations |
| apps/moss-pikachu/MossPikachu/Resources/config.json | Bundled config artifact (currently unused by code) |
| apps/moss-pikachu/MossPikachu/Views/SearchOverlayController.swift | NSPanel controller for the search overlay |
| apps/moss-pikachu/MossPikachu/Views/SearchOverlayView.swift | Search UI, debounced querying, and result open behavior |
| apps/moss-pikachu/MossPikachu/Views/SearchOverlayPresentation.swift | Observable presentation + keyboard selection model |
| apps/moss-pikachu/MossPikachu/Views/ResultsListView.swift | Results list + row rendering |
| apps/moss-pikachu/MossPikachu/Views/PikachuPetView.swift | Pet rendering + animations by state |
| apps/moss-pikachu/MossPikachu/Views/FloatingPetWindowController.swift | Floating pet NSPanel + drag/context menu |
| apps/moss-pikachu/MossPikachu/Views/SettingsView.swift | Settings UI + manual reindex/clear controls |
| apps/moss-pikachu/MossPikachu/Views/SettingsWindowController.swift | Settings window wrapper |
| apps/moss-pikachu/MossPikachu/Views/KeyEventHandler.swift | NSViewRepresentable key catcher helper |
| apps/moss-pikachu/MossPikachu.xcodeproj/project.pbxproj | Primary Xcode project configuration + resources |
| apps/moss-pikachu/MossPikachu.xcodeproj/project.xcworkspace/contents.xcworkspacedata | Workspace metadata |
| apps/moss-pikachu/MossPikachu.xcodeproj/xcshareddata/xcschemes/MossPikachu.xcscheme | Shared scheme for build/run |
| apps/moss-pikachu/.cursor/skills/moss-pikachu/SKILL.md | Cursor “skill” doc for maintaining this app |
| apps/moss-pikachu/.cursor/skills/moss-pikachu/architecture.md | Component/data flow notes |
| apps/moss-pikachu/.cursor/skills/moss-pikachu/macos-patterns.md | Implementation patterns for macOS UI/hotkeys/sandboxing |
| apps/moss-pikachu/.cursor/skills/moss-pikachu/moss-integration.md | Worker protocol + Moss SDK usage notes |
| apps/moss-pikachu/.cursor/skills/moss-pikachu/ui-animations.md | UI sizing and animation guidelines |
| apps/moss-pikachu/.cursor/skills/moss-pikachu/pitfalls.md | Known pitfalls and constraints |
| apps/moss-pikachu/.cursor/skills/moss-pikachu/scripts/validate-phase.sh | Phase-gated build/validation script |
| apps/moss-pikachu/.cursor/skills/moss-pikachu/scripts/setup-moss-venv.sh | Minimal venv setup for skill validation |
| apps/moss-pikachu/Untitled Project/Untitled Project.xcodeproj/project.pbxproj | Extra Xcode project added (appears accidental) |
| apps/moss-pikachu/Untitled Project/Untitled Project.xcodeproj/project.xcworkspace/contents.xcworkspacedata | Extra workspace metadata |
Files not reviewed (2)
- apps/moss-pikachu/MossPikachu.xcodeproj/project.xcworkspace/contents.xcworkspacedata: Generated file
- apps/moss-pikachu/Untitled Project/Untitled Project.xcodeproj/project.xcworkspace/contents.xcworkspacedata: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| func reindexNow() async throws { | ||
| await performInitialScan(forceAll: true) | ||
| } |
| if ignoredNames.contains(name) { return false } | ||
| if path.contains("/.git/") || path.contains("/node_modules/") { return false } | ||
| guard FileManager.default.fileExists(atPath: path) else { return true } | ||
| var isDir: ObjCBool = false | ||
| FileManager.default.fileExists(atPath: path, isDirectory: &isDir) | ||
| if isDir.boolValue { return false } |
| Task { | ||
| do { | ||
| try await searchService.initialize() | ||
| AppLogger.shared.isDebugEnabled = true | ||
| AppLogger.shared.log("SearchService initialized") |
| } catch { | ||
| AppLogger.shared.isDebugEnabled = true | ||
| AppLogger.shared.log("SearchService init failed: \(error.localizedDescription)") | ||
| NotificationManager.shared.showError(error.localizedDescription) | ||
| } |
| var onKeyDown: ((NSEvent) -> Bool)? | ||
|
|
||
| override var acceptsFirstResponder: Bool { false } | ||
|
|
||
| override func keyDown(with event: NSEvent) { | ||
| guard shouldHandleKeys?() == true, onKeyDown?(event) == true else { |
| { | ||
| "index_name": "documents", | ||
| "watched_folders": ["Documents", "Desktop", "Downloads"], | ||
| "allowed_extensions": ["md", "txt", "html", "rtf", "pdf", "docx", "notes"], | ||
| "cache_path": "~/Library/Application Support/MossPikachu/index" | ||
| } |
| /// Moss SessionIndex scope for the current product build (test corpus: Downloads/cwp-stuff). | ||
| enum IndexScope { | ||
| static let folderName = "cwp-stuff" | ||
| static let sessionName = "cwp-stuff" | ||
| static let manifestFilename = "index-manifest-cwp-stuff.json" |
| /* Begin PBXNativeTarget section */ | ||
| 000000000000000100000000 /* Untitled Project */ = { | ||
| isa = PBXNativeTarget; | ||
| buildConfigurationList = 000000000000000110000000 /* Build configuration list for PBXNativeTarget "Untitled Project" */; | ||
| buildPhases = ( | ||
| 000000000000000120000000 /* Sources */, | ||
| 000000000000000130000000 /* Frameworks */, | ||
| 000000000000000140000000 /* Resources */, | ||
| ); | ||
| buildRules = ( | ||
| ); | ||
| fileSystemSynchronizedGroups = ( | ||
| 000000000000000000000010 /* Untitled Project */, | ||
| ); | ||
| name = "Untitled Project"; | ||
| productName = MyApp; | ||
| productReference = 000000000000000000000120 /* Untitled Project.app */; | ||
| productType = "com.apple.product-type.application"; | ||
| }; |
| IPHONEOS_DEPLOYMENT_TARGET = 27.0; | ||
| LOCALIZATION_PREFERS_STRING_CATALOGS = YES; | ||
| MACOSX_DEPLOYMENT_TARGET = 27.0; | ||
| MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; | ||
| MTL_FAST_MATH = YES; |
| let stdinPipe = Pipe() | ||
| let stdoutPipe = Pipe() | ||
| proc.standardInput = stdinPipe | ||
| proc.standardOutput = stdoutPipe | ||
| proc.standardError = Pipe() | ||
|
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 44 out of 49 changed files in this pull request and generated 8 comments.
Files not reviewed (2)
- apps/moss-pikachu/MossPikachu.xcodeproj/project.xcworkspace/contents.xcworkspacedata: Generated file
- apps/moss-pikachu/Untitled Project/Untitled Project.xcodeproj/project.xcworkspace/contents.xcworkspacedata: Generated file
| proc.terminationHandler = { [weak self] _ in | ||
| self?.ioQueue.async { | ||
| self?.failPending(MossBridgeError.workerCrashed) | ||
| } | ||
| } |
| let stdoutPipe = Pipe() | ||
| proc.standardInput = stdinPipe | ||
| proc.standardOutput = stdoutPipe | ||
| proc.standardError = Pipe() |
| func shutdown() { | ||
| fileMonitor.stop() | ||
| if settings.mossCloudSync { | ||
| Task { | ||
| try? await mossBridge?.pushIndex() | ||
| } | ||
| } | ||
| mossBridge?.stop() | ||
| } |
| - macOS 12+ | ||
| - Xcode 15+ | ||
| - Python 3.10+ |
| @@ -0,0 +1,70 @@ | |||
| # Moss Pikachu | |||
|
|
|||
| Native macOS menu bar app for semantic file search powered by [Moss](https://github.com/usemoss/moss). | |||
|
|
||
| ``` | ||
| AppDelegate | ||
| ├── NSStatusBar (menu: Search, Settings, Quit) |
| { | ||
| "index_name": "documents", | ||
| "watched_folders": ["Documents", "Desktop", "Downloads"], | ||
| "allowed_extensions": ["md", "txt", "html", "rtf", "pdf", "docx", "notes"], | ||
| "cache_path": "~/Library/Application Support/MossPikachu/index" | ||
| } |
| IPHONEOS_DEPLOYMENT_TARGET = 27.0; | ||
| LOCALIZATION_PREFERS_STRING_CATALOGS = YES; | ||
| MACOSX_DEPLOYMENT_TARGET = 27.0; | ||
| MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; | ||
| MTL_FAST_MATH = YES; |
Summary
apps/moss-pikachuon theprojectsbranch~/Downloadsvia Moss PythonSessionIndexTest plan
apps/moss-pikachu/MossPikachu.xcodeprojin Xcode and build./apps/moss-pikachu/scripts/setup-moss-venv.shwith Moss credentials./apps/moss-pikachu/scripts/smoke-test-indexing.shMade with Cursor