GenAI-WorkspaceOne terminal. Any model.

A terminal-first setup for driving hosted frontier models and models on your own hardware through the same workflow. tmux holds the screen, Neovim takes the left, an agent takes the right, and every harness — Claude Code, Cursor, Codex CLI, OpenCode — reads its rules from one shared source of truth.

One command — gw — is the whole entry point. Editing and AI land on one screen, in the directory you're already standing in.

tmux 1:gw 2:zsh 21:34
~/GenAI-Workspace gw
nvim — 70%
~/GenAI-Workspace/ .claude .friday .opencode docs repos .mcp.json → .friday/mcp.json AGENTS.md → .friday/rules.md CLAUDE.md → .friday/rules.md README.md
genai tooling — 30%
claude codeopencodecodex
  • needs input
  • a question is waiting on you
  • working
  • keeps running if you close the terminal
  • completed
  • finished, waiting for review
describe a task

Hand off a task larger than you'd chat through, and it gets sorted into those three states while you keep editing on the left.

how it fits together

A stack, not one app

The thing people call "an AI setup" is four independent layers. Keeping them separate is the whole point: the model and the harness don't know about each other, so you can swap a hosted frontier model for one running on your own machine without changing how you work.

layer 4Tool protocol
Gives the model hands and feet — filesystem, git, web, your own services. MCP over stdio locally, Streamable HTTP for remote. Defined once in .friday/mcp.json.
MCPFastMCP notionpenpot
layer 3Chat UI optional
A browser surface over the same backend. Nice to have, never load-bearing — the terminal is the primary interface.
Open WebUILibreChat AnythingLLM
layer 2Agent / harness the pane on the right
Reads files, runs shell, edits repos, calls tools, loops. This is what gw puts on screen, and what .friday/ configures. Each harness reads instructions from a different path — which is the problem .friday/ solves.
Claude CodeOpenCode Codex CLICursor Gemini CLI
layer 1Inference hosted or your own hardware
Loads the weights and answers. Hosted frontier models for the hard reasoning; a local daemon on :11434 for everything cheap, private, or offline.
ClaudeGPT GeminiOllama llama.cppvLLM
The spine is layers 1, 2 and 4. Layer 3 is a convenience. If you only ever set up an inference endpoint, a harness, and MCP, you have the whole thing.

models

Self-hosted and hosted, same workflow

Neither choice is the right one for every task. Hosted frontier models are still where the hard reasoning happens. Local models are free, private and work on a plane. Because the harness sits above both, choosing is a per-task decision rather than an architecture decision.

☁ hosted frontier
Claude · GPT · Gemini
─────────────────────
+ strongest reasoning
+ large context
+ reliable tool-calling
every token leaves the machine
costs tokens, needs network
⌂ your own hardware
Ollama · llama.cpp · vLLM
─────────────────────
+ free per token
+ context never leaves
+ works fully offline
weaker on long agentic loops
bound by your RAM

Where each one earns its place

taskruns onwhy
multi-file refactor, architecturehosted long loops need tool-calling that holds up
summarise a git difflocal runs constantly; zero cloud tokens
anything under NDA or unreleasedlocal the context never leaves the machine
research, long-context readinghosted context window is the constraint
on a train, no signallocal it's the only one that answers
The pattern worth stealing: a hosted model driving the main loop, with a local model attached as an MCP tool for the cheap, repetitive subtasks. One agent, two tiers of inference, and the expensive one only does the thinking.

One hard rule from the research: use weights released in the last six months. Stalled local agent loops are almost always an old model with poor tool-call adherence, not a broken harness. Full write-up in docs/tooling-research.md.

the workspace

tmux holds it, Neovim edits it, the agent works beside it

Nothing here is a new application. It's tmux, Neovim and an agent CLI arranged so that handing off work never means leaving the screen you're working on.

tmuxthe frame
Owns the session, so work outlives the terminal window. Close the laptop lid, come back, the agent is still going. gw always targets the top-level socket, even when invoked from a shell nested inside Neovim.
Neovim70% — the left pane
Where you actually work. gw in the current directory execs Neovim into the very pane you typed it in, so no window is wasted.
genai tooling30% — the right pane
Claude Code, OpenCode or Codex — whichever harness you're driving, it gets the same slot and the same rules from .friday/. Narrow on purpose: it's a task queue you glance at, not something you stare into.

Three ways in

gw

Current directory. Reuses this tab — agent splits in on the right, Neovim takes over this pane.

gw ~/repos/my-app

Another directory. Opens its own tab, named after the folder, so unrelated workspaces never share a screen.

gw-pick

Don't know the path yet. An fzf popup, bound in tmux, browses directories and hands the one you pick straight to gw.

the idea

.friday — one source of truth

Every harness reads its instructions, MCP config, skills and commands from a different path. Left alone, that means four copies of the same rules drifting apart. .friday/ holds the canonical copy, and .friday/init symlinks it into whatever each tool expects. Edit once, every tool picks it up.

without
  • .claude/ rules, mcp, skills
  • .cursor/ the same rules again
  • .opencode/ and again
  • ~/.codex/ and again

Four copies. Three of them are already wrong.

with .friday
  • .friday/ the only real files
  • CLAUDE.md → .friday/rules.md
  • AGENTS.md → .friday/rules.md
  • .cursorrules → .friday/rules.md
  • .mcp.json → .friday/mcp.json

One file. Every tool reads it.

What's inside

  • .friday/
  • ├── init bootstrap — creates every symlink below
  • ├── cleanup removes what init created
  • ├── rules.md source of truth for instructions
  • ├── mcp.json MCP servers, shared by every harness
  • ├── settings.json canonical settings, Claude Code schema
  • ├── skills/ curated surface → .claude/skills
  • ├── commands/ slash commands → .claude/commands
  • └── vendor/ upstream submodules, unmodified

Who gets what

toollinks created
Claude Code CLAUDE.md, .mcp.json, .claude/skills, .claude/commands, .claude/settings.json
Cursor.cursorrules
Codex CLI / OpenCodeAGENTS.md

Idempotent — re-run any time to repair drifted links. A real file sitting at a link path is backed up to <file>.bak first. The links themselves are per-machine setup, not project source, so they're gitignored.

Vendoring rule: third-party skills come in as git submodules under .friday/vendor/, with the individual skill directory symlinked into .friday/skills/. vendor/ stays an untouched upstream clone; skills/ is the curated surface. Locally authored skills and commands are prefixed friday- so git tracks them and leaves the generated symlinks alone.

extend

Skills and commands, in plain Markdown

Both are just directories of Markdown. Add a file, and it shows up in the harness — no plugin system, no build step, and everything is diffable.

a skill
.friday/skills/<name>/SKILL.md
  • friday-paper markdown → styled PDF
  • friday-research structured research doc
  • friday-mermaid-diagrams diagram reference
a command
.friday/commands/<name>.md
  • /friday-install vendor a third-party skill
  • /friday-research research a decision
  • /friday-snippet one-pager → Notion

Skills work across harnesses. Slash commands are Claude Code-only today — the other tools each use a different format, and no shared standard exists yet.

setup

Three commands

1 · Clone it

git clone git@github.com:mrsauravsahu/genai-workspace.git

2 · Wire up your tools

bash .friday/init

Asks which harnesses you use and symlinks accordingly. Point it at a cloned project to wire that repo back to the same shared config: bash .friday/init repos/<name>

3 · Open the workspace

gw
Want .friday/ everywhere? Keep the canonical copy at ~/.friday and symlink it into each project with ln -s ~/.friday .friday. Harnesses resolve the path relative to the working directory, so a project can't point at your home directory on its own. Projects needing their own rules keep a real local .friday/ instead.

Read the source on GitHub · the research behind these choices · the design language for this page