暖簾
AI writing that sounds like you.
A macOS desktop app that learns your voice and weaves it into everything you write.
Website · Download · Chrome Extension
Noren extracts your unique writing voice from samples you provide, then uses that voice profile to generate text that sounds like you, not like a chatbot.
Weave - Write a prompt, get voice-matched output. Paste or inject directly into any app.
Chat - Conversational mode with full history and file attachments. Every response is filtered through your voice.
Extract - Feed in writing samples (emails, docs, tweets). Noren distills your tone, rhythm, sentence structure, and vocabulary into a portable voice profile.
Compare - See your voiced output side-by-side with generic AI output. The difference is the product.
Your writing samples → Voice extraction → Profile (core identity + format contexts)
↓
Your prompt + profile → LLM → Voice-matched output → Clipboard / Inject into app
The voice profile is a structured document that captures how you write, not what you write about. It travels with you across formats - emails, tweets, docs, Slack messages, adapting enforcement level (strict / guided / light) per use case.
You can inspect what that artifact looks like:
noren-app/
├── src-tauri/ Rust backend (Tauri v2)
│ ├── src/
│ │ ├── main.rs App lifecycle, command registration
│ │ ├── commands/ Tauri IPC commands
│ │ │ ├── generate.rs Weave generation (voice-aware)
│ │ │ ├── chat.rs Chat + conversation persistence
│ │ │ ├── extract.rs Voice extraction orchestration
│ │ │ ├── profiles.rs Profile CRUD + server sync
│ │ │ ├── settings.rs Config, provider, hotkey management
│ │ │ ├── billing.rs Subscription / checkout
│ │ │ └── living_profile.rs Edit logging + profile evolution
│ │ ├── window.rs Popup + main window management
│ │ ├── hotkey.rs Global shortcut (Cmd+K default)
│ │ ├── accessibility.rs macOS AX API (text capture, injection)
│ │ ├── clipboard.rs Clipboard read/write
│ │ ├── keychain.rs macOS Keychain for API keys
│ │ └── tray.rs Menu bar tray icon
│ └── noren-engine/ Core library (extraction, generation, LLM clients)
│
├── src-frontend/ Svelte 5 + Tailwind v4 frontend
│ └── src/
│ ├── app.css Design system (Japanese indigo palette, dark mode)
│ └── lib/
│ ├── components/
│ │ ├── Shell.svelte Popup window shell
│ │ ├── MainShell.svelte Main app window with sidebar
│ │ ├── GenerateView.svelte Weave interface
│ │ ├── ChatView.svelte Chat with history + attachments
│ │ ├── ProfilesView.svelte Voice profile viewer/editor
│ │ ├── ExtractView.svelte Voice extraction flow
│ │ ├── SettingsView.svelte Provider config, billing, hotkey
│ │ └── OnboardingView.svelte First-run setup
│ ├── api/tauri.ts Type-safe Tauri command bindings
│ └── stores/ Svelte 5 reactive state (subscription)
| Layer | Technology |
|---|---|
| Framework | Tauri v2 |
| Backend | Rust |
| Frontend | Svelte 5, Tailwind CSS v4 |
| LLM | Anthropic, OpenAI, Gemini, Ollama, or any OpenAI-compatible provider |
| Storage | ~/.noren/ (profiles, config, chat history) |
| Secrets | macOS Keychain |
| Platform | macOS 13+ (Apple Silicon + Intel) |
The visual identity draws from Japanese indigo dyeing - the same craft tradition as the noren curtain.
#1E3148 - deep indigo, primary#3B6B8A - mid indigo, secondary#E8EDF2 - palest indigo, tints#C44A2F - persimmon red, accent#F6F1EB - unbleached silk, background#2B2725 - ink stone, textDark mode automatically matches macOS appearance via prefers-color-scheme.
Fonts: Fraunces (headings), Plus Jakarta Sans (body), JetBrains Mono (code).
cargo install tauri-clixcode-select --install# Install frontend dependencies
cd src-frontend && npm install && cd ..
# Development (hot reload)
cargo tauri dev
# Production build
cargo tauri build
The dev build creates a popup window (triggered by global hotkey) and a main app window. The production build outputs Noren.app; public user downloads are signed, notarized .pkg installers built from that app bundle.
The app bundles a Chrome native-messaging sidecar for Keychain access. Release builds need both of these files present:
src-tauri/binaries/noren-keychain-host-aarch64-apple-darwinsrc-tauri/binaries/noren-keychain-host-x86_64-apple-darwinThey are now tracked in git and must stay in sync with src/bin/noren-keychain-host.rs.
If you need to rebuild the sidecars locally:
# Apple Silicon sidecar
cargo build --manifest-path src-tauri/Cargo.toml --bin noren-keychain-host --target aarch64-apple-darwin --release
cp src-tauri/target/aarch64-apple-darwin/release/noren-keychain-host src-tauri/binaries/noren-keychain-host-aarch64-apple-darwin
# Intel sidecar
rustup target add x86_64-apple-darwin
cargo build --manifest-path src-tauri/Cargo.toml --bin noren-keychain-host --target x86_64-apple-darwin --release
cp src-tauri/target/x86_64-apple-darwin/release/noren-keychain-host src-tauri/binaries/noren-keychain-host-x86_64-apple-darwin
Release build flow:
# ARM app
cargo tauri build
# Intel app
cargo tauri build --target x86_64-apple-darwin
For local signed + notarized builds, the machine must have:
Developer ID Application certificate imported into KeychainAPPLE_ID, APPLE_PASSWORD, and APPLE_TEAM_IDnotarytool Keychain profileTAURI_SIGNING_PRIVATE_KEYTAURI_SIGNING_PRIVATE_KEY_PASSWORDBuild public installer packages from the signed .app bundles:
mkdir -p /tmp/noren-release-X.Y.Z
mkdir -p /tmp/noren-pkg-root-X.Y.Z/{aarch64,x64}
ditto src-tauri/target/release/bundle/macos/Noren.app \
/tmp/noren-pkg-root-X.Y.Z/aarch64/Noren.app
ditto src-tauri/target/x86_64-apple-darwin/release/bundle/macos/Noren.app \
/tmp/noren-pkg-root-X.Y.Z/x64/Noren.app
pkgbuild --analyze --root /tmp/noren-pkg-root-X.Y.Z/aarch64 \
/tmp/noren-release-X.Y.Z/components-aarch64.plist
pkgbuild --analyze --root /tmp/noren-pkg-root-X.Y.Z/x64 \
/tmp/noren-release-X.Y.Z/components-x64.plist
plutil -replace 0.BundleIsRelocatable -bool NO /tmp/noren-release-X.Y.Z/components-aarch64.plist
plutil -replace 0.BundleIsRelocatable -bool NO /tmp/noren-release-X.Y.Z/components-x64.plist
pkgbuild --root /tmp/noren-pkg-root-X.Y.Z/aarch64 \
--install-location /Applications \
--identifier ink.noren.desktop \
--version X.Y.Z \
--component-plist /tmp/noren-release-X.Y.Z/components-aarch64.plist \
--sign "Developer ID Installer: Okajevo Onome (YZ64BWQC3R)" \
/tmp/noren-release-X.Y.Z/Noren_X.Y.Z_aarch64.pkg
pkgbuild --root /tmp/noren-pkg-root-X.Y.Z/x64 \
--install-location /Applications \
--identifier ink.noren.desktop \
--version X.Y.Z \
--component-plist /tmp/noren-release-X.Y.Z/components-x64.plist \
--sign "Developer ID Installer: Okajevo Onome (YZ64BWQC3R)" \
/tmp/noren-release-X.Y.Z/Noren_X.Y.Z_x64.pkg
Keep BundleIsRelocatable set to false; otherwise macOS Installer can update an old copy outside /Applications.
Current public GitHub release assets expected by the website are:
Noren_X.Y.Z_aarch64.pkgNoren_X.Y.Z_x64.pkgAfter building, notarize and staple the packages, then upload them to the matching GitHub release with gh release upload ... --clobber.
Current release builds are intended to be:
Users should be able to download the .pkg, run the standard macOS Installer, and open Noren.app from /Applications without unsigned-app warnings.
BYOK (Bring Your Own Key) - Use your own API key with any supported provider. Keys are stored in macOS Keychain, never in config files.
Noren Pro - Managed inference through api.usenoren.ai. No API key needed. Includes server-side voice extraction and profile sync.