Skip to content

Repository files navigation

Pixet

Pixet

A pixel-art Claude Code desktop client. Tauri-based fork of winfunc/opcode — same underlying engine, completely different vibe, plus a stack of upstream-bug fixes you can feel.

License: AGPL v3 Tauri 2 React 18 Rust Bun Vite macOS version

Features · Screenshots · Pixet vs opcode · Getting started · Repo layout · Acknowledgments


⚠️ Pixet is a community fork. It is not affiliated with or endorsed by the upstream opcode project or its authors. For the original, unmodified client, see winfunc/opcode. All upstream copyrights and the AGPL-3.0 license are preserved — see NOTICE and LICENSE.


Screenshots

Pixet main window
Main chat — pixel-art rail, mascot, sessions
File tree + viewer
In-rail file tree + modal code viewer
Running shells widget
Running shells across every chat tab, with Stop
Agents view
Agents & MCP — opcode features, pixel-styled

Pixet vs opcode (tl;dr)

opcode (upstream) Pixet
Visual style Modern smooth UI Pixel-art overlay, Pixelify Sans, 12-color palette
Icon set lucide-react pixelarticons (+ lucide fallback)
Chat sidebar Full-page navigation between sessions Dense in-place rail: mascot, sessions, file tree, running shells, stats
Session rename Filesystem-only Inline rename with localStorage persistence
File viewer Open external Modal overlay inside the rail
Running processes Per-session Stop only Cross-tab Running panel with per-row Stop
Streaming on macOS/WebKit Drops events silently (#71, #26) Disk watchdog merges JSONL history every 4 s — zero extra API tokens
Multi-tab streaming Generic events leak between tabs Session-scoped listeners; tabs stay isolated
Prompt queue Drops sends after the first Hoisted dispatch, queue clears reliably
Bash kill Orphans descendants on cancel pgrep -P sweep before killing claude
External links Can hijack the Tauri window Routed through plugin-opener
Analytics Opt-in default, can re-enable silently Opt-out default, never silently re-enables
Project paths Encoded folder name only (#465) Full JSONL scan + sidecar resolution
Prompt input Runtime require() breaks in webview (#462) Static ESM import

What Pixet adds

🎨 Visual layer

  • Global pixel-art overlay (src/styles/pixet.css) — stippled dot patterns, Pixelify Sans typography, step-end animations across every animated surface.
  • Twelve-color palette anchored on a single orange accent. All hardcoded purple / violet / cyan / rose Tailwind classes were removed throughout the app — loaders, MCP widget, gradients, picker buttons.
  • Pixel-art mascot diorama (PixetMascot.tsx) — a creature at a CRT workstation, rendered as inline SVG, with hanging plant, bookshelf, lamp, steaming mug, and a mouse darting across the floor.
  • Custom Pixet wordmark + platform icons regenerated from the original mascot SVG for every Tauri target (.icns, .ico, PNG set).
  • Defensive Radix overlay (src/styles/pixet-radix.css) — keeps portaled content (popovers, dropdowns, tooltips) on-style.
  • Icon shim (src/lib/icons.ts) — re-exports pixelarticons where a pixel equivalent exists, falls back to lucide-react otherwise. See FALLBACK_ICONS.md.
  • Readable model + thinking pickers — full names instead of truncated buttons, larger hit targets.

🪟 Chat-surface rail

A dense sidebar that lives inside every chat session:

  • Mascot at the top.
  • Project sessions list (PixetProjectSessions.tsx) — inline rename (localStorage-backed via sessionNames.ts), one-click in-place session switching, no full-page navigation.
  • File tree of the active project (PixetFileTree.tsx) — lazy-loaded, recursive, virtualized where it counts.
  • Modal file viewer (PixetFileViewer.tsx) — click any file in the tree, get a code-styled overlay without leaving the chat. Backed by the new read_file_text Tauri command.
  • Running-shells widget (PixetRunningShells.tsx) — lists every Claude / Bash process the Rust ProcessRegistry has tracked as alive, across all chat tabs. Per-row Stop uses the same cancelClaudeExecution path as the main Stop, plus a pgrep -P sweep that picks up orphaned bash descendants. Hidden when nothing is running.
  • Usage stats (PixetSidebarStats.tsx) — project / session counts at a glance.

🔧 Reliability (upstream-bug workarounds)

  • Streaming-output watchdog — works around the Tauri-v2 event-broadcast IPC issue (opcode #71, #26) where the live event channel silently drops messages on macOS / WebKit. Pixet polls the on-disk session JSONL every 4 s (1.5 s for the first poll) and merges (not replaces) new entries, eliminating the vanish-and-reappear flicker. Loading state clears as soon as the result JSONL row from the Claude CLI is seen. Pure local disk reads, zero extra Claude API tokens.
  • Debounced loading indicatorvisibleIsLoading absorbs micro-flicker between events and disk polls.
  • Stick-to-bottom auto-scroll with a programmatic-scroll suppression window — the disk watchdog can no longer flip stickToBottom mid-animation when it injects merged history.
  • Prompt queue unblock — hoisted the API dispatch out of the listener-init branch so prompts after the first don't drop silently. Removed the isLoading gate on send/cancel so long-running bash no longer traps the queue.
  • Bash descendant capture — before killing a Claude turn, Pixet runs pgrep -P and tracks orphaned bash children so they end up in the Running panel and can be stopped explicitly.
  • Multi-tab event isolation — generic Tauri events without a session id no longer leak between tabs. Each chat scopes its listeners by session id.
  • Pre-registered session listeners on resume — closes the race where messages streamed before the listener was attached.
  • Project-path resolution (opcode #465) — resolves a project's real on-disk path from a full JSONL scan plus the sidecar file, instead of guessing from the encoded folder name. Fixes paths containing hyphens.
  • Prompt-input ESM fix (opcode #462) — replaced a runtime require() with a static ESM import so the prompt input works in the Tauri webview.
  • External link hardening — printed http://localhost:… URLs from the CLI are routed through plugin-opener instead of being followed inline, so a stray URL can't hijack the Tauri window.

🔒 Privacy

  • Analytics default to opt-out and never silently re-enable. If you turn it off, it stays off across upgrades.

⚙️ Backend & build

  • read_file_text Tauri command (src-tauri/src/commands/claude.rs) used by the in-rail file viewer.
  • pixet-web binary — separate Cargo bin for the optional web-server mode (src-tauri/src/web_main.rs).
  • justfile rewrite (bun + Tauri CLI) for repeatable local dev — just dev, just build, just web.
  • @tauri-apps/api aligned to match the Rust tauri minor (2.11 / 2.7 against 2.8 crates).
  • default-run = "pixet" so tauri dev doesn't ask which binary to run.
  • Default window bumped to 1440 × 900, with macOSPrivateApi, transparent decorations, and centered placement.

Smoke-tested platforms

Platform Status Notes
macOS · Apple Silicon · Darwin 25.x · WebKit ✅ daily-driven Tauri's broadcast event IPC is degraded here — the streaming watchdog is what keeps chat usable.
Linux / Windows inherits upstream Pixet hasn't been verified on these targets. PRs welcome.

Getting started

Prerequisites

  • Rust toolchain (stable)
  • Node.js + either bun or npm
  • Tauri prerequisites for your OS — Tauri prerequisites guide
  • Claude Code CLI installed and on PATH

Install + run

git clone <this-repo>
cd pixet
bun install          # or: npm install
bun run build        # first build — populates dist/
bun run tauri dev    # spawns the native window

bun run tauri dev compiles the Rust side (a few minutes on a cold cache) and then opens the Tauri window. The Vite dev server runs in the same process.

If bun isn't installed: brew install oven-sh/bun/bun on macOS, or use the upstream's npm scripts.

Just recipes (justfile)

just dev             # tauri dev
just build           # production build (dmg via build:dmg)
just web             # run the pixet-web binary

Type + Rust check before commit

bun run check        # tsc --noEmit && cargo check

Repository layout

The parts Pixet added or changed:

src/
  styles/
    pixet.css                  # global pixel-art overlay
    pixet-radix.css            # defensive overrides for Radix portal content
  components/
    PixetMascot.tsx            # the diorama SVG
    PixetLogo.tsx              # wordmark
    PixetSidebarStats.tsx      # usage / project counts in the rail
    PixetProjectSessions.tsx   # session list with rename + switch
    PixetFileTree.tsx          # lazy-loaded recursive file tree
    PixetFileViewer.tsx        # modal overlay for file contents
    PixetRunningShells.tsx     # cross-tab running-process widget + Stop
    ClaudeCodeSession.tsx      # rebuilt streaming/queue/auto-scroll
    claude-code-session/
      useClaudeMessages.ts     # merge-not-replace disk-watchdog hook
  lib/
    icons.ts                   # pixelarticons ⇄ lucide-react shim
    sessionNames.ts            # localStorage rename store + hook
    analytics/consent.ts       # opt-out-by-default consent gate
    api.ts                     # + listRunningClaudeSessions, killTrackedSubprocess, readFileText
  main.tsx                     # plugin-opener link routing, palette boot

src-tauri/
  src/commands/claude.rs       # + read_file_text, watchdog diagnostics, pgrep-P sweep
  src/main.rs                  # default-run = "pixet", registry wiring, window size
  src/web_main.rs              # pixet-web binary entry

NOTICE                         # upstream attribution + summary of changes
FALLBACK_ICONS.md              # icons that stayed on lucide
CONTRIBUTING.md                # contribution guidelines
docs/screenshots/              # README screenshot drop-in directory

License

Pixet inherits the upstream's GNU Affero General Public License v3.0. All Pixet modifications are released under the same license. See NOTICE for the full attribution + change summary.


Acknowledgments

  • opcode by mufeedvh, 123vviekr, and contributors — the parent project. Pixet is a thin reskin and bug-fix layer on top of their work; none of the pixel-art polish would matter without the substantial backend and chat-session engineering they built.
  • pixelarticons by halfmage — the icon set that gives the icon shim real pixel-art icons.
  • Pixelify Sans (Google Fonts) — the pixel typeface used throughout. Bundled locally in src/assets/fonts/pixelify-sans/.
  • Tauri, React, Vite, Bun — the platform underneath.

Made with pixels. Powered by Claude.

About

No description, website, or topics provided.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages