refactor: rename app to aryx

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-03-25 21:11:36 +01:00
co-authored by Copilot
parent cb7f216bc3
commit ab4e217d74
26 changed files with 81 additions and 81 deletions
+7 -7
View File
@@ -94,13 +94,13 @@ jobs:
include:
- os: windows-latest
label: Windows
asset_path: release/Eryx-windows-x64.zip
asset_path: release/Aryx-windows-x64.zip
- os: macos-13
label: macOS
asset_path: release/Eryx-macos-x64.zip
asset_path: release/Aryx-macos-x64.zip
- os: ubuntu-latest
label: Linux
asset_path: release/Eryx-linux-x64.tar.gz
asset_path: release/Aryx-linux-x64.tar.gz
steps:
- name: Check out repository
@@ -130,20 +130,20 @@ jobs:
- name: Ad-hoc sign macOS app bundle
if: runner.os == 'macOS'
run: codesign --force --deep --sign - release/Eryx-macos-x64/Eryx.app
run: codesign --force --deep --sign - release/Aryx-macos-x64/Aryx.app
- name: Create Windows release archive
if: runner.os == 'Windows'
shell: pwsh
run: Compress-Archive -Path 'release\Eryx-windows-x64\*' -DestinationPath 'release\Eryx-windows-x64.zip' -Force
run: Compress-Archive -Path 'release\Aryx-windows-x64\*' -DestinationPath 'release\Aryx-windows-x64.zip' -Force
- name: Create macOS release archive
if: runner.os == 'macOS'
run: ditto -c -k --sequesterRsrc --keepParent release/Eryx-macos-x64/Eryx.app release/Eryx-macos-x64.zip
run: ditto -c -k --sequesterRsrc --keepParent release/Aryx-macos-x64/Aryx.app release/Aryx-macos-x64.zip
- name: Create Linux release archive
if: runner.os == 'Linux'
run: tar -czf release/Eryx-linux-x64.tar.gz -C release Eryx-linux-x64
run: tar -czf release/Aryx-linux-x64.tar.gz -C release Aryx-linux-x64
- name: Upload asset to GitHub release
shell: bash
+8 -8
View File
@@ -2,7 +2,7 @@
## What this system is
Eryx is a desktop workspace for Copilot-powered development work. It combines a persistent session model, project-aware context, reusable multi-agent orchestration patterns, optional external tooling, and live run visibility inside a single Electron application.
Aryx is a desktop workspace for Copilot-powered development work. It combines a persistent session model, project-aware context, reusable multi-agent orchestration patterns, optional external tooling, and live run visibility inside a single Electron application.
At a high level, the architecture is built around one core idea:
@@ -63,7 +63,7 @@ This split is the most important architectural feature in the app. It is what ke
## High-level runtime model
Eryx runs as a multi-process desktop application:
Aryx runs as a multi-process desktop application:
1. The **renderer** displays the workspace and captures user intent.
2. The **preload bridge** exposes a small, typed API into the browser context.
@@ -101,7 +101,7 @@ sequenceDiagram
M-->>R: Final workspace snapshot
```
This flow is important because it shows that Eryx is not architected as a simple "send prompt, get string" application. It treats execution as a structured, observable process.
This flow is important because it shows that Aryx is not architected as a simple "send prompt, get string" application. It treats execution as a structured, observable process.
## Application state model
@@ -113,7 +113,7 @@ The durable state of the app is a **workspace**. The workspace contains:
- settings
- run history
This gives Eryx a persistent operating model rather than a transient chat model.
This gives Aryx a persistent operating model rather than a transient chat model.
### Projects
@@ -155,7 +155,7 @@ A session is the working unit of the product. It binds together:
- optional per-session tool selection
- persisted run history
This is how Eryx keeps "ongoing work" first class. Sessions can survive restarts, can be organized, and can accumulate operational history over time.
This is how Aryx keeps "ongoing work" first class. Sessions can survive restarts, can be organized, and can accumulate operational history over time.
### Runs
@@ -171,7 +171,7 @@ That run model is what enables the activity panel and historical timeline instea
## Communication model
Eryx uses two main communication links:
Aryx uses two main communication links:
### 1. Renderer <-> main process
@@ -301,7 +301,7 @@ This keeps those concerns out of the renderer while still letting the UI feel na
## Build and release architecture
Eryx ships as an Electron application bundled together with a self-contained .NET sidecar.
Aryx ships as an Electron application bundled together with a self-contained .NET sidecar.
The build pipeline is organized around three layers:
@@ -315,7 +315,7 @@ This packaging model matches the runtime architecture: one desktop shell plus on
## Why this architecture works well
This architecture fits the product because it gives Eryx:
This architecture fits the product because it gives Aryx:
- a clear privilege split between UI and native capabilities
- a stable, persistent workspace model
+15 -15
View File
@@ -1,21 +1,21 @@
<p align="center">
<img src="assets/icons/icon.png" alt="Eryx logo" width="180" />
<img src="assets/icons/icon.png" alt="Aryx logo" width="180" />
</p>
<h1 align="center">Eryx</h1>
<h1 align="center">Aryx</h1>
<p align="center">
A desktop workspace for Copilot-powered work across real projects.
</p>
Eryx is built for people who want more than a generic AI chat window. It gives you a place to ask quick questions, connect real projects, run reusable agent patterns, and keep ongoing work organized in one app.
Aryx is built for people who want more than a generic AI chat window. It gives you a place to ask quick questions, connect real projects, run reusable agent patterns, and keep ongoing work organized in one app.
It works especially well when you want AI help that stays grounded in an actual codebase: your folders, your repository state, your current branch, and your active work.
## Why use Eryx?
## Why use Aryx?
- **Start fast** with a scratchpad conversation for quick questions and ad-hoc work.
- **Work against real projects** by attaching local folders and letting Eryx stay aware of repository context.
- **Work against real projects** by attaching local folders and letting Aryx stay aware of repository context.
- **Go beyond one assistant** with orchestration patterns such as single-agent, sequential, concurrent, handoff, and group-chat flows.
- **See what is happening** with live activity for each agent while a run is in progress.
- **Stay organized** with persistent sessions you can rename, pin, archive, and return to later.
@@ -29,11 +29,11 @@ If you just want to think through an idea, draft something, or ask for help with
### Connect a real project
Add a local folder when you want help that is grounded in your work. Eryx is designed to feel strongest when it is attached to a real project instead of acting like a general-purpose chatbot.
Add a local folder when you want help that is grounded in your work. Aryx is designed to feel strongest when it is attached to a real project instead of acting like a general-purpose chatbot.
### Choose how agents collaborate
Eryx supports several ways of working:
Aryx supports several ways of working:
- **Single** for direct one-agent help
- **Sequential** for pipeline-style work where each agent sees the full conversation and appends its contribution
@@ -59,7 +59,7 @@ Sessions are persistent, so you can return to ongoing work instead of starting f
## Before you start
To use Eryx comfortably, make sure you have:
To use Aryx comfortably, make sure you have:
- a **Windows machine**
- **GitHub Copilot CLI** installed and available as `copilot`
@@ -67,11 +67,11 @@ To use Eryx comfortably, make sure you have:
- a local folder or git repository ready to connect if you want project-aware help
- any MCP servers or language servers you want to use installed and reachable from your machine
Eryx includes connection status in the app so you can quickly tell whether Copilot is ready before you start a session.
Aryx includes connection status in the app so you can quickly tell whether Copilot is ready before you start a session.
## Getting started
1. **Open Eryx**
1. **Open Aryx**
Launch the app and head to settings if you want to confirm your Copilot connection first.
2. **Check that Copilot is ready**
@@ -84,14 +84,14 @@ Eryx includes connection status in the app so you can quickly tell whether Copil
Use a simple single-agent setup to begin, or choose a saved multi-agent pattern when you want a more structured workflow.
5. **Configure optional tooling**
If you want MCP or LSP support, add the global definitions in settings and then enable the ones you want for the current session from the Activity panel. Eryx also surfaces Copilot CLI runtime tools for tool auto-approval, and you can set pattern-level defaults and override them per session.
If you want MCP or LSP support, add the global definitions in settings and then enable the ones you want for the current session from the Activity panel. Aryx also surfaces Copilot CLI runtime tools for tool auto-approval, and you can set pattern-level defaults and override them per session.
6. **Start working**
Ask a question, describe a task, or explore a project. As the run progresses, you can watch the participating agents and keep the session for later.
## When Eryx feels most useful
## When Aryx feels most useful
Eryx shines when you want to:
Aryx shines when you want to:
- move from quick chat to deeper multi-step work without leaving the app
- keep AI conversations tied to actual projects instead of isolated prompts
@@ -115,6 +115,6 @@ GitHub Actions now runs validation on pushes and pull requests, and pushing a gi
## Current focus
Eryx is focused on local, project-based work with your GitHub Copilot account. It already covers the essentials for working with projects, sessions, and reusable orchestration patterns, and it is growing toward a fuller AI workstation experience over time.
Aryx is focused on local, project-based work with your GitHub Copilot account. It already covers the essentials for working with projects, sessions, and reusable orchestration patterns, and it is growing toward a fuller AI workstation experience over time.
If you want an AI app that feels closer to a control room for real work than a blank chat box, Eryx is built for that.
If you want an AI app that feels closer to a control room for real work than a blank chat box, Aryx is built for that.
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "eryx",
"name": "aryx",
"version": "1.0.0",
"description": "Electron orchestrator for Copilot-powered agent workflows across multiple projects.",
"private": true,
+2 -2
View File
@@ -1,5 +1,5 @@
export const productName = 'Eryx';
export const macBundleIdentifier = 'com.davidkaya.eryx';
export const productName = 'Aryx';
export const macBundleIdentifier = 'com.davidkaya.aryx';
type SupportedPlatform = 'win32' | 'darwin' | 'linux';
type SupportedArch = 'x64' | 'arm64';
@@ -27,7 +27,7 @@ internal static class CopilotCliPathResolver
if (string.IsNullOrWhiteSpace(cliPath))
{
throw new InvalidOperationException(
"Eryx requires the system-installed 'copilot' command on PATH. Install the GitHub Copilot CLI and ensure it is available in the current environment.");
"Aryx requires the system-installed 'copilot' command on PATH. Install the GitHub Copilot CLI and ensure it is available in the current environment.");
}
CopilotCliLaunch launch = ResolveCliLaunch(
@@ -156,7 +156,7 @@ internal static partial class CopilotConnectionMetadataResolver
}
catch (Exception exception)
{
Console.Error.WriteLine($"[eryx sidecar] Failed to inspect Copilot auth status: {exception.Message}");
Console.Error.WriteLine($"[aryx sidecar] Failed to inspect Copilot auth status: {exception.Message}");
return null;
}
}
@@ -198,7 +198,7 @@ internal sealed class LspToolSession : IAsyncDisposable
},
clientInfo = new
{
name = "Eryx",
name = "Aryx",
version = "1.0.0",
},
},
@@ -516,7 +516,7 @@ internal sealed class LspToolSession : IAsyncDisposable
if (!string.IsNullOrWhiteSpace(line))
{
RecordStderrLine(line);
Console.Error.WriteLine($"[eryx lsp:{_profile.Id}] {line}");
Console.Error.WriteLine($"[aryx lsp:{_profile.Id}] {line}");
}
}
}
@@ -236,7 +236,7 @@ public sealed class SidecarProtocolHost
catch (Exception exception)
{
SidecarConnectionDiagnosticsDto connection = CreateMissingCliDiagnostics(exception);
Console.Error.WriteLine($"[eryx sidecar] {connection.Summary} {exception.Message}");
Console.Error.WriteLine($"[aryx sidecar] {connection.Summary} {exception.Message}");
return CreateCapabilities([], [], connection);
}
}
@@ -279,7 +279,7 @@ public sealed class SidecarProtocolHost
catch (Exception exception)
{
cliVersion = await cliVersionTask.ConfigureAwait(false);
Console.Error.WriteLine($"[eryx sidecar] Failed to list available Copilot models: {exception.Message}");
Console.Error.WriteLine($"[aryx sidecar] Failed to list available Copilot models: {exception.Message}");
return new CapabilityProbeResult(
models,
@@ -351,7 +351,7 @@ public sealed class SidecarProtocolHost
}
catch (Exception exception)
{
Console.Error.WriteLine($"[eryx sidecar] Failed to list available Copilot runtime tools: {exception.Message}");
Console.Error.WriteLine($"[aryx sidecar] Failed to list available Copilot runtime tools: {exception.Message}");
return [];
}
}
@@ -423,8 +423,8 @@ public sealed class SidecarProtocolHost
{
string status = ClassifyConnectionStatus(exception);
string summary = status == "copilot-auth-required"
? "GitHub Copilot requires authentication before Eryx can load models."
: "GitHub Copilot was found, but Eryx could not load its model list.";
? "GitHub Copilot requires authentication before Aryx can load models."
: "GitHub Copilot was found, but Aryx could not load its model list.";
return new SidecarConnectionDiagnosticsDto
{
+2 -2
View File
@@ -145,7 +145,7 @@ export class EryxAppService extends EventEmitter<AppServiceEvents> {
if (!this.didScheduleInitialProjectGitRefresh) {
this.didScheduleInitialProjectGitRefresh = true;
void this.refreshProjectGitContext().catch((error) => {
console.error('[eryx git]', error);
console.error('[aryx git]', error);
});
}
@@ -1348,7 +1348,7 @@ export class EryxAppService extends EventEmitter<AppServiceEvents> {
changed = true;
const failedAt = nowIso();
const error = 'Pending approval was interrupted because Eryx restarted before a decision was recorded.';
const error = 'Pending approval was interrupted because Aryx restarted before a decision was recorded.';
const requestIds = this.rejectPendingApprovals(session, failedAt, error);
session.status = 'error';
session.lastError = error;
+1 -1
View File
@@ -1,6 +1,6 @@
import keytar from 'keytar';
const serviceName = 'eryx';
const serviceName = 'aryx';
export class SecretStore {
async get(account: string): Promise<string | null> {
+1 -1
View File
@@ -115,7 +115,7 @@ export class SidecarClient {
childProcess.stderr.setEncoding('utf8');
childProcess.stderr.on('data', (chunk: string) => {
console.error('[eryx sidecar]', chunk.trim());
console.error('[aryx sidecar]', chunk.trim());
});
childProcess.on('exit', (code) => {
+1 -1
View File
@@ -11,7 +11,7 @@ export function createMainWindow(): BrowserWindow {
height: 960,
minWidth: 1120,
minHeight: 720,
title: 'eryx',
title: 'aryx',
icon: resolveWindowIconPath({
appPath: app.getAppPath(),
platform: process.platform,
+1 -1
View File
@@ -50,4 +50,4 @@ const api: ElectronApi = {
},
};
contextBridge.exposeInMainWorld('eryxApi', api);
contextBridge.exposeInMainWorld('aryxApi', api);
+2 -2
View File
@@ -293,7 +293,7 @@ function AppearanceSection({
<div className="mb-1">
<h3 className="text-[13px] font-semibold text-zinc-200">Appearance</h3>
<p className="mt-0.5 text-[12px] text-zinc-500">
Choose how Eryx looks on your device
Choose how Aryx looks on your device
</p>
</div>
@@ -348,7 +348,7 @@ function ConnectionSection({
<div className="mb-1">
<h3 className="text-[13px] font-semibold text-zinc-200">GitHub Copilot</h3>
<p className="mt-0.5 text-[12px] text-zinc-500">
Eryx uses your installed GitHub Copilot CLI for AI capabilities
Aryx uses your installed GitHub Copilot CLI for AI capabilities
</p>
</div>
<div className="mt-4 rounded-xl border border-[var(--color-border)] bg-zinc-900/30 p-4">
+2 -2
View File
@@ -524,9 +524,9 @@ export function Sidebar({
{/* Header — extra top padding clears the title bar overlay zone */}
<div className="drag-region flex items-center justify-between border-b border-[var(--color-border)] px-4 pb-3 pt-3">
<div className="flex items-center gap-2.5">
<img alt="eryx" className="size-8 rounded-xl" src={appIconUrl} />
<img alt="aryx" className="size-8 rounded-xl" src={appIconUrl} />
<div>
<span className="text-sm font-semibold text-zinc-100">eryx</span>
<span className="text-sm font-semibold text-zinc-100">aryx</span>
<span className="ml-1.5 rounded bg-zinc-800 px-1 py-0.5 text-[9px] font-medium text-zinc-500">
ALPHA
</span>
+1 -1
View File
@@ -21,7 +21,7 @@ export function WelcomePane({
</div>
<div>
<h1 className="text-base font-semibold text-zinc-100">Welcome to eryx</h1>
<h1 className="text-base font-semibold text-zinc-100">Welcome to aryx</h1>
<p className="mt-2 max-w-md text-[13px] leading-relaxed text-zinc-500">
Start a scratchpad conversation for ad-hoc questions or connect a project to work with
repo-aware Copilot agents.
+1 -1
View File
@@ -2,7 +2,7 @@ import type { ElectronApi } from '@shared/contracts/ipc';
declare global {
interface Window {
eryxApi: ElectronApi;
aryxApi: ElectronApi;
}
}
+1 -1
View File
@@ -6,7 +6,7 @@
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<title>eryx</title>
<title>aryx</title>
</head>
<body class="bg-slate-950 text-slate-100">
<div id="root"></div>
+2 -2
View File
@@ -1,7 +1,7 @@
export function getElectronApi() {
if (!window.eryxApi) {
if (!window.aryxApi) {
throw new Error('The Electron preload API is unavailable.');
}
return window.eryxApi;
return window.aryxApi;
}
+1 -1
View File
@@ -28,7 +28,7 @@ export interface MarkdownPasteInspection {
reason: MarkdownPasteReason;
}
export const markdownEditorNamespace = 'eryx-markdown-composer';
export const markdownEditorNamespace = 'aryx-markdown-composer';
export const markdownEditorNodes: ReadonlyArray<Klass<LexicalNode>> = [
HeadingNode,
+1 -1
View File
@@ -24,7 +24,7 @@ export function applySessionEventActivity(
if (event.kind === 'agent-activity') {
const agentKey = resolveAgentKey(event);
if (!agentKey) {
console.warn('[eryx activity] Dropping agent-activity event without agentId/agentName.', event);
console.warn('[aryx activity] Dropping agent-activity event without agentId/agentName.', event);
return current;
}
+4 -4
View File
@@ -15,18 +15,18 @@ describe('resolveWindowIconPath', () => {
test('uses the macOS icns asset on Darwin', () => {
expect(
resolveWindowIconPath({
appPath: '/Applications/Eryx.app/Contents/Resources/app',
appPath: '/Applications/Aryx.app/Contents/Resources/app',
platform: 'darwin',
}),
).toBe('/Applications/Eryx.app/Contents/Resources/app/assets/icons/macos/icon.icns');
).toBe('/Applications/Aryx.app/Contents/Resources/app/assets/icons/macos/icon.icns');
});
test('uses the Linux 512px PNG asset on Linux', () => {
expect(
resolveWindowIconPath({
appPath: '/opt/eryx/resources/app',
appPath: '/opt/aryx/resources/app',
platform: 'linux',
}),
).toBe('/opt/eryx/resources/app/assets/icons/linux/icons/512x512.png');
).toBe('/opt/aryx/resources/app/assets/icons/linux/icons/512x512.png');
});
});
+4 -4
View File
@@ -43,14 +43,14 @@ describe('resolveSidecarProcess', () => {
expect(
resolveSidecarProcess({
isPackaged: true,
appPath: '/Applications/Eryx.app/Contents/Resources/app',
resourcesPath: '/Applications/Eryx.app/Contents/Resources',
appPath: '/Applications/Aryx.app/Contents/Resources/app',
resourcesPath: '/Applications/Aryx.app/Contents/Resources',
platform: 'darwin',
}),
).toEqual({
command: '/Applications/Eryx.app/Contents/Resources/sidecar/Eryx.AgentHost',
command: '/Applications/Aryx.app/Contents/Resources/sidecar/Eryx.AgentHost',
args: ['--stdio'],
cwd: '/Applications/Eryx.app/Contents/Resources/sidecar',
cwd: '/Applications/Aryx.app/Contents/Resources/sidecar',
});
});
});
+11 -11
View File
@@ -13,10 +13,10 @@ describe('resolveReleaseTarget', () => {
arch: 'x64',
platformLabel: 'windows',
dotnetRuntime: 'win-x64',
outputDirectoryName: 'Eryx-windows-x64',
archiveBaseName: 'Eryx-windows-x64',
outputDirectoryName: 'Aryx-windows-x64',
archiveBaseName: 'Aryx-windows-x64',
sidecarExecutableName: 'Eryx.AgentHost.exe',
packagedExecutableName: 'Eryx.exe',
packagedExecutableName: 'Aryx.exe',
});
});
@@ -26,10 +26,10 @@ describe('resolveReleaseTarget', () => {
arch: 'arm64',
platformLabel: 'macos',
dotnetRuntime: 'osx-arm64',
outputDirectoryName: 'Eryx-macos-arm64',
archiveBaseName: 'Eryx-macos-arm64',
outputDirectoryName: 'Aryx-macos-arm64',
archiveBaseName: 'Aryx-macos-arm64',
sidecarExecutableName: 'Eryx.AgentHost',
appBundleName: 'Eryx.app',
appBundleName: 'Aryx.app',
});
});
@@ -39,16 +39,16 @@ describe('resolveReleaseTarget', () => {
arch: 'x64',
platformLabel: 'linux',
dotnetRuntime: 'linux-x64',
outputDirectoryName: 'Eryx-linux-x64',
archiveBaseName: 'Eryx-linux-x64',
outputDirectoryName: 'Aryx-linux-x64',
archiveBaseName: 'Aryx-linux-x64',
sidecarExecutableName: 'Eryx.AgentHost',
packagedExecutableName: 'Eryx',
packagedExecutableName: 'Aryx',
});
});
test('exports the expected product metadata constants', () => {
expect(productName).toBe('Eryx');
expect(macBundleIdentifier).toBe('com.davidkaya.eryx');
expect(productName).toBe('Aryx');
expect(macBundleIdentifier).toBe('com.davidkaya.aryx');
});
test('rejects unsupported platforms', () => {
+3 -3
View File
@@ -10,7 +10,7 @@ import {
describe('scratchpad project helpers', () => {
test('creates a stable built-in scratchpad project', () => {
const project = createScratchpadProject('C:\\Users\\me\\AppData\\Roaming\\eryx\\scratchpad');
const project = createScratchpadProject('C:\\Users\\me\\AppData\\Roaming\\aryx\\scratchpad');
expect(project.id).toBe(SCRATCHPAD_PROJECT_ID);
expect(project.name).toBe(SCRATCHPAD_PROJECT_NAME);
@@ -38,7 +38,7 @@ describe('scratchpad project helpers', () => {
addedAt: '2026-03-23T00:00:00.000Z',
},
],
'C:\\Users\\me\\AppData\\Roaming\\eryx\\scratchpad',
'C:\\Users\\me\\AppData\\Roaming\\aryx\\scratchpad',
);
expect(merged[0].id).toBe(SCRATCHPAD_PROJECT_ID);
@@ -69,7 +69,7 @@ describe('scratchpad project helpers', () => {
},
},
],
'C:\\Users\\me\\AppData\\Roaming\\eryx\\scratchpad',
'C:\\Users\\me\\AppData\\Roaming\\aryx\\scratchpad',
);
expect(merged[0].git).toBeUndefined();