@knoopxGitHub ↗

knoopx

I'm a polyglot SWE from Barcelona. +20 years experience in info-sec, video streaming, e-commerce, SAAS, STEM teacher, hearing tech, and ML.

Viewing version 1

Back to latest →

Shared this setup with the community.

You’re reading the setup as it was published on 18 September 2026.

What I build

All sorts of stuff: development tools, ml projects, desktop shells, homelabs, FPV drones, electric skateboards, 3D printers, mechanical keyboards, hardware projects.

Toolchains: Rust, Python, TypeScript/JavaScript, Nix, Ruby, Go, Crystal, Bash. Build tooling: Bun, uv, just, nix. Version control: Jujutsu (jj)

Agents & harnesses

A highly customized Pi setup, https://github.com/knoopx/pi

  • Sandboxed runtime (bubblewrap), launched from the compositor: Mod+Ppi ~/.pi, Mod+Shift+Kpi-project
  • No skill.md files, no JavaScript extensions: the system is a collection of TSV records, simple script tools, and hooks.
  • Cross-session memory: 16 record tables (5,254 rows) persisted as TSV, queried in-memory with DuckDB (see Skills)
  • Planning hook: forces the agent to plan, split tasks, and assign them to the corresponding sub-agents; all sessions start in an orchestrator window that plans and delegates, each sub-agent runs in its own Kitty tab
  • Sub-delegation hook: at 20k assistant output tokens, triggers forced sub-delegation
  • Syntax-error hook: on every syntax error, instructs the agent to query the syntax records and capture new findings
  • Session stashing: /stash-session adds the current session id to stashed-sessions.json and closes the window; /unstash-sessions opens an overlay with the session list, enter opens the session in a new window and removes it from the stash
  • Used for everything: specialized agents and tools for personal records, web research, content curation, media management, shopping, homelab management, music playback, reporting and plotting
  • The best harness is the one you own and configure for yourself; the underlying implementation is just a tech stack preference, and there are a hundred orchestration strategies, none fits all
  • I use Pi with a bunch of custom orchestration rules: task splitting and isolated subtask delegation into sessions. The main session stays lean, all exploration, analysis, and execution happen in disposable contexts, so Qwen3.8 and dumber models do not lose track of major tasks

The agent runs as a self-improving loop on top of a machine-readable skill graph.

The knowledge base is a living graph, not a pile of files. Every doc carries a frontmatter header — name, keywords, category, links to related docs — so the system can search by keyword, walk the references between docs, validate broken links and orphans, and collapse redundant forwarding chains. The same mechanism runs on the project's spec docs: typed links (parent / depends-on / implements) with a validator that catches dangling refs and cycles, so the design stays consistent as it grows.

Dispatcher and specialists. A top-level orchestrator never does the work itself — it splits tasks into small steps, routes each to the right domain specialist, verifies the result, and forwards every correction I make into every subsequent delegation. I state anything once.

Nudges — hints planted at drift-moments. The agent drifts: it starts aimed, but a long task quietly pulls it off course. So hints fire at exactly the moments drift starts:

  • New user message → "query the manual and tools, read them before acting"
  • A tool call fails with a parse error → "look the error up, capture it as a syntax note, only then retry"
  • Turn start → re-surface the session's live to-do list

The point is the timing: catching drift the moment it starts is cheap; catching it in a post-mortem, after the damage, isn't.

Guardrails — known-bad moves get stopped and replaced in one line.

  • rm → blocked, use trash (recoverable delete)
  • sed-pipeline bulk file edits → blocked, use targeted per-file edits
  • interactive jj squash → blocked, use the non-interactive form
  • hardcoded Nix store paths → blocked, use nix run
  • curl on the GitHub API → blocked, use gh api

Each one converts a mistake into an immediate, named lesson, so the same derailment happens once, not repeatedly. Each guardrail is fixture-tested (true-positive "should block" plus false-positive "should pass"), so the system cannot silently break its own guardrails.

The self-improvement loop. This one is mandatory: the agent's memory is session memory, not system memory, and you cannot maintain good behavior on discipline alone. So a standing protocol reflects on past sessions, finds every stumble and every correction, and encodes each one as a permanent doc, rule, or nudge in the owning domain:

  • The agent misuses a jj revset flag → the error becomes a new syntax note in the jj domain; the next session's manual already has it
  • I correct the agent mid-task → the correction is relayed into every remaining step, then distilled into a permanent rule
  • The agent does something I did not ask for → misconduct report: the root cause becomes a corrected protocol file, not a log entry

The flywheel: act → nudge on drift → guardrail on the bad move → everything gets recorded → the record gets distilled back into the graph → the next run starts smarter. Knowledge lives in the graph, not in the agent's head — every mistake is paid once, never re-billed.

Apps

NixOS (flake-based declarative config, kOS), Helix (default editor, LSP coverage), Niri (compositor: move across tens of running sessions, queue work, pin running sessions for follow-up), Astal (shell), Vicinae (launcher).

Full config: https://github.com/knoopx/nix

Models

https://huggingface.co/knoopx/Swift-Qwen3.8-27B-NInfer

  • Custom Ninfer Fork, with built-in model router https://github.com/knoopx/ninfer
  • MTP speculative decoding: up to 6 draft tokens per step, verified in a single forward pass
  • 261k context window, flash attention, int8 quantized KV cache
  • 3x concurrent sessions @ ~150 tok/s average each

Terminal

Kitty (GPU acceleration, Wayland) / Fish (default shell, custom greeting) / Nushell (structured data pipelines: TOML/YAML/JSON to tables).

Machines

Linux Desktop/Workstation:

  • Display (Gigabyte MO27U2): 3840x2160 @ 1.5x scale in a 26" panel, 240 Hz [External]
  • CPU: AMD Ryzen 9 9950X (32 threads) @ 5.76 GHz
  • GPU: NVIDIA GeForce RTX 5090 Founders Edition, 32GB VRAM
  • Memory: 64 GiB DDR5
  • Storage: 2TB NVMe plus 2x 3.6TB (btrfs, zstd compressed)

Chuwi Mini Book: My portable Linux laptop (Intel N150, 16GB, 512GB NVMe, 15.6" touchscreen). The crapiest and most awesome laptop I ever owned. Chuwi Hi 10 Max: My portable Linux tablet, where I plug one of my Corne keyboards

The same flake also builds Steam Deck and Android (AVF) profiles — one config, four hardware profiles.

Subscriptions & costs

  • No subscriptions, 100% self-hosted.
  • Ongoing cost after hardware: zero (electricity only). One-time GPU purchase 2,259 EUR.
  • The data stays on my computer.

Skills

My own ones, built over the past two years. Technically not skills, but a bunch of TSV records, simple script tools, and hooks.

  • 16 record tables (5,254 rows): bookmarks, contacts, documents, evidences, ideas, journal, models, places, recipes, resources, shopping lists, and more
  • Companion tools: duckdb-repl, nu-repl, records-, intent-, protocol-, evidence-
  • Hooks query the records before acting; every factual claim cites a stored evidence record

MCP connections

MCP is irrelevant to me. I only use pure shell scripts (mostly based on nu-shell/duckdb).

  • The scripting bridge (https://github.com/knoopx/pi-scripting-bridge) exposes the agent runtime to plain scripts: spawn-agent opens an interactive pi session in a new Kitty tab with system and tool overrides, session-terminate closes it and captures the final response
  • Scripts are written in Nushell, any other scripting language works too
  • No packages to install, no test suites to run; bugs get reported and fixed in about five minutes

How I work

The same way I used to 20 years ago, by reading, researching, learning and implementing following SWE best practices. Everything is captured as protocols and enforced via hooks. The whole stack is built to run exclusively on local models: lightweight and lean context.

  • For simple tasks, I start by asking questions about the task I want to achieve, which forces the agent to read and understand the pieces; once I have a clear idea, I instruct execution
  • protocols.tsv carries the rules that tell the agents how to orchestrate and execute tasks; everything is loaded on demand, no SYSTEM.md, no AGENTS.md
  • Nudges catch drift the moment it starts, guardrails stop known-bad moves in one line, and the self-improvement loop pays for every mistake once — see the self-improving loop above