AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
Your coding agents, forged into one desk. An open-source desktop for Omarchy that runs Claude Code, Codex, Grok and every coding CLI you use — agents, routines, tasks and real terminals.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Your coding agents, forged into one desk.
An open-source desktop for Omarchy that runs Claude Code, Codex, Grok and every other coding CLI you already use — in real terminals, as a team.README 전문 보기 ↗VibeForge never calls a model API and never holds a key. Every engine is a CLI you are already signed in to; VibeForge gives them a home. It remembers who does the work (agents with a brief, memory and skills), where they may work (allowed folders), when work starts (routines), and what to review when it ends (every run keeps its final screen, a transcript and the git diff since it began). No accounts. No telemetry. Everything on disk is plain YAML and Markdown.
On Omarchy (or any Arch + Hyprland setup):
curl -fsSL https://vibe-forge.net/install | bash
Then open VibeForge from the app launcher (Super + Space) or run vibeforge. Add --uninstall to remove the launcher (your data stays).
The installer needs git, Node 20.19+ or 22.12+ (Omarchy ships mise: mise use -g node@lts) and base-devel + python to build the terminal engine. It clones into ~/.local/share/vibeforge-app, checks out the newest release, and adds ~/.local/bin/vibeforge and a desktop entry. Set VIBEFORGE_BRANCH=main to follow the main branch instead.
Updating. VibeForge asks GitHub for the newest release number when it starts and every six hours (nothing else is sent; turn it off in Settings → Updates). When one is out, Help in the rail gets a dot: Update shows the release notes, runs the installer in a terminal you can watch, then restarts. Running the install command again does the same.
git clone https://github.com/L0nE-F0x/VibeForge.git
cd VibeForge
npm install
npm start # development: Vite + Electron with hot reload
npm run build # production build, when you want it now
./scripts/vibeforge # builds when this checkout is newer, then opens the window
| View | What it is for |
|---|---|
| Home | Who is waiting for you, by name, and what is waiting its turn; what's live, what finished and needs review, what fires next, and a year of your commits drawn in pixels. |
| Agents | Named teammates with a brief, memory, skills and allowed folders. Chats with an agent are real terminals. Switch its engine from Claude to Codex to Grok and the teammate stays the same. |
| Code | A workspace with tiled terminals that you can split, drag to rearrange and maximize, a file tree that inserts paths, and a browser beside them: click an http(s) link in a terminal (your dev server's, say) and it opens there, each workspace keeping its own page. Type claude, codex or any CLI in a terminal: its title bar says so, and from the moment it starts until you're back at the prompt it is recorded as a run (transcript and git diff). A terminal whose CLI goes quiet or finishes while you're looking elsewhere glows like an ember until you focus it, and so do its workspace and Code's icon in the rail. Looking at one terminal leaves the others glowing. Each title bar says which other coding CLIs are in the same folder. In a split, the terminals you aren't typing in dim a little. Drag workspaces to reorder them and jump between them with Alt+1…9. Open another branch, on a workspace's menu, checks that branch out beside the project and opens it as its own workspace. The folder you already have stays on its branch, and removing the new workspace later leaves its folder on disk. Layouts are remembered per workspace. |
| Chat | Throwaway conversations in an empty scratch folder. |
| Tasks | A board. Writing or assigning a task starts nothing; Execute does. A finished run lands in Review with its diff. A new task in a git workspace starts with Work in a separate copy on: the agent works in its own git worktree on a vibeforge/<task> branch, so it never touches the folder you or another agent are in; Apply brings its changes into the workspace as uncommitted edits (conflicts are marked, as a merge would) and removes the copy. In the workspace itself, a task takes turns: while another coding CLI is busy in that folder, Execute waits and starts on its own once that CLI has been quiet for half a minute (or start it now, in a copy or anyway). Hand off, on a finished run, makes a To do task for another agent from it. |
| Routines | Cron or interval schedules that open a fresh agent run while VibeForge is running, in the tray too. A due routine takes turns like a task: it waits while another coding CLI is busy in its folder. Missed slots are shown, never replayed. A routine whose last three runs failed glows here and on Home until one succeeds. |
The pulse at the bottom of the rail counts the terminals running and, underneath, six squares that follow whichever coding plan is closest to its limit. Click it for plan limits: each signed-in plan's windows (Claude's 5-hour and 7-day, Grok's credits by product, Gemini's 5-hour, 7-day and Gemini 4 Argon, Kimi's weekly and 5-hour, Codex's and Muse's 5-hour and weekly) with the time until they reset, the last day as a line, and when you'll run out at the current pace. A plan you aren't signed in to stays off the list, and one you sign in to appears on the next refresh. The Tokens tab has each CLI's tokens today, over the last 7 and 30 days, and all time, read from the logs Claude Code, Codex, Grok Build, Antigravity CLI, Gemini CLI, Kimi Code, Muse Code, OpenCode and Copilot CLI already keep on this machine; nothing is sent anywhere for those. Cursor Agent and Crush don't keep token counts that can be added up, so they don't appear. The CLIs clear their old logs, so VibeForge keeps each day's count (~/.local/share/vibeforge/usage-days.json) and all time keeps growing after they do.
Plan limits are off until you turn them on in Settings → Usage and activity. VibeForge then asks Anthropic, xAI, Google, Moonshot, OpenAI and Meta, at most every 3 minutes, with the sign-in each CLI already saved on this machine. It reads that sign-in for each request and never renews, rewrites or keeps it; when one has expired, the last numbers stay up until you next open that CLI. Codex's and Muse's limits also come from their own logs, with no network. Only the percentages are saved (~/.local/share/vibeforge/plans.json). Settings can also notify you as a window passes 80%, 95% and 100%, once per step until it resets; that's off, since Omarchy's own usage widget may already tell you.
The graph on Home is your commits in your workspaces, read with git. If you'd rather see your GitHub contribution graph, pick GitHub in Settings → Usage and activity: VibeForge then asks GitHub for it through the gh CLI you're signed in to, at most every 30 minutes, and keeps no token. That's off until you choose it.
It keeps your place. Each view reopens where you left it, the same agent, chat or task with its list scrolled where it was, including after a restart. A half-written message or an unsaved brief, task or skill waits for you until you send it, save it or press Discard. Ctrl+K (or the logo at the top of the rail) jumps to any agent, chat, workspace, task, routine or skill by typing part of its name, to a task, routine or skill by something it says, or to a run by something it said. Deleting a chat, task, skill or routine happens at once, with Undo on the toast (or Ctrl+Z) for a few seconds; only one that is still running asks first.
When an agent or CLI goes quiet while you're looking elsewhere, or sits on a question when it starts (trust this folder? sign in?), it glows until you look: its terminal and workspace in Code, the agent and its chat in Agents, a row under Waiting for you on Home, and a dot on the rail. Short tones, made on your machine, say the same: two soft knocks when it's your turn, a rising chime when a task, routine or typed CLI finishes, a lower one when it fails, and a chirp when dictation starts and stops. By default they play only while VibeForge is in the background, never while Omarchy's Do Not Disturb is on (voice aside), and each one can be turned off or previewed in Settings → Sounds.
It lives in the tray, next to Steam and the rest in Omarchy's bar (right-click the tray's arrow to pin it to the bar itself). A click opens the window; right-click for sounds, notifications, Start at login, in the tray, and Quit. The icon gets an amber corner while something is waiting for you, and the menu lists who, each opening right where it waits. Closing the window leaves VibeForge running there, so terminals keep going and routines keep firing; Settings → Tray and startup changes any of that. Start at login adds an entry to ~/.config/autostart, the same way Omarchy starts other tray apps, and is off until you turn it on.
It looks like the rest of Omarchy: square corners, JetBrains Mono with Geist headings, flat panels and pixel art, with light kept for what's alive: a working CLI is a slow ember, and one waiting for you glows. It wears your Omarchy theme: colours come from the active theme (colors.toml plus the ghostty palette for terminals) and change live when you switch themes, pixel wordmark included. Rather keep one? Settings → Appearance can pin any installed theme or any of Omarchy's stock themes, which VibeForge ships, so they work on other desktops too.
It speaks English, Deutsch, Español, Français, Português (Brasil), 日本語 and 简体中文, following your system language unless you pick one in Settings. The whole window is translated, errors included, and so are the tray menu, the quit question, desktop notifications, schedule descriptions and git's change summaries. Translations live in src/ui/i18n/, one file per language, and the typecheck fails if one is missing a line.
Anything with a command line. The defaults know how to hand a first prompt to Claude Code, Codex, Grok, Cursor Agent, Antigravity CLI, OpenCode and Muse as an argument, and paste it into Copilot, Kimi, Crush, Pi, Hermes or any other CLI once it's ready. Add your own in Settings or in ~/.config/vibeforge/engines.json:
{ "id": "claude", "label": "Claude Code", "bin": "claude", "args": [],
"promptArgs": ["{prompt}"], "continueArgs": ["--continue"] }
args are always passed. promptArgs puts the first message on the command line ({prompt} is replaced); leave it out and VibeForge pastes the message once the CLI is ready. continueArgs reopens the CLI's latest session in a folder — and when a CLI prints its own resume line on exit (claude --resume <id>, grok --resume <id>, codex resume <id>, agy --conversation <id>), Continue uses that exact session instead.
React UI ──IPC──▶ Electron main ──JSON lines──▶ PTY host (system Node)
agents, chats, tasks, node-pty + a headless xterm per
routines, runs, scheduler terminal → your CLIs
meta.json in each run folder plus a SQLite index, with change events pushed to the UI.PATH at start, so CLIs installed with mise or into ~/.local/bin are found however it was launched.Two CLIs open side by side can work together. Every VibeForge terminal has a vibeforge command on its PATH, so a CLI can run it with its own shell tool:
vibeforge who # the CLIs open now, and the agents you can hand tasks to (by id)
vibeforge tell codex "Can you check the migration in db/?"
vibeforge tell codex --wait "Is this regex safe?" # prints Codex's answer
vibeforge task helper "Write tests for src/parse.ts"
tell pastes the message into the other CLI once it is free, labelled with who sent it and how to answer. With --wait the answer comes back to the one who asked: from the CLI's own session log for Claude Code, Codex, Grok Build and Kimi Code, and from its screen for the rest. If the answer takes longer than the wait (9 minutes unless --timeout says otherwise), it arrives later as a message. task hands a VibeForge agent a task that runs in its own git copy of the workspace, never in the folder of the CLI that asked. When the agent finishes its turn, the CLI that asked gets a report as a message: what the agent said, its changes as a patch file with the files listed, and where its copy is (or that it ended without answering). A person still applies the changes, and a task handed out this way can't hand out more. Agents that VibeForge starts are told these commands exist, and so are Claude Code, Codex and Grok Build when a Code pane starts them (added to their own instructions: --append-system-prompt, developer_instructions unless your Codex config sets its own, --rules). Other CLIs, and one you type into a shell yourself, learn them from the first message they get, or from vibeforge help.
A lead. Settings → Agents together can make one CLI the lead in Code (Claude Code, say). A Code pane that starts it tells it your team: the agents allowed in that workspace, with the one-line Good at and the Cost (Cheap, Everyday, Strong) from each agent's Settings tab. It hands out parts of the work when another agent is better or cheaper for them, or when parts can run at once, and does the rest itself. Under Ask first (the default) a task any CLI hands out waits for you: its title bar shows "N to start". Under Go ahead tasks start at once, up to a number working at once and a number per message from you; past that they wait for you too. With Let it apply its helpers' changes on, the CLI that handed a task out can run vibeforge apply <task>; otherwise you apply them from the task. A helper that stops at a question for a person (a folder-trust prompt, say) is reported as waiting, not as finished.
In Code, the send button on a terminal's title bar does the same by hand: Send to… puts that CLI's last answer, the text you selected or its changes into another CLI's prompt for you to read and send, and Ask … to review its changes has the other CLI review this one's diff when its turn ends and sends the review back (one round, or more in Settings). Two CLIs can trade 8 messages before the next one waits in the prompt for you to press Enter; typing in either terminal starts the count again. The title bar shows who a CLI is talking with, and its stop button ends it until you type there. Settings → Agents together turns it off or changes the limits.
Talk to your agents instead of typing to them, and hear them answer. Everything happens on this machine: whisper.cpp turns speech into text, Piper reads answers aloud, and no audio leaves your computer or is kept.
sudo pacman -S whisper-cpp # listening
uv tool install piper-tts # talking back (or the AUR's piper-tts-bin)
Dictate. Hold Ctrl+Shift+Space and speak, then let go (Esc drops it). The words land in the message box or terminal that has focus, and wait there for you to read and press Enter. Message boxes and Code's toolbar also have a mic: click it, speak for as long as you like, and click it again (or hold it and let go). Code's mic types into the terminal that has focus and hands the keyboard back to it, so Enter sends.
Hear the answer. After you send a message you dictated, the first paragraph of the reply is read aloud, in that agent's voice (its Settings tab). Claude Code and Codex answers come from their own session logs. Hold the dictate key to cut an answer short. Settings → Voice can turn this off.
From anywhere on the desktop. Hold Super+Alt+V to talk to one agent: the one you pick in Settings → Voice, or the one you last dictated to. The words land in that agent's chat for you to read, and still wait for Enter. Settings → Voice adds the binding to Hyprland for you (or copy it):
o.bind("SUPER + ALT + V", "VibeForge: hold to talk", "vibeforge --voice start")
o.bind("SUPER + ALT + V", "VibeForge: stop talking", "vibeforge --voice stop", { release = true })
vibeforge --voice start|stop|cancel reaches the running window over a local socket in a few milliseconds; a short tone marks the start and end while it's in the background. Models (base.en is quick, large-v3-turbo hears best and knows many languages) and voices download from Hugging Face in Settings → Voice, and ones Omarchy's Voxtype or the AUR's piper-voices packages installed are found too. Whisper is told the names of your agents, routines, CLIs and workspace files, so it spells them right.
Settings → Phone serves a small page for your phone: each workspace and the coding CLIs in it, your plan limits, a CLI's screen, and a box to tell it what to do next. From there you can start an agent, or any CLI on its own, in a workspace; send a prompt; pick a finished session back up with your next instruction; and stop it. A CLI you typed into a terminal is only interrupted (Esc), so the terminal stays open, and nothing from the phone is ever typed into a terminal that has no CLI running in it.
It is off until you turn it on, and then it listens on 127.0.0.1:4737 only. The page asks once for the pairing code shown in Settings (it's kept in settings.json) and remembers it in the phone's browser; New code signs every phone out. To reach it from your phone, run Tailscale Serve once on this computer:
tailscale serve --bg --https=443 http://127.0.0.1:4737
then open the https address it prints on your phone, signed in to the same tailnet. The page offers to install itself, and the installed page fills the screen. Serve keeps the page inside your tailnet; tailscale funnel would put it on the internet, so don't use that. The computer has to stay on and awake with VibeForge running (the tray is enough). While the page is open it buzzes when a CLI starts waiting or finishes; a buzz on a locked phone isn't built yet. Plan limits on the phone are the same numbers as the desktop's and follow the same Settings switch. The page speaks the language VibeForge does, or your phone's when VibeForge follows the system.
~/.config/vibeforge/ edit anywhere — VibeForge picks up changes live
agents/<id>/agent.yaml name, engine, brief, allowed folders, skills
agents/<id>/memory.md durable notes added to every run
skills/<id>/SKILL.md
routines/<id>.yaml
tasks/<id>.yaml
engines.json settings.json workspaces.json layouts/
~/.local/share/vibeforge/
runs/<stamp>_<slug>/ meta.json, preamble.md, terminal.ansi, transcript.txt, scrollback.txt, git.txt, diff.patch
(the last two gzipped once the run has ended; Settings → Storage says how long runs are kept)
worktrees/<task>/ separate copies for tasks that work in one, until Apply or Discard
trash/ deleted chats, tasks, skills and routines, kept 30 s for Undo
scratch/<chat>/ Chat mode working folders
models/ voices/ whisper models and Piper voices downloaded in Settings → Voice
Override the roots with VIBEFORGE_CONFIG and VIBEFORGE_DATA. VibeForge's own log is ~/.local/share/vibeforge/logs/vibeforge.log: what the app did and what went wrong, never prompts or terminal output. Help → Copy diagnostics puts your versions, a few settings and its last 200 lines on the clipboard for a bug report.
Ctrl+K go to anything (Ctrl+Shift+K inside a terminal) · Ctrl+1…8 views · Alt+1…9 workspaces · Ctrl+, settings · Alt+←/→ or the mouse's side buttons back and forward · ↑/↓ move through the list you're in · Ctrl+Shift+B collapse the side panel · Ctrl+Shift+D/E new terminal right/below · Ctrl+Shift+W close it · Ctrl+Shift+M maximize the focused pane · Ctrl+Shift+/ every shortcut · Ctrl+S save · Ctrl+Z undo a delete while its toast is up · Esc close · Ctrl+Shift+Space dictate (hold, then let go) · in terminals Ctrl+C copies the selection (with nothing selected it interrupts the program) and Ctrl+V pastes (an image on its own goes to the program, so Claude Code can paste it); Omarchy's Super+C/V, Ctrl+Insert/Shift+Insert and Ctrl+Shift+C/V work too · drop files on a terminal to insert their paths.
In Code, drag a pane by its title bar onto another pane: the middle swaps them, an edge docks it on that side. Double-click a title bar to maximize. Right-click a view in the rail to hide it; Settings → Rail shows it again and sets the order. Side panels resize from their edge and collapse to a strip. Help in the rail replays the welcome tour, checks for updates, copies diagnostics, and opens bug reports and feature ideas as GitHub issues with your versions filled in; nothing is sent from the app.
npm test # unit tests + the real PTY host driven with /bin/bash (never a model CLI)
npm run typecheck
npm run lint # Biome, bug-shaped rules only
npm run coverage # the tests with coverage; src/core keeps 85% of its lines covered
npm run build && npm run smoke # the built app: every view, a language switch, Ctrl+K and a shell
# (SMOKE_HEADLESS=1 draws no window; CI runs it under xvfb)
The code is in src/core (the service, storage, scheduler — plain Node), src/ui (React) and electron/ (main process, preload, PTY host). The pixel font, mark and pixel fields live in src/shared/pixel.ts; node scripts/brand.ts (Node 22.18+, which runs TypeScript as is) regenerates the icon, the website's inline pixel art and the social image from it. The website is plain HTML/CSS/JS in site/ and deploys to Netlify from netlify.toml with no build step; preview it with python3 -m http.server -d site. docs/original-brief.md is the product brief VibeForge grew from; docs/status.md says what has been verified.
VibeForge is an independent project. It is not affiliated with Omarchy, Anthropic, OpenAI, xAI, Google, Meta, Moonshot, GitHub, Tailscale or any CLI it runs; their names are used only to say what VibeForge works with. Released under the MIT license.
Contributing notes are in CONTRIBUTING.md. Everyone here follows the code of conduct.
| Skills | Reusable SKILL.md procedures you install on agents. |
| Runs | Every CLI you typed into a terminal and every process VibeForge started, a day at a time: final screen, transcript, prompt, and the full diff since it began, saved the moment it ended so later edits stay out of it. Continue reopens the exact session. Search finds a run by what it said, not only its title: the words around the match are shown, and Ctrl+K lists those runs too. Copy as Markdown in its ⋯ menu gives you the prompt, how it ended and its patch, ready for an issue or a pull request. |