Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<p align="center">
<p align="center">Char - The AI notepad for <strong>private</strong> meetings</p>
<p align="center">
<a href="https://deepwiki.com/fastrepl/hyprnote"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
<a href="https://deepwiki.com/fastrepl/char"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
<a href="https://hyprnote.com/discord" target="_blank"><img src="https://img.shields.io/static/v1?label=Join%20our&message=Discord&color=blue&logo=Discord" alt="Discord"></a>
<a href="https://x.com/tryhyprnote" target="_blank"><img src="https://img.shields.io/static/v1?label=Follow%20us%20on&message=X&color=black&logo=x" alt="X"></a>
</p>
Expand All @@ -27,8 +27,8 @@ brew install --cask fastrepl/hyprnote/hyprnote@nightly
```

- [macOS](https://hyprnote.com/download) (public beta)
- [Windows](https://github.com/fastrepl/hyprnote/issues/66) (q1 2026)
- [Linux](https://github.com/fastrepl/hyprnote/issues/67) (q1 2026)
- [Windows](https://github.com/fastrepl/char/issues/66) (q1 2026)
- [Linux](https://github.com/fastrepl/char/issues/67) (q1 2026)

## Highlights

Expand Down Expand Up @@ -72,7 +72,7 @@ Char plays nice with whatever stack you're running.

Prefer a certain style? Choose from predefined templates like bullet points, agenda-based, or paragraph summary. Or create your own.

Check out our [template gallery](https://hyprnote.com/templates) and add your own [here](https://github.com/fastrepl/hyprnote/tree/main/apps/web/content/templates).
Check out our [template gallery](https://hyprnote.com/templates) and add your own [here](https://github.com/fastrepl/char/tree/main/apps/web/content/templates).

### AI Chat

Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use utoipa::{Modify, OpenApi};
#[derive(OpenApi)]
#[openapi(
info(
title = "Hyprnote AI API",
title = "Char AI API",
version = "1.0.0",
description = "AI services API for speech-to-text transcription, LLM chat completions, and subscription management"
),
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/flatpak/com.hyprnote.Hyprnote.desktop
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[Desktop Entry]
Name=Hyprnote
Name=Char
GenericName=AI Meeting Notes
Comment=The AI notepad for private meetings
Exec=hyprnote %U
Expand Down
14 changes: 7 additions & 7 deletions apps/desktop/flatpak/com.hyprnote.Hyprnote.metainfo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@
<component type="desktop-application">
<id>com.hyprnote.Hyprnote</id>

<name>Hyprnote</name>
<name>Char</name>
<summary>The AI notepad for private meetings</summary>

<metadata_license>CC0-1.0</metadata_license>
<project_license>MIT</project_license>

<description>
<p>
Hyprnote is an AI notetaking app specifically designed to take meeting notes.
With Hyprnote, you can transcribe all kinds of meetings whether it be online or offline.
Char is an AI notetaking app specifically designed to take meeting notes.
With Char, you can transcribe all kinds of meetings whether it be online or offline.
</p>
<p>Features:</p>
<ul>
<li>Listens to your meetings so you can only jot down important stuff</li>
<li>No bots joining your meetings - Hyprnote listens directly to sounds coming in and out of your computer</li>
<li>No bots joining your meetings - Char listens directly to sounds coming in and out of your computer</li>
<li>Crafts perfect summaries based on your memos, right after the meeting is over</li>
<li>Run completely offline by using LM Studio or Ollama</li>
<li>Bring your own LLM - use local models via Ollama or third-party APIs like Gemini, Claude, or Azure-hosted GPT</li>
Expand All @@ -28,9 +28,9 @@
<launchable type="desktop-id">com.hyprnote.Hyprnote.desktop</launchable>

<url type="homepage">https://hyprnote.com</url>
<url type="bugtracker">https://github.com/fastrepl/hyprnote/issues</url>
<url type="vcs-browser">https://github.com/fastrepl/hyprnote</url>
<url type="contribute">https://github.com/fastrepl/hyprnote/blob/main/CONTRIBUTING.md</url>
<url type="bugtracker">https://github.com/fastrepl/char/issues</url>
<url type="vcs-browser">https://github.com/fastrepl/char</url>
<url type="contribute">https://github.com/fastrepl/char/blob/main/CONTRIBUTING.md</url>

<developer id="com.hyprnote">
<name>Fastrepl</name>
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/flatpak/com.hyprnote.Hyprnote.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Flatpak manifest for Hyprnote
# Flatpak manifest for Char
# https://docs.flathub.org/docs/for-app-authors/requirements
#
# To generate vendored dependencies:
Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/components/chat/body/empty.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function ChatBodyEmpty({
<div className="flex justify-start px-3 py-2 pb-4">
<div className="flex flex-col min-w-[240px] max-w-[80%]">
<div className="flex items-center gap-2 mb-2">
<img src="/assets/dynamic.gif" alt="Hyprnote" className="w-5 h-5" />
<img src="/assets/dynamic.gif" alt="Char" className="w-5 h-5" />
<span className="text-sm font-medium text-neutral-800">
Hyprnote AI
</span>
Expand All @@ -52,7 +52,7 @@ export function ChatBodyEmpty({
<div className="flex justify-start px-3 pb-4">
<div className="flex flex-col min-w-[240px] max-w-[80%]">
<div className="flex items-center gap-1 mb-2">
<img src="/assets/dynamic.gif" alt="Hyprnote" className="w-5 h-5" />
<img src="/assets/dynamic.gif" alt="Char" className="w-5 h-5" />
<span className="text-sm font-medium text-neutral-800">
Hyprnote AI
</span>
Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/src/components/main/sidebar/toast/registry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export function createToastRegistry({
icon: (
<img
src="/assets/hyprnote-pro.png"
alt="Hyprnote Pro"
alt="Char Pro"
className="size-5"
/>
),
Expand All @@ -162,7 +162,7 @@ export function createToastRegistry({
icon: (
<img
src="/assets/hyprnote-pro.png"
alt="Hyprnote Pro"
alt="Char Pro"
className="size-5"
/>
),
Expand Down
4 changes: 1 addition & 3 deletions apps/desktop/src/components/settings/ai/llm/configure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@ export function ConfigureProviders() {
<HyprProviderCard
providerId="hyprnote"
providerName="Hyprnote"
icon={
<img src="/assets/icon.png" alt="Hyprnote" className="size-5" />
}
icon={<img src="/assets/icon.png" alt="Char" className="size-5" />}
/>
{PROVIDERS.filter((provider) => provider.id !== "hyprnote").map(
(provider) => (
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/components/settings/ai/llm/shared.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const _PROVIDERS = [
id: "hyprnote",
displayName: "Hyprnote",
badge: "Recommended",
icon: <img src="/assets/icon.png" alt="Hyprnote" className="size-5" />,
icon: <img src="/assets/icon.png" alt="Char" className="size-5" />,
baseUrl: new URL("/llm", env.VITE_API_URL).toString(),
requirements: [
{ kind: "requires_auth" },
Expand Down
4 changes: 1 addition & 3 deletions apps/desktop/src/components/settings/ai/stt/configure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ export function ConfigureProviders() {
<HyprProviderCard
providerId="hyprnote"
providerName="Hyprnote"
icon={
<img src="/assets/icon.png" alt="Hyprnote" className="size-5" />
}
icon={<img src="/assets/icon.png" alt="Char" className="size-5" />}
badge={PROVIDERS.find((p) => p.id === "hyprnote")?.badge}
/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/components/settings/ai/stt/shared.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ const _PROVIDERS = [
id: "hyprnote",
displayName: "Hyprnote",
badge: "Recommended",
icon: <img src="/assets/icon.png" alt="Hyprnote" className="size-5" />,
icon: <img src="/assets/icon.png" alt="Char" className="size-5" />,
baseUrl: new URL("/stt", env.VITE_API_URL).toString(),
models: [
"cloud",
Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/src/components/settings/general/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export function SettingsApp() {
{(telemetryConsentField) => (
<AppSettingsView
autostart={{
title: "Start Hyprnote at login",
title: "Start Char at login",
description:
"Always ready without manually launching.",
value: autostartField.state.value,
Expand Down
2 changes: 1 addition & 1 deletion crates/api-research/src/mcp/prompts/research_chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ use rmcp::{ErrorData as McpError, model::*};
struct ResearchChatPrompt;

pub(crate) fn research_chat() -> Result<GetPromptResult, McpError> {
hypr_mcp::render_prompt::<ResearchChatPrompt>("System prompt for the Hyprnote research chat")
hypr_mcp::render_prompt::<ResearchChatPrompt>("System prompt for the Char research chat")
}
4 changes: 2 additions & 2 deletions crates/api-research/src/mcp/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ impl ServerHandler for ResearchMcpServer {
website_url: None,
},
instructions: Some(
"Hyprnote research server. Provides tools for web search and content retrieval powered by Exa."
"Char research server. Provides tools for web search and content retrieval powered by Exa."
.to_string(),
),
}
Expand All @@ -103,7 +103,7 @@ impl ServerHandler for ResearchMcpServer {
Ok(ListPromptsResult {
prompts: vec![Prompt::new(
"research_chat",
Some("System prompt for the Hyprnote research chat"),
Some("System prompt for the Char research chat"),
None::<Vec<PromptArgument>>,
)],
next_cursor: None,
Expand Down
2 changes: 1 addition & 1 deletion crates/api-support/src/mcp/prompts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub(crate) fn support_chat() -> Result<GetPromptResult, McpError> {
hypr_template_support::render_support_chat()
.map_err(|e| McpError::internal_error(e.to_string(), None))
.map(|content| GetPromptResult {
description: Some("System prompt for the Hyprnote support chat".to_string()),
description: Some("System prompt for the Char support chat".to_string()),
messages: vec![PromptMessage::new_text(
PromptMessageRole::Assistant,
content,
Expand Down
4 changes: 2 additions & 2 deletions crates/api-support/src/mcp/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ impl ServerHandler for SupportMcpServer {
website_url: None,
},
instructions: Some(
"Hyprnote support server. Provides tools for GitHub issue management (search, create, comment) and Stripe billing operations (list subscriptions, billing portal). Always search before creating issues to avoid duplicates.".to_string(),
"Char support server. Provides tools for GitHub issue management (search, create, comment) and Stripe billing operations (list subscriptions, billing portal). Always search before creating issues to avoid duplicates.".to_string(),
),
}
}
Expand All @@ -187,7 +187,7 @@ impl ServerHandler for SupportMcpServer {
Ok(ListPromptsResult {
prompts: vec![Prompt::new(
"support_chat",
Some("System prompt for the Hyprnote support chat"),
Some("System prompt for the Char support chat"),
None::<Vec<PromptArgument>>,
)],
next_cursor: None,
Expand Down
2 changes: 1 addition & 1 deletion crates/db-parser/src/v0/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub async fn parse_from_sqlite(path: &Path) -> Result<Collection> {
.await?;
let db = UserDatabase::from(db);

// Older Hyprnote DBs can have `sessions.words` as NULL/empty, but db-user's
// Older Char DBs can have `sessions.words` as NULL/empty, but db-user's
// `Session::from_row` expects a non-null JSON string.
let conn = db.conn()?;
conn.execute(
Expand Down
2 changes: 1 addition & 1 deletion crates/detect/src/app/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use tokio::time::{Duration, sleep};

use crate::BackgroundTask;

// `defaults read /Applications/Hyprnote.app/Contents/Info.plist CFBundleIdentifier`
// `defaults read /Applications/Char.app/Contents/Info.plist CFBundleIdentifier`
const MEETING_APP_LIST: [&str; 3] = [
"us.zoom.xos", // tested
"Cisco-Systems.Spark", // tested
Expand Down
2 changes: 1 addition & 1 deletion crates/device-monitor/src/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ fn setup_pulseaudio(stop_rx: &mpsc::Receiver<()>) -> Option<PulseAudioHandles> {
if proplist
.set_str(
libpulse_binding::proplist::properties::APPLICATION_NAME,
"Hyprnote Device Monitor",
"Char Device Monitor",
)
.is_err()
{
Expand Down
2 changes: 1 addition & 1 deletion crates/eval/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "eval"
version = "0.1.0"
edition = "2021"
description = "LLM evaluation runner for Hyprnote"
description = "LLM evaluation runner for Char"

[dependencies]
backon = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion extensions/shared/API.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Hyprnote Extension API Reference
# Char Extension API Reference

> AUTO-GENERATED from runtime.ts

Expand Down
8 changes: 4 additions & 4 deletions openstatus.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
target: 200
frequency: 1m
kind: http
name: Hyprnote Web
name: Char Web
openTelemetry: {}
regions:
- railway_europe-west4-drams3a
Expand All @@ -31,7 +31,7 @@
target: 200
frequency: 1m
kind: http
name: Hyprnote API
name: Char API
openTelemetry: {}
regions:
- cdg
Expand All @@ -54,7 +54,7 @@
target: 200
frequency: 1m
kind: http
name: Hyprnote Web
name: Char Web
openTelemetry: {}
regions:
- railway_europe-west4-drams3a
Expand All @@ -77,7 +77,7 @@
target: 200
frequency: 1m
kind: http
name: Hyprnote API
name: Char API
openTelemetry: {}
regions:
- cdg
Expand Down
2 changes: 1 addition & 1 deletion plugins/git/src/operations/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::path::Path;

use crate::types::{CommitInfo, FileChangeType, FileStatus, StatusInfo};

const DEFAULT_GITIGNORE: &str = "# Hyprnote auto-generated gitignore
const DEFAULT_GITIGNORE: &str = "# Char auto-generated gitignore
# Large audio files (not suitable for git)
*.wav
*.ogg
Expand Down
4 changes: 2 additions & 2 deletions plugins/hooks/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fn push_cli_arg(args: &mut Vec<OsString>, field_name: &str, value: &str) {
pub struct AfterListeningStoppedArgs {
/// Path to the resource directory.
pub resource_dir: String,
/// Application-specific Hyprnote data.
/// Application-specific Char data.
pub app_hyprnote: String,
/// Optional meeting-specific data.
#[serde(skip_serializing_if = "Option::is_none")]
Expand All @@ -67,7 +67,7 @@ impl HookArgs for AfterListeningStoppedArgs {
pub struct BeforeListeningStartedArgs {
/// Path to the resource directory.
pub resource_dir: String,
/// Application-specific Hyprnote data.
/// Application-specific Char data.
pub app_hyprnote: String,
/// Optional meeting-specific data.
#[serde(skip_serializing_if = "Option::is_none")]
Expand Down
4 changes: 2 additions & 2 deletions plugins/importer/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl ImportSource {
kind: Some(ImportSourceKind::HyprnoteV0Stable),
transform: TransformKind::HyprnoteV0,
path,
name: "Hyprnote v0 - Stable".to_string(),
name: "Char v0 - Stable".to_string(),
})
}

Expand All @@ -61,7 +61,7 @@ impl ImportSource {
kind: Some(ImportSourceKind::HyprnoteV0Nightly),
transform: TransformKind::HyprnoteV0,
path,
name: "Hyprnote v0 - Nightly".to_string(),
name: "Char v0 - Nightly".to_string(),
})
}

Expand Down
2 changes: 1 addition & 1 deletion plugins/local-llm/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub async fn list_supported_model() -> Result<Vec<ModelInfo>, String> {
ModelInfo {
key: SupportedModel::HyprLLM,
name: "HyprLLM".to_string(),
description: "Experimental model trained by the Hyprnote team.".to_string(),
description: "Experimental model trained by the Char team.".to_string(),
size_bytes: SupportedModel::HyprLLM.model_size(),
},
ModelInfo {
Expand Down
2 changes: 1 addition & 1 deletion plugins/pdf/src/typst/content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ fn build_cover_page(

cover.push_str(" #v(1fr)\n");

cover.push_str(" #text(size: 10pt, fill: muted-color)[Exported from Hyprnote]\n");
cover.push_str(" #text(size: 10pt, fill: muted-color)[Exported from Char]\n");

cover.push_str(" ]\n");
cover.push_str("]\n\n");
Expand Down
2 changes: 1 addition & 1 deletion plugins/tray/src/menu_items/tray_open.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ impl MenuItemHandler for TrayOpen {
const ID: &'static str = "hypr_tray_open";

fn build(app: &AppHandle<tauri::Wry>) -> Result<MenuItemKind<tauri::Wry>> {
let item = MenuItem::with_id(app, Self::ID, "Open Hyprnote", true, None::<&str>)?;
let item = MenuItem::with_id(app, Self::ID, "Open Char", true, None::<&str>)?;
Ok(MenuItemKind::MenuItem(item))
}

Expand Down
2 changes: 1 addition & 1 deletion plugins/windows/src/window/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ impl AppWindow {
impl WindowImpl for AppWindow {
fn title(&self) -> String {
match self {
Self::Main => "Hyprnote".into(),
Self::Main => "Char".into(),
Self::Control => "Control".into(),
}
}
Expand Down
Loading