initial commit of jail and vibe
4 files changed,  +294, -0
A flake.lock
+61, -0
 1@@ -0,0 +1,61 @@
 2+{
 3+  "nodes": {
 4+    "flake-utils": {
 5+      "inputs": {
 6+        "systems": "systems"
 7+      },
 8+      "locked": {
 9+        "lastModified": 1731533236,
10+        "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
11+        "owner": "numtide",
12+        "repo": "flake-utils",
13+        "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
14+        "type": "github"
15+      },
16+      "original": {
17+        "owner": "numtide",
18+        "repo": "flake-utils",
19+        "type": "github"
20+      }
21+    },
22+    "nixpkgs": {
23+      "locked": {
24+        "lastModified": 1777268161,
25+        "narHash": "sha256-bxrdOn8SCOv8tN4JbTF/TXq7kjo9ag4M+C8yzzIRYbE=",
26+        "owner": "NixOS",
27+        "repo": "nixpkgs",
28+        "rev": "1c3fe55ad329cbcb28471bb30f05c9827f724c76",
29+        "type": "github"
30+      },
31+      "original": {
32+        "owner": "NixOS",
33+        "ref": "nixos-unstable",
34+        "repo": "nixpkgs",
35+        "type": "github"
36+      }
37+    },
38+    "root": {
39+      "inputs": {
40+        "flake-utils": "flake-utils",
41+        "nixpkgs": "nixpkgs"
42+      }
43+    },
44+    "systems": {
45+      "locked": {
46+        "lastModified": 1681028828,
47+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
48+        "owner": "nix-systems",
49+        "repo": "default",
50+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
51+        "type": "github"
52+      },
53+      "original": {
54+        "owner": "nix-systems",
55+        "repo": "default",
56+        "type": "github"
57+      }
58+    }
59+  },
60+  "root": "root",
61+  "version": 7
62+}
A flake.nix
+107, -0
  1@@ -0,0 +1,107 @@
  2+{
  3+  description = "Vibe - Sandboxed OpenCode runner with firejail isolation";
  4+
  5+  inputs = {
  6+    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  7+    flake-utils.url = "github:numtide/flake-utils";
  8+  };
  9+
 10+  outputs = { self, nixpkgs, flake-utils }:
 11+    flake-utils.lib.eachDefaultSystem (system:
 12+      let
 13+        pkgs = nixpkgs.legacyPackages.${system};
 14+        
 15+        # jail package - wraps jail.sh with firejail dependency
 16+        jail = pkgs.stdenvNoCC.mkDerivation {
 17+          pname = "jail";
 18+          version = "0.1.0";
 19+          
 20+          src = ./.;
 21+          
 22+          nativeBuildInputs = [ pkgs.makeWrapper ];
 23+          
 24+          buildInputs = [ pkgs.firejail ];
 25+          
 26+          installPhase = ''
 27+            runHook preInstall
 28+            
 29+            mkdir -p $out/bin
 30+            cp jail.sh $out/bin/jail
 31+            chmod +x $out/bin/jail
 32+            
 33+            # Wrap jail to ensure firejail is in PATH
 34+            wrapProgram $out/bin/jail \
 35+              --prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.firejail pkgs.git pkgs.coreutils pkgs.which ]}
 36+            
 37+            runHook postInstall
 38+          '';
 39+          
 40+          meta = with pkgs.lib; {
 41+            description = "Run OpenCode in a sandboxed firejail environment";
 42+            homepage = "https://kilimanjaro.io/vibe";
 43+            license = licenses.mit;
 44+            platforms = platforms.linux;
 45+          };
 46+        };
 47+        
 48+        # vibe package - wraps jail opencode
 49+        vibe = pkgs.stdenvNoCC.mkDerivation {
 50+          pname = "vibe";
 51+          version = "0.1.0";
 52+          
 53+          src = ./.;
 54+          
 55+          nativeBuildInputs = [ pkgs.makeWrapper ];
 56+          
 57+          buildInputs = [ jail pkgs.opencode ];
 58+          
 59+          installPhase = ''
 60+            runHook preInstall
 61+            
 62+            mkdir -p $out/bin
 63+            cp vibe.sh $out/bin/vibe
 64+            chmod +x $out/bin/vibe
 65+            
 66+            # Wrap vibe to ensure jail and opencode are in PATH
 67+            wrapProgram $out/bin/vibe \
 68+              --prefix PATH : ${pkgs.lib.makeBinPath [ jail pkgs.opencode ]}
 69+            
 70+            runHook postInstall
 71+          '';
 72+          
 73+          meta = with pkgs.lib; {
 74+            description = "Run OpenCode in a sandboxed environment with optional session token";
 75+            homepage = "https://kilimanjaro.io/vibe";
 76+            license = licenses.mit;
 77+            platforms = platforms.linux;
 78+          };
 79+        };
 80+        
 81+      in {
 82+        packages = {
 83+          inherit jail vibe;
 84+          default = vibe;
 85+        };
 86+        
 87+        devShells.default = pkgs.mkShell {
 88+          name = "vibe-dev";
 89+          
 90+          buildInputs = with pkgs; [
 91+            opencode
 92+            firejail
 93+            git
 94+            bash
 95+            jq
 96+            curl
 97+            which
 98+          ];
 99+          
100+          shellHook = ''
101+            echo "Vibe development shell"
102+            echo "Available tools: opencode, firejail, git, jq, curl"
103+            echo "Run 'jail' to start the sandbox wrapper"
104+            echo "Run 'vibe' to start OpenCode in sandbox (optional: vibe <token>)"
105+          '';
106+        };
107+      });
108+}
A jail.sh
+101, -0
  1@@ -0,0 +1,101 @@
  2+#!/usr/bin/env bash
  3+
  4+# opencode-sandbox - Run OpenCode in a sandboxed firejail environment
  5+# This script runs in firejail with filesystem isolation
  6+# while maintaining access to current directory and configuration
  7+
  8+set -euo pipefail
  9+
 10+# Enable OpenCode experimental support for oxfmt when listed as a package dependency
 11+export OPENCODE_EXPERIMENTAL_OXFMT="true"
 12+export EDITOR="echo"
 13+
 14+# Capture current environment
 15+CURRENT_DIR="$(pwd)"
 16+ROOT="$(git rev-parse --show-toplevel)"
 17+
 18+# For NixOS: resolve to actual Nix store paths (not symlinks)
 19+OPENCODE_PATH="$(readlink -f "$(which opencode)")"
 20+echo "Using $OPENCODE_PATH"
 21+
 22+# Build firejail command arguments
 23+FIREJAIL_ARGS=(
 24+    # Use noprofile to avoid default restrictions that might block large directories
 25+    --noprofile
 26+
 27+    # Security restrictions
 28+    --private-tmp              # Private /tmp directory
 29+    --noroot                   # Disable su/sudo inside sandbox
 30+    --caps.drop=all           # Drop all capabilities
 31+    --nonewprivs              # Prevent privilege escalation
 32+    --nogroups                # Don't inherit supplementary groups
 33+
 34+    # Filesystem access - whitelist specific paths only
 35+    --whitelist="$ROOT"
 36+    --read-only="$ROOT"
 37+    --whitelist="$ROOT/.git"  # if started in a subdirectory of a git project
 38+    --read-write="$ROOT/.git" # => needs access to .git and .jj for bug and commits
 39+    --whitelist="$ROOT/.jj"
 40+    --read-write="$ROOT/.jj"
 41+    --whitelist="$CURRENT_DIR"        # Allow access to current directory
 42+    --read-write="$CURRENT_DIR"       # Make current directory writable
 43+    --whitelist="/nix/store"       # Make Nix tools available in dev shell
 44+    --read-only="/nix/store"
 45+    --whitelist="$HOME/.bashrc"
 46+    --read-write="$HOME/.bashrc" # tool call aliases
 47+    --whitelist="$HOME/.agents"
 48+    --read-write="$HOME/.agents" # skills
 49+    --whitelist="$HOME/.ssh" # to troubleshoot Nix depoyment
 50+    --read-only="$HOME/.ssh"
 51+)
 52+
 53+# Blacklist specific tools resident in /usr/bin environment that you absolutely don't want
 54+# OpenCode using. This augments any restrictions you put in your OpenCode permissions.
 55+BLACKLIST=(
 56+    npm
 57+    /usr/bin/npm
 58+    yarn
 59+    java
 60+    perl
 61+)
 62+for bl in "${BLACKLIST[@]}"; do
 63+    FIREJAIL_ARGS+=(--blacklist="$(which "$bl")")
 64+done
 65+
 66+# Add configuration access if files/directories exist
 67+if [ -d "$HOME/.config/opencode" ]; then
 68+    FIREJAIL_ARGS+=(--whitelist="$HOME/.config/opencode")
 69+    FIREJAIL_ARGS+=(--read-write="$HOME/.config/opencode")
 70+
 71+    # auth creds and logs
 72+    FIREJAIL_ARGS+=(--whitelist="$HOME/.local/share/opencode")
 73+    FIREJAIL_ARGS+=(--read-write="$HOME/.local/share/opencode")
 74+fi
 75+if [ -d "$HOME/.config/jj" ]; then
 76+    FIREJAIL_ARGS+=(--whitelist="$HOME/.config/jj")
 77+    FIREJAIL_ARGS+=(--read-only="$HOME/.config/jj")
 78+fi
 79+
 80+# Add PNPM store
 81+if [ -d "$HOME/.local/share/pnpm" ]; then
 82+    FIREJAIL_ARGS+=(--whitelist="$HOME/.config/pnpm")
 83+    FIREJAIL_ARGS+=(--read-only="$HOME/.config/pnpm")
 84+    FIREJAIL_ARGS+=(--whitelist="$HOME/.local/share/pnpm")
 85+    FIREJAIL_ARGS+=(--read-write="$HOME/.local/share/pnpm")
 86+    FIREJAIL_ARGS+=(--whitelist="$HOME/.cache/node") # corepack installs
 87+    FIREJAIL_ARGS+=(--read-only="$HOME/.cache/node")
 88+
 89+fi
 90+
 91+# add playwright browsers
 92+if [ -d "$HOME/.cache/ms-playwright" ]; then
 93+    FIREJAIL_ARGS+=(--whitelist="$HOME/.cache/ms-playwright")
 94+    FIREJAIL_ARGS+=(--read-write="$HOME/.cache/ms-playwright")
 95+fi
 96+
 97+# Network access (allow by default, can be restricted with --net=none)
 98+# FIREJAIL_ARGS+=(--net=none)  # Uncomment to disable network access
 99+
100+echo "Starting in firejail sandbox..."
101+exec firejail "${FIREJAIL_ARGS[@]}" "$@"
102+
A vibe.sh
+25, -0
 1@@ -0,0 +1,25 @@
 2+#!/usr/bin/env bash
 3+
 4+# vibe - Run OpenCode in a sandboxed firejail environment
 5+# Usage: vibe [<token>] or vibe -s <token>
 6+
 7+set -euo pipefail
 8+
 9+# Handle different argument patterns:
10+# - vibe (no args) -> jail opencode
11+# - vibe <token> -> jail opencode -s <token>
12+# - vibe -s <token> -> jail opencode -s <token>
13+
14+if [ $# -eq 0 ]; then
15+    # No arguments - run opencode without session token
16+    exec jail opencode
17+elif [ "$1" = "-s" ] && [ $# -eq 2 ]; then
18+    # Explicit -s flag with token
19+    exec jail opencode -s "$2"
20+elif [ $# -eq 1 ] && [ "$1" != "-s" ]; then
21+    # Single argument that is not -s, treat as token
22+    exec jail opencode -s "$1"
23+else
24+    echo "Usage: vibe [<token>] or vibe -s <token>" >&2
25+    exit 1
26+fi