gluonfield/enchanted
Enchanted is iOS and macOS app for chatting with private self hosted language models such as Llama2, Mistral or Vicuna using Ollama.
Stale — last commit 1y ago
worst of 4 axeslast commit was 1y ago; top contributor handles 91% of recent commits…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
last commit was 1y ago; no CI workflows detected
- ✓9 active contributors
- ✓Apache-2.0 licensed
- ⚠Stale — last commit 1y ago
Show 3 more →Show less
- ⚠Single-maintainer risk — top contributor 91% of recent commits
- ⚠No CI workflows detected
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Concerns → Mixed if: 1 commit in the last 365 days
- →Deploy as-is Mixed → Healthy if: 1 commit in the last 180 days
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/gluonfield/enchanted)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/gluonfield/enchanted on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: gluonfield/enchanted
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/gluonfield/enchanted 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 — Stale — last commit 1y ago
- 9 active contributors
- Apache-2.0 licensed
- ⚠ Stale — last commit 1y ago
- ⚠ Single-maintainer risk — top contributor 91% of recent commits
- ⚠ No CI workflows detected
- ⚠ 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 gluonfield/enchanted
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/gluonfield/enchanted.
What it runs against: a local clone of gluonfield/enchanted — 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 gluonfield/enchanted | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 446 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of gluonfield/enchanted. If you don't
# have one yet, run these first:
#
# git clone https://github.com/gluonfield/enchanted.git
# cd enchanted
#
# 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 gluonfield/enchanted and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "gluonfield/enchanted(\\.git)?\\b" \\
&& ok "origin remote is gluonfield/enchanted" \\
|| miss "origin remote is not gluonfield/enchanted (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "Enchanted/Application/EnchantedApp.swift" \\
&& ok "Enchanted/Application/EnchantedApp.swift" \\
|| miss "missing critical file: Enchanted/Application/EnchantedApp.swift"
test -f "Enchanted/Services/OllamaService.swift" \\
&& ok "Enchanted/Services/OllamaService.swift" \\
|| miss "missing critical file: Enchanted/Services/OllamaService.swift"
test -f "Enchanted/Stores/AppStore.swift" \\
&& ok "Enchanted/Stores/AppStore.swift" \\
|| miss "missing critical file: Enchanted/Stores/AppStore.swift"
test -f "Enchanted/Services/SwiftDataService.swift" \\
&& ok "Enchanted/Services/SwiftDataService.swift" \\
|| miss "missing critical file: Enchanted/Services/SwiftDataService.swift"
test -f "Enchanted/Models/ConversationState.swift" \\
&& ok "Enchanted/Models/ConversationState.swift" \\
|| miss "missing critical file: Enchanted/Models/ConversationState.swift"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 446 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~416d)"
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/gluonfield/enchanted"
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
Enchanted is a native iOS, macOS, and visionOS app that provides a ChatGPT-like UI for privately hosted language models (Llama 2, Mistral, Vicuna, Starling) via Ollama. It enables multimodal conversations with self-hosted LLMs without relying on closed APIs, supporting markdown rendering, image uploads, and custom prompt templates across Apple's entire ecosystem. Single-target Xcode project structure: Enchanted/ contains all source, Enchanted.xcodeproj/ manages build configuration. Application/EnchantedApp.swift is the entry point. Assets.xcassets manages icons and colors across all platforms. Uses SwiftPM for dependency management (Package.resolved present), indicating modern Swift tooling with no CocoaPods or Carthage.
👥Who it's for
Privacy-conscious developers and end-users who want to run large language models locally on their own hardware without sending data to OpenAI or other cloud providers. Also appeals to macOS/iOS power users seeking a polished, native alternative to web-based LLM interfaces.
🌱Maturity & risk
Actively developed and production-ready—available on the App Store (id6474268307), with visible stars and recent activity. The 222KB Swift codebase and presence on multiple platforms (iOS, macOS, visionOS) indicate a mature project, though the single-maintainer status (@amgauge) means stability depends on continued community engagement.
Single-maintainer risk is the primary concern (repo shows 'augustdev' as core author). Ollama dependency means the app is tightly coupled to that project's API stability—breaking changes in Ollama could require updates. No visible CI/CD pipeline (no .github/workflows in file list) and lack of automated tests could slow bug fixes.
Active areas of work
Recent work appears focused on visionOS support (Accessibility.plist and solidimagestack assets indicate Vision Pro optimizations). The app maintains multi-platform parity across iOS, macOS, and visionOS, with ongoing refinement of the chat UI and model management features. No recent commit history visible in file list, but App Store presence suggests active maintenance.
🚀Get running
Clone the repo: git clone https://github.com/AugustDev/enchanted.git. Open Xcode: open Enchanted.xcodeproj. Resolve Swift Package dependencies in Xcode (File → Packages → Reset Package Caches if needed). You will need a running Ollama server locally or on your network to test the app—see the README for Ollama setup instructions.
Daily commands: In Xcode: select target (Enchanted, iPhone, Mac, or Vision Pro simulator), then press Cmd+R or Product → Run. For visionOS testing, ensure visionOS simulator is installed. The app requires a running Ollama instance; configure the server URL in Settings within the app.
🗺️Map of the codebase
Enchanted/Application/EnchantedApp.swift— Main app entry point and SwiftUI app structure—every contributor must understand the app lifecycle and root environment setup.Enchanted/Services/OllamaService.swift— Core service for communicating with the Ollama API—essential for understanding how LLM requests are handled and streamed.Enchanted/Stores/AppStore.swift— Central application state management and configuration—all features depend on the global app state defined here.Enchanted/Services/SwiftDataService.swift— Persistence layer using SwiftData—required reading for understanding how conversations and models are stored.Enchanted/Models/ConversationState.swift— Core data model for chat conversations—defines the schema and behavior all UI layers interact with.Enchanted/Models/LanguageModel.swift— Represents available LLM configurations—critical for understanding model selection and endpoint handling.
🛠️How to make changes
Add a new LLM service integration
- Create a new service file (e.g., CustomLLMService.swift) in Enchanted/Services/ that conforms to the same interface as OllamaService.swift for making inference calls (
Enchanted/Services/OllamaService.swift) - Add a new case to the LanguageModel enum in Models/LanguageModel.swift to represent your service type (
Enchanted/Models/LanguageModel.swift) - Update AppStore.swift to instantiate and select your new service based on user configuration (
Enchanted/Stores/AppStore.swift) - Update CompletionsStore.swift to route streaming responses through your new service implementation (
Enchanted/Stores/CompletionsStore.swift)
Add a new speech or audio feature
- Extend SpeechService.swift to add new methods using AVSpeechSynthesizer or other AVFoundation APIs (
Enchanted/Services/SpeechService.swift) - Create a new extension file (e.g., AVSpeechSynthesisVoice+Extension.swift) if you need custom voice handling (
Enchanted/Extensions/AVSpeechSynthesisVoice+Extension.swift) - Add properties and methods to AppStore.swift to track speech-related state and expose them to SwiftUI views (
Enchanted/Stores/AppStore.swift)
Add a new keyboard shortcut or hotkey
- Define the new hotkey combination in Enchanted/Helpers/HotKeys.swift (
Enchanted/Helpers/HotKeys.swift) - Register the hotkey handler in HotkeyService.swift (
Enchanted/Services/HotkeyService.swift) - Connect the hotkey action to AppStore.swift state updates or method calls (
Enchanted/Stores/AppStore.swift)
Add a new theme or color scheme
- Add new color sets to Enchanted/Assets.xcassets/Colors/ (e.g., myNewColor.colorset) (
Enchanted/Assets.xcassets/Colors) - Define new colors in Colours+Extension.swift and add a case to AppColorScheme enum in Models/AppColorScheme.swift (
Enchanted/Extensions/Colours+Extension.swift) - Update AppStore.swift to track the selected color scheme and apply it globally (
Enchanted/Stores/AppStore.swift)
🔧Why these technologies
- SwiftUI — Cross-platform UI framework for iOS, macOS, and visionOS with declarative syntax and powerful state management
- SwiftData — Modern native persistence for Apple platforms replacing Core Data; simpler API for storing conversations and app state
- Combine / @Published — Reactive programming model for binding app state changes to UI updates in real-time
- URLSession — Standard iOS/macOS HTTP client for streaming responses from Ollama API with async/await support
- AVFoundation (AVSpeechSynthesizer) — Native text-to-speech capability across all Apple platforms without external dependencies
⚖️Trade-offs already made
-
Ollama-only API support (no OpenAI, Claude, etc. built-in)
- Why: Focused scope on private, self-hosted models aligns with privacy-first product positioning
- Consequence: Limited flexibility; users cannot easily switch to cloud LLM providers without architecture changes
-
Single-server architecture (one Ollama endpoint at a time)
- Why: Simplifies configuration and state management; matches typical user setup
- Consequence: Users cannot run multiple Ollama servers simultaneously or load-balance across instances
-
Local-only persistence (no cloud sync)
- Why: Aligns with privacy goals; all data stays on device
- Consequence: Conversations not synced across devices; users must manually transfer or re-run conversations
-
Streaming UI updates via @Published state
- Why: Native SwiftUI
- Consequence: undefined
🪤Traps & gotchas
The app requires a running Ollama server accessible at a configurable URL—development will fail silently if Ollama is not running or reachable. visionOS support uses solidimagestack assets which are Vision Pro-specific; simulator testing requires visionOS SDK installed. No visible keychain/credentials setup in file list, so confirm how Ollama authentication (if any) is handled. Xcode 15+ is likely required for visionOS target support.
🏗️Architecture
💡Concepts to learn
- Ollama Protocol / REST API — Enchanted's entire backend communication layer depends on Ollama's HTTP API for chat completions and model management; understanding the /api/chat endpoint, streaming responses, and model discovery is essential for debugging and extending features.
- SwiftUI's @Published and Combine — The app almost certainly uses Combine's ObservableObject pattern for reactive state management across the chat UI, settings, and Ollama connection state—core to iOS/macOS app architecture.
- Multiplatform SwiftUI (iOS + macOS + visionOS) — Enchanted targets three distinct platforms from a single codebase using conditional compilation and platform-specific view hierarchies; critical for understanding layout decisions and touch/gesture handling differences.
- Server-Sent Events (SSE) / HTTP Streaming — Ollama returns chat completions as streamed JSON responses; Enchanted must parse and display tokens incrementally, requiring URLSession streaming support or WebSocket fallback for real-time chat UX.
- Vision Pro's visionOS Layer Stack (solidimagestack) — App icons and assets for visionOS require a three-layer image stack (front/middle/back); different from iOS/macOS flat icons. The solidimagestack assets in the file list show Vision Pro-specific rendering.
- Markdown Rendering in SwiftUI — The README mentions markdown support in chat responses; SwiftUI's native markdown support (iOS 15.1+) or third-party libraries like MarkdownUI must be integrated to render model responses with formatting.
- URLSession Delegate & Network Resilience — A local Ollama server may be unreliable or unreachable; the app must handle network timeouts, retries, and graceful error messaging—critical for user experience in offline or flaky WiFi scenarios.
🔗Related repos
jmorganca/ollama— The core backend that Enchanted communicates with; defines the API contract and model serving capabilitiesoobabooga/text-generation-webui— Alternative local LLM UI offering web-based interface; shows competing approach to private model interaction (web vs. native)LLaMA-Factory/LLaMA-Factory— Companion tool for fine-tuning and quantizing models that Enchanted can serve through OllamaOpenAI/gpt-4-vision-system-prompt— Related to multimodal capabilities—Enchanted's image upload feature parallels GPT-4 Vision, so understanding prompt injection risks is relevantyonilevy/llmchain— Swift LLM chain library; alternative to raw Ollama API calls, though Enchanted appears to use direct HTTP
🪄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 GitHub Actions workflow for iOS/macOS build validation
The repo lacks automated CI/CD pipelines. With an Xcode project and multiple platform targets (iOS, macOS, visionOS), a GitHub Actions workflow would catch build regressions early. This is critical for a multi-platform app where SwiftPM dependencies (Package.resolved exists) need validation across platforms.
- [ ] Create .github/workflows/build.yml with Xcode build steps for iOS and macOS schemes
- [ ] Reference Enchanted.xcodeproj/xcshareddata/xcschemes/Enchanted.xcscheme for scheme name
- [ ] Add build matrix for iOS 16+, macOS 13+, and visionOS targets
- [ ] Include SwiftPM dependency resolution validation using Package.resolved
Create unit tests for Ollama API integration layer
The app integrates with Ollama backend for model interactions, but there's no visible test directory structure. Adding tests for the API client would be high-value: testing model listing, message streaming, error handling, and connection failures are critical for a chat app relying on external LLM services.
- [ ] Create Enchanted/Tests/OllamaAPITests.swift to mock Ollama endpoint responses
- [ ] Add tests for connection validation (reachability checks to localhost:11434 default)
- [ ] Test model listing, chat completion requests, and streaming response parsing
- [ ] Add tests for error cases: connection failures, invalid model names, network timeouts
Document Ollama configuration and connection setup in README
The README snippet shows the app is 'Ollama compatible' but provides no setup instructions. New contributors and users need clarity on: required Ollama version, default connection settings (localhost:11434), supported model list, and troubleshooting. This blocks both user adoption and contributor onboarding.
- [ ] Add 'Configuration' section to README documenting Ollama setup (installation, running service)
- [ ] Document the default connection string and how to configure custom Ollama hosts
- [ ] List tested/supported models (Llama 2, Mistral, Vicuna, Starling mentioned in description)
- [ ] Add troubleshooting section for common issues: connection refused, model not found, response timeouts
🌿Good first issues
- Add unit tests for OllamaAPI client—no test target visible in the file structure. Start with tests for model listing and chat completion request/response parsing in a new Tests/ directory.
- Document the Settings UI and configuration options in the README—the Settings screenshot is referenced but not explained. Add a 'Configuration' section with server URL format, authentication steps, and supported model list.
- Create a quick-start guide for first-time Ollama users—add a 'Getting Started with Ollama' section in the README with links to model downloads and common setup issues (network accessibility, memory requirements for different models).
⭐Top contributors
Click to expand
Top contributors
- @gluonfield — 91 commits
- @wzulfikar — 2 commits
- @arjunbazinga — 1 commits
- @so898 — 1 commits
- @mguella — 1 commits
📝Recent commits
Click to expand
Recent commits
2f82ee2— feat: colour adjustments (#194) (gluonfield)027bb23— fix: typo delete all conversation on calling delete (#159) (arjunbazinga)ee5e6ca— Add support for <think> tag (#190) (so898)2aa9d14— add support for llama vision (#165) (mguella)2207cbb— Update README.md (gluonfield)0073d4a— fix minor typos (#130) (nick-w-nick)aebe49b— fix: swift data delete all button (gluonfield)a0f6695— fix: overlap (gluonfield)58130aa— Feat/visionos (#127) (gluonfield)88137aa— Update README.md (gluonfield)
🔒Security observations
- High · Missing Explicit Network Security Configuration —
Enchanted/Enchanted.entitlements and Info.plist configuration. The app communicates with self-hosted Ollama servers over the network. Without visible network security policies (App Transport Security settings), there's a risk of unencrypted HTTP traffic to model servers, especially if users connect to local network instances without HTTPS. Fix: Ensure App Transport Security (ATS) is properly configured. Explicitly allow local network connections only via Local Network entitlements (NSBonjourServiceTypes, NSLocalNetworkUsageDescription) while enforcing HTTPS for remote connections. Review Info.plist for NSAllowsArbitraryLoads settings. - High · Clipboard Access Without Visible Privacy Disclosure —
Enchanted/Extensions/NSClipboardItem.swift and Info.plist. The file 'NSClipboardItem.swift' indicates clipboard operations, but no corresponding NSPasteboardUsageDescription found in the visible configuration. iOS/macOS require privacy descriptions for clipboard access to be transparent to users. Fix: Ensure Info.plist includes NSPasteboardUsageDescription (macOS) or appropriate privacy descriptions. Add clear user-facing explanations for why clipboard access is needed. - Medium · Potential Insecure Model Data Storage —
Enchanted/Extensions/ModelContext+Extension.swift. The codebase references ModelContext and database operations (ModelContext+Extension.swift) for persisting chat conversations and model data. Without seeing the actual implementation, there's a risk of unencrypted sensitive conversation storage, especially if using deprecated methods. Fix: Verify that SwiftData or Core Data uses encryption at rest. Implement file-level encryption for sensitive data. Consider using Keychain for authentication tokens and sensitive credentials. - Medium · Text-to-Speech Data Exposure —
Enchanted/Extensions/AVSpeechSynthesisVoice+Extension.swift. AVSpeechSynthesisVoice extension indicates text-to-speech functionality. User conversations may be sent to system TTS services or third-party APIs without explicit user consent tracking. Fix: Document and disclose all third-party services used for TTS. Ensure users can opt-out of TTS without affecting core functionality. Verify that sensitive conversation content is not logged by TTS systems. - Medium · Missing Package Dependency Verification —
Enchanted.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved. The 'Package.resolved' file exists but content is not provided for analysis. Unable to verify that all Swift Package Manager dependencies are from trusted sources, pinned to secure versions, and free from known vulnerabilities. Fix: Regularly audit dependencies using tools like swift-package-scanner or npm-audit equivalents. Pin all dependencies to specific versions. Monitor security advisories for all transitive dependencies. Implement SBOM (Software Bill of Materials) tracking. - Medium · Potential Hardcoded Configuration in Entitlements —
Enchanted/Enchanted.entitlements and Enchanted/EnchantedDebug.entitlements. Multiple entitlement files exist (Enchanted.entitlements, EnchantedDebug.entitlements) with different configurations. Debug entitlements may contain relaxed security settings that could be accidentally included in production builds. Fix: Ensure build configurations strictly separate debug and production entitlements. Implement pre-build verification to prevent debug entitlements in release builds. Review both files to ensure no hardcoded credentials or overly-permissive capabilities. - Low · Accessibility Configuration Exposure —
Enchanted/Accessibility.plist. Accessibility.plist is present which may contain service identifiers or UI automation hints that could be leveraged by malicious accessibility services. Fix: Review Accessibility.plist for sensitive information. Implement additional runtime checks to verify accessibility service legitimacy before exposing data to accessibility APIs. - Low · Debug Symbols and Breakpoints in Version Control —
Enchanted.xcodeproj/xcuserdata/wpc.xcuserdatad. Xcode breakpoint files (.xcbkptlist) and debug configuration files are present in the repository, potentially exposing debug information and internal code paths. Fix: undefined
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.