1
0
mirror of https://github.com/osmarks/random-stuff synced 2026-04-15 13:01:23 +00:00

dot new files

This commit is contained in:
osmarks
2026-04-09 17:26:03 +01:00
parent afa77d3004
commit 1bec99de86
7 changed files with 224 additions and 8 deletions

View File

@@ -4,10 +4,32 @@ if status is-interactive
end
if status is-login
and status is-interactive
# To add a key, set -Ua SSH_KEYS_TO_AUTOLOAD keypath
# To remove a key, set -U --erase SSH_KEYS_TO_AUTOLOAD[index_of_key]
# keychain --eval $SSH_KEYS_TO_AUTOLOAD 2> /dev/null | source
# disabled for performance reasons
#keychain --eval $SSH_KEYS_TO_AUTOLOAD 2> /dev/null | source
end
function __project_jail_chpwd --on-variable PWD
if set -q NORECURSE
set -e NORECURSE
return
end
if set -q IN_PROJECT_JAIL
return
end
if test -x ~/.local/bin/project-jail
if ~/.local/bin/project-jail
set -l back "$dirprev[1]"
test -n "$back"; or set back "$HOME"
set -g NORECURSE
cd "$back"
end
end
end
# Also check once at shell startup.
if not set -q IN_PROJECT_JAIL
if test -x ~/.local/bin/project-jail
~/.local/bin/project-jail
end
end
#if status is-interactive
#
#end

View File

@@ -38,7 +38,14 @@ packages = [
"bemenu-wayland",
"pavucontrol",
"swaylock",
"jq"
"jq",
"fish",
"zoxide",
"atuin",
"arc-icon-theme",
"breeze-icons",
"arc-gtk-theme",
"magic-wormhole"
]
subprocess.run(["sudo", "pacman", "-S", *packages])

175
dotfiles/project_jail.py Executable file
View File

@@ -0,0 +1,175 @@
#!/usr/bin/env python3
# Automatically put shell sessions in bwrap when navigating to a project folder.
# Supply chain attack mitigation.
# Written by GPT-5.4 and adapted slightly by hand.
from __future__ import annotations
import json
import os
import shutil
import subprocess
import sys
from pathlib import Path
CONFIG_PATH = Path.home() / ".config" / "jails.json"
MARKER_ENV = "IN_PROJECT_JAIL"
PROFILES = {
"rust": [
("rw", "~/.cargo/bin"),
("rw", "~/.cargo/git"),
("ro", "~/.gitconfig")
],
"node": [
("rw", "~/.npm"),
("rw", "~/.cache/node-gyp"),
("ro", "~/.gitconfig")
],
"python": []
}
def load_config() -> dict[str, dict]:
with CONFIG_PATH.open("r", encoding="utf-8") as f:
res = json.load(f)
for path, entry in res.items():
entry["path"] = path
return res
def resolve_path(p: str) -> Path:
return Path(os.path.expandvars(os.path.expanduser(p))).resolve()
def find_matching_entry(cwd: Path, config: dict[str, dict]) -> dict | None:
best: tuple[int, dict] | None = None
for path, entry in config.items():
try:
root = resolve_path(str(path))
cwd.relative_to(root)
except Exception:
continue
score = len(root.parts)
if best is None or score > best[0]:
best = (score, entry)
return best[1] if best else None
def ensure_dir(path: Path) -> None:
path.mkdir(parents=True, exist_ok=True)
def build_bwrap_command(entry: dict, cwd: Path) -> list[str]:
bwrap = shutil.which("bwrap")
if not bwrap:
print("project-jail: bwrap not found in PATH", file=sys.stderr)
sys.exit(1)
shell = os.environ.get("SHELL", "/usr/bin/fish")
home = Path.home()
project_root = resolve_path(str(entry["path"]))
state_dir = Path(os.environ.get("XDG_STATE_HOME", home / ".local" / "state")) / "project-jails"
sandbox_name = entry.get("name") or project_root.name
sandbox_home = state_dir / sandbox_name / "home"
sandbox_tmp = state_dir / sandbox_name / "tmp"
ensure_dir(sandbox_home)
ensure_dir(sandbox_tmp)
ro_binds = [
"/usr",
"/bin",
"/sbin",
"/lib",
"/lib64",
"/opt",
"/etc",
]
dev_binds = [
"/dev/dri", # GPU
"/dev/shm", # shared memory
]
cmd = [
bwrap,
"--unshare-all",
"--share-net",
"--die-with-parent",
"--proc", "/proc",
"--dev", "/dev",
"--tmpfs", "/tmp",
"--dir", str(sandbox_home),
"--setenv", "HOME", str(sandbox_home),
"--setenv", "USER", os.environ.get("USER", ""),
"--setenv", "LOGNAME", os.environ.get("LOGNAME", ""),
"--setenv", MARKER_ENV, "1",
"--setenv", "PROJECT_ROOT", str(project_root),
"--chdir", str(cwd),
]
rw_binds = []
profile = PROFILES[entry["profile"]]
for type, path in profile:
path = str(resolve_path(path))
if type == "rw":
rw_binds.append(path)
elif type == "ro":
ro_binds.append(path)
else:
assert False
for path in ro_binds:
if Path(path).exists():
cmd += ["--ro-bind", path, path]
for path in rw_binds:
if Path(path).exists():
cmd += ["--bind", path, path]
for path in dev_binds:
if Path(path).exists():
cmd += ["--dev-bind", path, path]
runtime_dir = os.environ.get("XDG_RUNTIME_DIR")
if runtime_dir and Path(runtime_dir).exists():
cmd += ["--bind", runtime_dir, runtime_dir]
cmd += ["--setenv", "XDG_RUNTIME_DIR", runtime_dir]
cmd += ["--setenv", "fish_color_cwd", "red"]
envs = ["WAYLAND_DISPLAY", "DISPLAY", "DBUS_SESSION_BUS_ADDRESS", "PULSE_SERVER"]
for env in envs:
if res := os.environ.get(env):
cmd += ["--setenv", env, res]
# Mount the selected project tree at the same absolute path.
cmd += ["--bind", str(project_root), str(project_root)]
# Minimal env cleanup.
cmd += [
shell,
"-i",
]
print(f"-> sandbox profile {entry['profile']} for {entry['name']}")
return cmd
def main() -> int:
if os.environ.get(MARKER_ENV) == "1":
return 0
cwd = Path.cwd().resolve()
config = load_config()
entry = find_matching_entry(cwd, config)
if not entry:
return 2
cmd = build_bwrap_command(entry, cwd)
os.execvp(cmd[0], cmd)
return 1
if __name__ == "__main__":
raise SystemExit(main())

View File

@@ -11,6 +11,7 @@ set $term wezterm
set $menu bemenu-run --no-exec | xargs swaymsg exec --
output * adaptive_sync on
output "DP-3" render_bit_depth 10
output * bg #000000 solid_color

View File

@@ -1,5 +1,9 @@
* {
border-radius: 0 !important;
}
.tabbrowser-tab:not([selected="true"]) > .tab-stack > .tab-background {
border: 1px solid rgba(130, 130, 130, 0.5) !important;
border: 1px solid rgba(130, 130, 130, 0.5) !important;
}
.tabbrowser-tab {

View File

@@ -23,4 +23,8 @@ config.font_rules = {
}
}
config.keys = {
{key="Enter", mods="SHIFT", action=wezterm.action{SendString="\x1b\r"}},
}
return config

View File

@@ -7,6 +7,9 @@
// custom settings, run `zed: open default settings` from the
// command palette (cmd-shift-p / ctrl-shift-p)
{
"project_panel": {
"hide_hidden": true
},
"agent": {
"default_model": {
"provider": "zed.dev",