# Bitig · Features & Differentiators Version 1.1.4 · Workspaces ("Otağ"), WebGL GPU acceleration, Draggable Split Panes, Settings Search README · Changelog · Roadmap
--- ## Vision: Why Another Terminal? Terminals on Windows have drifted to two extremes: | | Strength | Weakness | |---|---|---| | **Windows Terminal** | Fast, stable, native ConPTY | A plain text box; no contextual intelligence, no interactive assistance | | **Warp and cloud terminals** | Rich feature set | Mandatory account, cloud telemetry, a privacy problem in corporate environments | Bitig aims to close the gap between the two. Four core principles: | Principle | What it means | |---|---| | **100% local** | Zero cloud dependencies, zero telemetry, no account. All data lives as plain JSON under `%APPDATA%/Bitig/`. | | **No security compromises** | Strict Electron isolation (`contextIsolation: true`, `sandbox: true`), a separate Node `vm` context for plugins. | | **Keyboard first** | Every capability is reachable without a mouse via a single shortcut; every shortcut is rebindable. | | **Developer focused** | Turns an ordinary stream of text into a clickable, parametric, observable workstation. | --- ## Comparison Matrix Legend: `+` built in and complete, `~` partial or via plugin, `-` absent. | Feature | Windows Terminal | Warp | Hyper / Tabby | Bitig 1.1.4 | |---|:---:|:---:|:---:|:---| | ConPTY integration | `+` native | `-` custom engine | `~` node-pty | `+` **ConPTY + xterm.js** | | GPU Text Rendering | `+` DirectX | `+` Metal/OpenGL | `-` | `+` **WebGL 2.0 GPU Acceleration** | | Workspaces & Tree Sessions | `-` | `-` | `~` basic tabs | `+` **Otağ Binary Tree Workspaces (`Ctrl+Shift+O`)** | | Interactive Split Resizing | `+` | `-` | `~` | `+` **Draggable dividers with dynamic PTY refit** | | Settings Live Search | `+` | `+` | `~` | `+` **Instant full-text settings filtering** | | Windows Explorer Integration | `+` | `-` | `~` | `+` **Right-click menu + `bitig .` CLI** | | Drag & Drop Path Insertion | `+` | `+` | `~` | `+` **Smart auto-quoting + glow indicators** | | Multi-Pane Regex Search | `-` | `-` | `-` | `+` **`Ctrl+F` + `◫ Panes` across all splits** | | Auto-Update Pipeline | `+` Store | `+` auto | `~` | `+` **`electron-updater` GitHub Releases** | | Inline (ghost) command suggestions | `-` | `+` cloud-assisted | `-` | `+` **Local history + project aware, `Tab` to accept** | | Multiple independent windows | `+` | `+` | `+` | `+` **`Ctrl+Shift+N`, no background ghost process** | | Live working directory in tab title | `~` needs shell config | `+` | `~` | `+` **Automatic shell integration (OSC 7)** | | Local parametric runbooks | `-` | `~` cloud / account | `-` | `+` **Bitig Betik, local JSON (`Ctrl+Shift+B`)** | | Live port sniffer | `-` | `-` | `-` | `+` **ANSI-stripped, buffered, click to open** | | Secret Shield (token redaction) | `-` | `-` | `-` | `+` **Automatic masking** | | Local AI assistant | `~` Copilot | `~` Warp AI, cloud | `-` | `+` **Ollama + BYOK (`Ctrl+I`)** | | Quake / dropdown HUD | `~` separate mode | `-` | `~` via plugin | `+` **Built in (`Win+~`)** | | Broadcast input | `-` | `-` | `~` some builds | `+` **Built in (`Alt+Shift+I`)** | | IDE smart links | `-` URLs only | `~` partial | `-` URLs only | `+` **`vscode://`, Cursor** | | Nerd Font glyph probing | `-` | `-` | `-` | `+` **Canvas PUA probe** | | Sandboxed plugin runtime | `-` | `-` | `~` full Node access | `+` **Node `vm`, allowlisted API** | --- ## The Cockpit Surface ``` ┌────────────────────────────────────────────────────────────────────────┐ │ B I T I G C O C K P I T │ ├────────────────────────────────────────────────────────────────────────┤ │ Ports :3000 (Next.js) :5173 (Vite) Quake HUD Win+~ │ │ Betik Docker Dev Cluster Broadcast Alt+Shift+I│ │ Shield 1 API key masked Bilge AI Ctrl+I │ └────────────────────────────────────────────────────────────────────────┘ ``` --- ## 1. Inline Command Suggestions `Tab` to accept · Shipped v1.0.1 · Rebuilt in v1.0.2 **Problem.** You type `npm run dev` twenty times a day. Reaching for `Ctrl+R` and searching history for a command you already know by heart is friction, and the shell's own `Tab` completion knows nothing about the commands *you* actually run. **Solution.** As you type, Bitig renders the most likely full command as translucent ghost text after the cursor. Press `Tab` (or `→` / `End` at the end of the line) to accept it, `Ctrl`/`Alt`+`→` to accept a single word or path segment, `Esc` to dismiss. If there is no suggestion, `Tab` is passed straight through to the shell, so native completion is never broken. A suggestion is always a **true prefix extension** of what you typed — it is rendered as `candidate.slice(line.length)`, so a fuzzy match (scattered characters) would produce a suffix unrelated to the line. v1.0.2 removed fuzzy candidates from this path entirely. The suggestion engine (`src/renderer/src/autocomplete.ts`) ranks candidates from: | Source | Ranking signal | Example | |---|---|---| | **Command history** | frecency: recency bucket + `log2(count)` + same-working-directory bonus + non-zero-exit penalty | `docker compose up -d` | | **Current session** | anything you ran in this pane outranks the history file it is not in yet | `npm run typecheck` | | **Project context** | `package.json` scripts across `npm` / `pnpm` / `yarn` / `bun`, `Makefile` targets | `pnpm dev`, `make release` | | **Path arguments** | directory and file names for the last argument of `cd`, `ls`, `cat`, `code`, `rm`, `node`, ... (`cd`, `pushd`, `mkdir` get directories only) | `cd src/renderer/` | | **Built-in dictionary** | fallback for an empty history | `git status`, `code .` | Exact-case candidates beat case-folded ones, and longer completions are penalized, so the safest completion wins. Project context is resolved in the main process (`completion:context`), cached per directory by mtime, and refreshed on a 5 second TTL plus after every command — so a file you just created is completable immediately, with no disk access on the keystroke path. > **Implementation note.** The ghost text is a positioned DOM overlay, never > written into the terminal buffer — writing it would collide with the shell's own > echo and corrupt the line. Its letter spacing is corrected at render time so it > lands exactly on the terminal's character grid. > > **`Tab` never leaves the terminal.** xterm.js only calls `preventDefault()` for > keys it handles itself; when the suggestion layer swallows `Tab`, that step is > skipped and the browser would move DOM focus onto a title bar or status bar > button. Every path that swallows `Tab` calls `preventDefault()` explicitly, and > a capture-phase guard blocks focus traversal outside real text inputs (v1.0.2). --- ## 2. True Multi-Window `Ctrl+Shift+N` · Shipped v1.0.1 **Problem.** In 1.0.0 a second launch of Bitig only focused the existing window, and — worse — closing the last window left an invisible process alive, still holding PTY sessions and a global hotkey. **Solution.** Launching the executable again opens a **new, fully independent window**, exactly like Windows Terminal; `Ctrl+Shift+N` does the same from inside the app. Each window owns its own tabs and PTY sessions: closing one window kills only its shells, and closing the last one terminates the process completely. Settings, themes, history and snippets stay under a single owner (one process, many windows), so there is never more than one writer for `settings.json`. > **Root cause of the 1.0.0 ghost process.** The Quake HUD window was created > eagerly at startup. Because a (hidden) window was always open, Electron's > `window-all-closed` event never fired. The HUD is now created lazily on first > use, and quitting is driven by an explicit count of real Bitig windows. --- ## 3. Live Working Directory in Tab Titles Shipped v1.0.1 **Problem.** Tab titles came only from OSC 0/2, which PowerShell and cmd emit once at startup — with the *full path of the executable*. The result: a tab labelled `system32` forever, no matter how many times you `cd`. **Solution.** Bitig injects a prompt hook into the shell it spawns (`src/main/pty/shellIntegration.ts`) so every prompt emits the current directory as an OSC 7 sequence: | Shell | Injection | |---|---| | PowerShell / pwsh | `-NoExit -EncodedCommand` wrapping the existing `prompt` function | | cmd | `/K prompt $E]7;file:///$P$E\$P$G` | | bash / Git Bash | `PROMPT_COMMAND` prefixed with a `printf` of `$PWD` | The renderer listens for OSC 7 (and OSC 9;9 for ConEmu compatibility) and retitles the tab to the folder name the moment it changes — `cd Desktop` renames the tab to **Desktop** instantly. Your own `prompt` function or `PROMPT_COMMAND` is wrapped, never replaced. For shells that cannot be instrumented (WSL, exotic setups) a fallback tracker (`src/renderer/src/cwdTracker.ts`) infers the directory from the prompt line itself. Manually renamed tabs (double-click) are always left alone, and the full path is available as the tab's tooltip. --- ## 4. Bitig Betik: Parametric Runbook Manager `Ctrl+Shift+B` · Shipped v0.8.0 **Problem.** Developers run long, parameter-heavy commands every day: ``` docker run -d -p 8080:80 -v C:\project:/app --name api-dev node:20 ffmpeg -i input.mp4 -c:v libx264 -crf 23 -c:a aac output.mp4 kubectl port-forward svc/my-service 8080:80 -n staging ``` Memorizing them, or pasting them out of a notes app and hand-editing quotes and ports, is both slow and error-prone. **Solution.** `Ctrl+Shift+B` opens a searchable template picker. Bitig turns the `{{variable}}` placeholders into a dynamic form; filling it in and pressing `Enter` types the compiled command straight into the active terminal. A live preview shows exactly what will run before it runs.
Template schema (%APPDATA%/Bitig/snippets.json) ```jsonc { "snippets": [ { "id": "docker-run-volume", "name": "Start Docker Container (Port & Volume)", "description": "Runs a container with port forwarding and a bind mount", "category": "Docker", "command": "docker run -d -p {{host_port}}:{{container_port}} -v \"{{host_dir}}\":{{container_dir}} --name {{name}} {{image}}", "variables": { "host_port": { "label": "Host Port", "default": "3000" }, "container_port": { "label": "Container Port", "default": "3000" }, "host_dir": { "label": "Local Directory","default": "%CD%" }, "container_dir": { "label": "Target Directory","default": "/app" }, "name": { "label": "Container Name", "default": "app-dev" }, "image": { "label": "Docker Image", "default": "node:20-alpine" } } } ] } ```
--- ## 5. Live Port & Service Sniffer Shipped v0.9.0 **Problem.** After `npm run dev`, `cargo run` or `docker compose up`, finding the port the app came up on means scanning a wall of scrolling logs. **Solution.** `src/renderer/src/portSniffer.ts` analyses the PTY output stream: - **ANSI escape sequences are stripped** before scanning, so color codes never break the regex. - A **per-pane rolling buffer** (512 characters) keeps URLs that are split across PTY chunks from being lost. - The moment a port opens, a pulsing, clickable badge appears in the tab title and status bar. One click opens `http://localhost:PORT` in the default browser. - Millisecond values such as `ready in 153 ms` are never mistaken for ports. --- ## 6. Smart Links & IDE Integration Shipped v0.9.0 **Problem.** When a build error prints `at src/renderer/src/main.ts:42:15`, a standard terminal shows it as flat text. Hunting the file down in your editor and jumping to the line breaks your flow. **Solution.** `src/renderer/src/smartLinks.ts` registers a custom link provider with xterm.js. It recognizes stack-trace patterns (`src/main.ts:42:15`, `C:\Users\...\file.py:102`) and `Ctrl + Left click` opens the file at the exact line and column: ``` vscode://file/c:/Users/samet/Desktop/Bitig/src/renderer/src/main.ts:42:15 ``` The handoff goes through the `cockpit:open-file` channel via `shell.openExternal`. --- ## 7. Secret Shield Shipped v0.9.0 **Problem.** On a stream or in a screen share, `cat .env` or `echo $STRIPE_KEY` exposes live credentials. Worse, those commands are written to command history in plain text and stay there. **Solution.** `src/renderer/src/secretShield.ts` and `src/main/history/historyStore.ts` work together. | Detected pattern | Example | |---|---| | JWT token | `eyJhbGciOi...` | | AWS access key | `AKIA[0-9A-Z]{16}` | | GitHub PAT | `ghp_[0-9a-zA-Z]{36}` | | OpenAI / Anthropic key | `sk-...`, `sk-ant-...` | | Private key block | `-----BEGIN RSA PRIVATE KEY-----` | Values are masked to `ghp_************` before the command is persisted, so searching your history never carries a leak risk. --- ## 8. Bitig Bilge: Local, Privacy-First AI Assistant `Ctrl+I` · Shipped v0.9.8 **Problem.** Copying an unfamiliar error into a browser search breaks your flow, and pasting company code or logs into a cloud AI service violates most data security policies. **Solution.** - **100% local, or BYOK.** With Ollama (`http://localhost:11434`) nothing ever leaves the machine; alternatively bring your own OpenAI, Anthropic, Gemini or DeepSeek key. Bitig never forwards data to servers of its own, because there are none. - **Natural language to command.** Press `Ctrl+I`, type *"find and delete all .log files larger than 100MB"*, and get a command appropriate for the active shell. `Enter` runs it, `Tab` sends it to the terminal for editing. - **Smart error explainer.** The last command and the relevant error lines are analysed into an actionable fix. - **Key handling.** API keys live only in `%APPDATA%/Bitig/settings.json`, are entered masked in the settings panel, and can be verified with a live connection test. --- ## 9. Quake / Dropdown HUD `Win+~` or `Ctrl+~` · Shipped v0.9.5 **Problem.** Digging a terminal out from behind a dozen windows for one quick Git command is pure overhead. **Solution.** On the hotkey, Bitig drops down from the top edge of the screen as a translucent, always-on-top HUD. It is controlled at runtime through the `quake:toggle` and `quake:set-hotkey` channels and auto-hides on blur. Since v1.0.1 the HUD window is created lazily on first use, so it never keeps the app alive in the background. --- ## 10. Broadcast Input `Alt+Shift+I` · Shipped v0.9.5 **Problem.** With four split panes connected to four servers, typing `git pull` or `systemctl restart` into each one by hand is tedious and error-prone. **Solution.** With broadcast mode on, every keystroke in the focused pane is sent to every PTY session in the tab simultaneously. A pulsing red frame around the window and a banner dropping from the top edge make the mode impossible to miss. Turning it off restores independent panes. --- ## 11. Sandboxed Plugin System Shipped v1.0.0 **Problem.** Plugin support is usually either absent or grants plugins full Node access, turning every plugin into a potential security hole. **Solution.** A plugin is a `plugin.json` manifest plus an entry script under `%APPDATA%/Bitig/plugins//`. The script runs in an isolated Node `vm` context with no `require`, `process` or `fs`. The only reachable surface is the explicitly allowlisted `bitig` object: | API | Purpose | |---|---| | `bitig.ui.setStatusBarWidget` | Adds a live widget to the status bar | | `bitig.actions.register` | Adds an action to the command palette and keybinding system | | `bitig.getGitBranch` | Returns the Git branch of the active directory | | `bitig.getSystemMemory` | Returns system memory usage | | `bitig.openUrl` | Opens a URL in the default browser | | `bitig.setInterval` | A timer that is cleaned up automatically when the plugin unloads | Three reference plugins ship in the box: `git-status` (current branch), `system-monitor` (live RAM usage) and `quick-web-search` (universal actions for Google and Stack Overflow searches). --- ## Architectural Principles Every feature added to Bitig has to obey these four rules. 1. **Zero latency.** Terminal text flows directly between the PTY and xterm.js. Additional analysis (port sniffer, secret shield, telemetry, suggestions) runs asynchronously and may never add perceptible input lag. 2. **Keyboard first.** Every action is bound to an `actionId`, is rebindable, and is reachable from the Command Palette (`Ctrl+Shift+P`). 3. **Data sovereignty.** User data — snippets, history, settings, API keys — stays on the user's own machine as plain JSON. 4. **Isolated plugin architecture.** Plugins run inside a Node `vm` with access only to allowlisted Bitig APIs; they can never reach the operating system directly. ---
Bitig · Old Turkic for "writing, script, written text".