# Johannes Grof > Software developer and HTL Kaindorf student in south-east Styria, Austria. Builds native iPhone and Mac apps, web projects and small developer tools. The portfolio is available in English and German. The HTML pages and their canonical URLs are the primary source; this file is a directory for language models and other readers that support llms.txt. A public project page does not necessarily mean its source code or beta is public. ## About I live in south-east Styria and study at HTL Kaindorf. Most of what I build starts as a problem I ran into myself: a workflow that takes too many steps, a device that won't cooperate, an app that should exist and doesn't. I work with TypeScript, Swift and Python, but the stack matters less than whether the finished thing actually gets used. ## Stack - iPhone and Mac: Swift, SwiftUI, AppKit, Menu bar apps, Bluetooth LE - Web: TypeScript, Astro, Vite, Vercel, Cloudflare - CLI and tools: Rust, Python, Node, Local LLMs - Shipping: Code signing, Notarisation, Sparkle updates, GitHub Actions ## ÖffiGo - Page: https://johannesgrof.me/oeffigo/ (German: https://johannesgrof.me/de/oeffigo/) - Product website: https://oeffigo.app - Platform: iPhone (iOS 17+) and Apple Watch. Android is paused for now. - Status: closed TestFlight beta, not released yet Transit, without the guesswork. A public-transport app for all of Austria: departures, routes and step-by-step guidance, on the iPhone, the Apple Watch and the lock screen. Every time says where it came from, and when a transfer gets tight, ÖffiGo already has a plan B. No ads, no account. - Departures: Your stop with every line, delays, platform changes and cancellations, and a label on each time saying whether it is live, realtime or timetable. - Plan B when it gets tight: When a delay costs you the transfer, ÖffiGo works out an alternative from where you are. It only suggests one that saves at least three minutes. - Subscriptions: Save a trip or a whole line. ÖffiGo keeps checking while the app is closed and tells you once when something changes. - Apple Watch and Live Activity: A full app on the wrist, and the next stop on the lock screen and in the Dynamic Island without unlocking. - All of Austria: A to B across the country with up to two stops along the way, real walking legs, and the map in the operators' own colours. - Inside the station: Transfers through big interchanges via escalator, lift or stairs, wherever OpenStreetMap has mapped the station. Data: Place search, route planning and disruptions run on Verkehrsauskunft Österreich (VAO), which supports ÖffiGo as a school project. Realtime comes from the operators where they supply it. The punctuality analysis currently covers Vienna and Styria. ## Kontobuch - Website: https://kontobuch.johannesgrof.me/ - Availability: Free · No sign-up · macOS, Windows, Linux & web A digital accounting notebook. Write journal entries, calculate discounts and VAT, and get help with the next step. ## Projects ### PatchPilot - Page: https://johannesgrof.me/projects/patchpilot/ (German: https://johannesgrof.me/de/projects/patchpilot/) - Status: beta - Stack: TypeScript, Ink, Ollama - Platforms: npm, Terminal - Source: https://github.com/jx-grxf/PatchPilot A terminal coding agent for local models, with configurable permissions. PatchPilot works inside a repository with a model you run yourself: Ollama, LM Studio, MLX, llama.cpp or vLLM. Every file edit and shell command shows up in the transcript first, and the risky ones wait for your approval. Since 2.0 there are no cloud providers and no API keys. Problem: Most coding agents send your code to someone else's server and hide the run behind a chat bubble. Small local models, on the other hand, tend to break tool calls and loop until the run is wasted. What was built: A TypeScript terminal UI with nine focused tools, native function calling plus a validated fallback for smaller models, isolated child agents with narrow permissions, and a context meter that shows when the window is about to fill up. - Local only: Ollama on your machine, your LAN or over Tailscale, plus OpenAI-compatible servers like LM Studio, MLX, llama.cpp and vLLM. - Every file read and shell command lands in the transcript before it runs, with plan, build and bypass modes and a workspace boundary. - Small models stay usable: tool calls are validated and repaired step by step when they break. - Resumable sessions, pinned and compacted context, and child agents that work in their own context. ### BriskEdit - Page: https://johannesgrof.me/projects/briskedit/ (German: https://johannesgrof.me/de/projects/briskedit/) - Status: in development - Stack: Swift, SwiftUI, AppKit - Platforms: macOS - Source: https://github.com/jx-grxf/BriskEdit A native Mac editor with a terminal and Markdown preview. BriskEdit is a native editor built with SwiftUI and AppKit. It has an integrated terminal, Markdown preview and a Run button that finds the right toolchain for the file you are editing. Problem: I wanted a Mac editor for small coding tasks, with a terminal and Markdown preview already built in. What was built: A native editor on TextKit 2 and AppKit with an integrated SwiftTerm terminal, a toolchain-discovering Run button, Markdown preview, gitignore-aware find, and LSP completion from the servers already on your machine. No Electron, no telemetry. - Native text editing with TextKit 2 and AppKit. - One Run button discovers the toolchain per file (clang, swiftc, python3, node, cargo, go). - Integrated SwiftTerm terminal, live Markdown preview, and gitignore-aware find-in-folder. - LSP completion and diagnostics from your own language servers. No marketplace, no telemetry, no Electron. ### MacPhone - Page: https://johannesgrof.me/projects/macphone/ (German: https://johannesgrof.me/de/projects/macphone/) - Status: active - Stack: Swift, SwiftUI, Bluetooth LE - Platforms: macOS - Source: https://github.com/jx-grxf/MacPhone Test real Bluetooth devices through an emulator on your Mac. MacPhone runs and controls many Android emulators and iOS simulators from one Mac, and bridges a real Bluetooth LE device straight into an emulator. It mirrors the full GATT tree onto the emulator's virtual controller so on-device apps see the real services, characteristics, and advertisement with no dongle. Problem: The hard part of testing a hardware-talking mobile app isn't the app. It's getting a real BLE device in front of code running inside an emulator. What was built: A SwiftUI app that manages AVDs and Xcode simulators, connects to a physical BLE device over CoreBluetooth, mirrors its full GATT tree, and re-broadcasts it on the Android emulator's netsim controller via a Bumble virtual peripheral, forwarding reads, writes, and notifications both ways. - Manages Android emulators (AVDs) and Xcode iOS simulators in parallel from one panel. - Bridges a real BLE device into the emulator over CoreBluetooth, mirroring the full GATT tree. - Forwards reads, writes, and notifications both ways, so the app under test sees the real hardware. - Keeps sessions clean: disconnects stale clients and tears the bridge down with its parent process. ### BottleLite - Page: https://johannesgrof.me/projects/bottlelite/ (German: https://johannesgrof.me/de/projects/bottlelite/) - Status: preview - Stack: Swift, SwiftUI, Wine - Platforms: macOS, Wine - Source: https://github.com/jx-grxf/BottleLite A lightweight native macOS runner for Windows apps. BottleLite is a SwiftUI Wine front-end for running Windows apps on macOS without Electron, accounts, telemetry, or a bundled runtime. It detects your existing Wine install, keeps bottles persistent, imports .exe files safely, and gives each program logs, settings, and stop controls. Problem: Wine workflows on macOS tend to sprawl across Terminal commands, prefixes, logs, and runtime assumptions. What was built: A SwiftUI app that manages bottles, validates PE executables, runs GUI and console programs through existing Wine, captures logs, and wires Sparkle update feeds for preview releases. - Manages persistent Wine bottles with import, rename, delete, and per-program settings. - Validates .exe files by extension and MZ header before adding them to a bottle. - Runs GUI apps quietly and console tools visibly in Terminal.app, with logs for each launch. - Preview distribution includes a DMG, Sparkle appcast, and SHA256 checksums. ### poise - Page: https://johannesgrof.me/projects/poise/ (German: https://johannesgrof.me/de/projects/poise/) - Status: active - Stack: Swift, macOS, Menu Bar - Platforms: macOS - Source: https://github.com/jx-grxf/poise Your AirPods as a posture coach, fully on-device. A native macOS menu bar app that reads head motion from your AirPods' built-in sensors, learns your upright baseline, and nudges you when you start to slouch. No camera, no cloud. The motion data never leaves your Mac. Problem: Posture apps usually mean a webcam watching you all day, or a wearable you have to remember to charge and put on. What was built: A SwiftUI menu bar app that taps the AirPods' CMHeadphoneMotionManager, calibrates an upright baseline, and watches for sustained forward tilt. Everything stays local. - Reads head motion straight from the AirPods sensors via CMHeadphoneMotionManager. - Calibrates your upright baseline and only nudges you on sustained slouching. - Runs entirely on-device: no camera, no cloud upload, no motion data leaving the Mac. - Sits quietly in the menu bar with a DMG release and Sparkle update feed. ### claude-swap-bar - Page: https://johannesgrof.me/projects/claude-swap-bar/ (German: https://johannesgrof.me/de/projects/claude-swap-bar/) - Status: active - Stack: Swift, macOS, Menu Bar - Platforms: macOS - Source: https://github.com/jx-grxf/claude-swap-bar Switch between Claude Code accounts from the menu bar, with live usage meters. A native macOS menu bar app for anyone running more than one Claude Code account. Swap the active account in one click and watch live usage meters for each, so you can see what's left before you hit a limit. Problem: Running multiple Claude Code accounts means manual re-auth and no visibility into how much of each plan you've used. What was built: A SwiftUI menu bar app that stores and switches between accounts and surfaces live per-account usage meters right in the dropdown. - Switches the active Claude Code account in one click from the menu bar. - Shows live per-account usage meters right in the dropdown. - Stores multiple accounts so re-authenticating blind is a thing of the past. - Native SwiftUI app with a GitHub release and Sparkle update feed. ### NotchTray - Page: https://johannesgrof.me/projects/notchtray/ (German: https://johannesgrof.me/de/projects/notchtray/) - Status: active - Stack: Swift, macOS, Menu Bar - Platforms: macOS - Source: https://github.com/jx-grxf/NotchTray Reach menu bar icons hidden behind the notch on older macOS versions. A native macOS utility that surfaces status items hidden behind the MacBook notch and shows them in a Dynamic Island-style dropdown, so overflow menu bar icons stay reachable instead of disappearing under the camera housing. Problem: On notched MacBooks, extra menu bar icons get pushed under the notch and become unclickable once the bar fills up. What was built: A Swift menu bar utility that detects overflow status items and presents them in a Dynamic Island-style dropdown anchored to the notch. - Detects status items pushed behind the MacBook notch. - Presents them in a Dynamic Island-style dropdown anchored to the notch. - Keeps overflow menu bar icons reachable without removing apps. - Native Swift utility, shipping as a signed DMG since v1.0.0. ### CCrab - Page: https://johannesgrof.me/projects/ccrab/ (German: https://johannesgrof.me/de/projects/ccrab/) - Status: experimental - Stack: Swift, AppKit, Core Animation - Platforms: macOS 14+ - Source: https://github.com/jx-grxf/CCrab A small desktop companion that shows what Claude Code is doing. A native macOS desktop companion for Claude Code: a pixel crab on a floating panel that reacts to what your agent sessions are doing, plus a menu bar item with your 5-hour and weekly usage bars, every live session, and recent projects. Written in Swift against AppKit and Core Animation. No Electron, no WebView. Problem: I wanted to see when a coding agent is busy without keeping its terminal or a browser tab in front. What was built: Every animation is a Core Animation keyframe over layer contents, so the render server owns the timeline and the process gets no per-frame wakeups. The resting pose is parsed from vector rects into CALayers instead of decoded bitmaps, and animations are removed, not paused, the moment the panel is occluded, the display sleeps, or the screen locks. - Core Animation handles the animation timeline, without an application timer for every frame. - Menu bar with 5-hour and weekly usage bars, reset countdowns, and every live session. - State arrives over Claude Code hooks on a loopback endpoint: nothing polls, no extra API calls, no token is read. - Connecting backs up your settings.json first and leaves other tools' hook entries alone. ### PortPirate - Page: https://johannesgrof.me/projects/portpirate/ (German: https://johannesgrof.me/de/projects/portpirate/) - Status: coming soon - Stack: Swift, macOS, Menu Bar - Platforms: macOS - Source: source not public macOS menu bar control for local dev ports. A Swift menu bar app that maps every listening port to its process, its repository, and the AI agent that started it, so localhost stays visible and exact processes can be stopped from one native surface. Problem: Local development servers keep running, ports collide, and it is hard to tell which process, repository, or agent owns a given listener. What was built: I built a native Swift menu bar app that scans listening TCP ports, links each one to its process, repo, and agent, and gates process control behind precise actions. - Runs as a native macOS menu bar utility with a dedicated runtime browser. - Maps each listening TCP port to its process, repository, and the agent that started it. - Opens localhost URLs and stops exact PIDs instead of using broad process commands. ### SlamX - Page: https://johannesgrof.me/projects/slamx/ (German: https://johannesgrof.me/de/projects/slamx/) - Status: archived - Stack: Swift, macOS, Sensors - Platforms: macOS - Source: https://github.com/jx-grxf/SlamX Slap your MacBook and it knows. Real accelerometer, no microphone. A native macOS toy that reads the MacBook's built-in Apple SPU accelerometer over IOKit HID, spots a sharp impact spike, counts it, and plays a sound. No mic, no fake triggers: it reacts to the actual motion sensor, with live telemetry and a calibration wizard so you can see it working. Problem: A joke 'slap detector' is easy to fake with the microphone or a fixed trigger. Apple also gives no clean public Core Motion API for the MacBook accelerometer. What was built: A SwiftUI app that taps the private AppleSPUHIDDevice stream through IOKit HID, with live telemetry (impact, peak, sample rate, raw bytes), Soft/Balanced/Hard presets, a calibration wizard, and local sound feedback. - Reads the MacBook's Apple SPU accelerometer directly over IOKit HID. - Live telemetry: impact, peak, sample rate, axes, magnitude, and raw HID bytes. - Sensor only: no microphone access, no audio fallback, nothing uploaded. - Calibration wizard, threshold presets, and your own sounds. Built for fun; please don't actually abuse your Mac. ### dirhop - Page: https://johannesgrof.me/projects/dirhop/ (German: https://johannesgrof.me/de/projects/dirhop/) - Status: beta - Stack: Rust, ratatui, nucleo - Platforms: macOS, Linux - Source: https://github.com/jx-grxf/dirhop Jump to any folder from the terminal in a few keystrokes. A fuzzy folder picker for the terminal, written in Rust. It searches every folder in your home directory while you type, ranks your projects and the places you visit most at the top, and drops you there with Enter. You choose the command name and the shortcut in a small settings screen, and it keeps itself up to date from GitHub releases. Problem: Getting into a project meant tabbing through four or five folders every time, and jump tools like zoxide only know folders you have already visited. What was built: A parallel directory walk built on the ignore crate (the one ripgrep uses) streams folders into the UI in batches, so results show up before the scan is done. The Helix editor's nucleo matcher scores every keystroke, plus a bonus for git repos, project folders and frecency. The UI draws on stderr and prints the chosen path on stdout, so a small zsh, bash or fish function can cd into it. - Searches around 10,000 folders in under 100 ms, with results filling in while you type. - Git repos, project folders and the places you visit most rank first; zoxide history counts too. - Preview with git branch, detected language and folder contents; Ctrl-E opens your editor, Ctrl-O opens Finder. - Your own command name and shortcut, a one-line install, and self-updates checked against SHA-256. ### HealthKit-MCP - Page: https://johannesgrof.me/projects/healthkit-mcp/ (German: https://johannesgrof.me/de/projects/healthkit-mcp/) - Status: experimental - Stack: TypeScript, MCP, HealthKit - Platforms: MCP, iOS, Supabase - Source: source not public Read-only Apple Health context for MCP-capable agents. A bridge that syncs Apple Health aggregates from an iPhone app into a scoped backend and exposes sleep, workouts, training load, and trends through a read-only Model Context Protocol server. Problem: Apple Health has rich personal context, but there is no normal server API an agent can read from safely. What was built: A TypeScript MCP server, Supabase schema, and iOS HealthKit sync plan that move aggregate summaries instead of raw health samples. - Read-only MCP tools for daily summaries, sleep, workouts, training load, and trends. - Demo mode runs without a backend; the Supabase path is prepared for real user isolation. - The iPhone side reads HealthKit locally and syncs aggregates instead of raw samples. - Built for ChatGPT, Claude, Codex, and Claude Code as MCP-capable clients. ### agent-presence - Page: https://johannesgrof.me/projects/agent-presence/ (German: https://johannesgrof.me/de/projects/agent-presence/) - Status: active - Stack: Rust, Discord, CLI - Platforms: macOS, Windows, Linux - Source: https://github.com/jx-grxf/agent-presence Discord Rich Presence for Claude Code and Codex. One static binary, no bot token. A small Rust tool that shows what your coding agent is doing live in your Discord status. It ships as a single static binary, needs no bot token, and shows little by default, so you decide what is visible. Problem: Showing agent activity in Discord usually means standing up a bot with a token and trusting whatever it decides to broadcast. What was built: A single static Rust binary that talks to Discord's local Rich Presence IPC. No bot token, no hosted service, and conservative defaults for what it shows. - Shows live in Discord what your Claude Code or Codex session is doing. - One static Rust binary, no bot token, no hosted service. - Conservative defaults: you control what surfaces in your status. - Runs on macOS, Windows, and Linux with signed release artifacts. ### Hermes-Discord-Voice - Page: https://johannesgrof.me/projects/hermes-discord-voice/ (German: https://johannesgrof.me/de/projects/hermes-discord-voice/) - Status: archived - Stack: TypeScript, Discord, Whisper - Platforms: Node.js, Discord - Source: https://github.com/jx-grxf/Hermes-Discord-Voice Self-hosted voice for the Hermes agent, straight in a Discord call. The bot joins your Discord voice channel, captures a spoken turn, transcribes it locally with Whisper, sends the text to Hermes, and speaks the reply back through the TTS voice you pick. Personal servers only, with no hosted service in the middle. Problem: Talking to a local agent over Discord voice usually means trusting a hosted bot and giving up control of the speech pipeline. What was built: A self-hosted Discord.js bridge with local whisper-cli transcription, one Hermes session per guild, a per-guild speaker allowlist, and pluggable TTS: Piper, macOS say, ElevenLabs or a custom command. - Joins Discord voice, records a turn, and transcribes it locally with whisper-cli, no cloud speech recognition. - Routes transcripts to Hermes over CLI by default, or its API/Gateway. - Replies through Piper, macOS say, ElevenLabs, or your own TTS command. - Private by default: one session per guild with a speaker allowlist you control. ### OpenClaw-Discord-Voice - Page: https://johannesgrof.me/projects/openclaw-discord-voice/ (German: https://johannesgrof.me/de/projects/openclaw-discord-voice/) - Status: archived - Stack: TypeScript, Discord, Voice - Platforms: Node.js, Discord - Source: source not public Talk to a local OpenClaw agent through a Discord voice channel. Join a voice channel, speak one turn, and the bridge transcribes it locally with Whisper, hands it to your local OpenClaw session, and plays the reply back. The whole pipeline stays on your machine and in view. Problem: Voice-controlling a local agent over Discord usually means a hosted bot you can't see into and don't fully control. What was built: A self-hosted Discord.js bridge: Opus decode, ffmpeg to WAV, local whisper-cli transcription, one session per guild, and switchable Piper, macOS say, or ElevenLabs voices. - Captures one spoken turn and transcribes it locally with whisper-cli, no cloud speech recognition. - Bridges straight into your local OpenClaw session, one per Discord guild. - Switchable replies: Piper, macOS say, or ElevenLabs. - Built-in doctor and /info checks for env, binaries, model path, and Discord auth. ### johannesgrof.me - Page: https://johannesgrof.me/projects/johannesgrof-me/ (German: https://johannesgrof.me/de/projects/johannesgrof-me/) - Status: active - Stack: Astro, TypeScript, Vercel - Platforms: Web - Source: https://github.com/jx-grxf/johannesgrof.me This site: a portfolio that reads its own release data from GitHub. An Astro site with no client framework, where every project row pulls its version, release assets and download counts from the GitHub API at build time and a daily rebuild keeps them current. Bilingual EN/DE, static except for one contact function. Problem: A portfolio goes out of date the moment a release ships: versions, download counts and dates get typed in by hand and are quietly wrong a week later. What was built: A static Astro site that resolves each repository once per build and renders the numbers it gets back, with verified fallbacks for the case where GitHub is unreachable. A scheduled deploy hook rebuilds it daily; the contact form is the only server-side surface. - Build-time GitHub data with verified fallbacks, so a rate-limited build degrades instead of lying. - Bilingual EN/DE with hreflang alternates on every route, project pages included. - One serverless function for the contact form: origin check, per-IP rate limit, honeypot. ### ÖffiGo Website - Page: https://johannesgrof.me/projects/oeffigo-website/ (German: https://johannesgrof.me/de/projects/oeffigo-website/) - Status: active - Stack: Astro, TypeScript, Cloudflare - Platforms: Web - Live: https://oeffigo.app - Source: source not public The product site behind oeffigo.app, with a public data status page. The marketing and status site for ÖffiGo: what the app does, which parts are beta, and a status page that reports the state of the transport data instead of leaving it to a screenshot. Problem: A transport app that mixes official realtime, timetable data and its own beta measurements has to say which is which, and a landing page that only markets the app cannot do that. What was built: A product site that carries the same status discipline as the app: every capability is labelled with what it actually delivers today, and a public status page reports the data situation live. - A public status page for the data situation instead of a marketing claim. - The same paper system as this site, in ÖffiGo's own colours. - Bilingual, statically served, on its own domain. ### Tools - Page: https://johannesgrof.me/projects/tools/ (German: https://johannesgrof.me/de/projects/tools/) - Status: active - Stack: TypeScript, Vite, pdf-lib - Platforms: Web - Live: https://tools.johannesgrof.me - Source: https://github.com/jx-grxf/tools Merge, split, rotate and convert PDFs and images, entirely in your browser. A small web app that does the everyday PDF and image jobs without an upload: merge, split, extract or delete pages, rotate, PDF to images, images to PDF, and format conversion. Every file is processed in the browser, so nothing is sent anywhere and there is no size limit beyond your own memory. Problem: Free online PDF tools want an upload, which is the one thing you do not want for a contract, a payslip or a scan. What was built: Vite and TypeScript with no UI framework, conversions written as pure functions with no DOM access so they can be unit tested in Node, and a tool registry that makes adding a new operation a one-entry change. pdf-lib writes, pdf.js reads and renders, fflate zips, all bundled, nothing loaded from a CDN at runtime. - Merge, split, extract and delete pages, rotate, PDF to images, images to PDF, and image format conversion. - Everything runs in the browser: no upload, no account, no size limit beyond your own memory. - Results download individually or as a ZIP, and the limits (no OCR, no encrypted PDFs) are stated openly in the README. - Deployed from GitHub Actions over OIDC and SSM, with no long-lived AWS key in the repository. ### Caruso-Reborn - Page: https://johannesgrof.me/projects/caruso-reborn/ (German: https://johannesgrof.me/de/projects/caruso-reborn/) - Status: beta - Stack: TypeScript, UPnP, DLNA - Platforms: macOS, Web - Source: https://github.com/jx-grxf/Caruso-Reborn Internet radio, brought back to first-gen T+A Caruso systems. T+A dropped a usable internet-radio path for older Caruso units, so this turns your computer into a local UPnP/DLNA source: search stations on your laptop, save the ones that work, and browse them again from the Caruso, along with your own music folders. Problem: First-gen Caruso systems still sound great, but T+A no longer offers a practical native internet-radio path, so everyday station browsing is broken. What was built: A local Fastify and UPnP/DLNA bridge that announces itself as a media server, resolves real stream URLs from TuneIn and Radio Browser, and exposes saved stations and local music under the Caruso's own tree, with a web dashboard and a keyboard TUI control room. - Turns your Mac into a UPnP/DLNA media server the Caruso can browse. - Resolves playable streams from TuneIn, with a Radio Browser fallback. - Saved stations and local music folders appear in the Caruso's own tree. - Web dashboard plus a keyboard control-room TUI; rebinds when you switch LAN/Wi-Fi. ### ip-multitool - Page: https://johannesgrof.me/projects/ip-multitool/ (German: https://johannesgrof.me/de/projects/ip-multitool/) - Status: active - Stack: Python, CLI, Networking - Platforms: Terminal, Python - Source: https://github.com/jx-grxf/ip-multitool A focused terminal toolkit for IP, DNS, RDAP, HTTP, and subnet diagnostics. A Python CLI/TUI for practical network checks: IP and domain lookup, privacy indicators, DNS records, RDAP/WHOIS, HTTP response inspection, subnet math, local network discovery, and authorized port checks. Problem: Network debugging often jumps between web lookups, dig, whois, curl, subnet calculators, and local scan tools. What was built: A Python package with a full-screen TUI, scriptable commands, JSON output, optional dig/nmap/arp-scan integration, and explicit safety boundaries. - IP and domain lookups with geo, ISP, ASN, reverse DNS, RDAP, and privacy indicators. - DNS, WHOIS/RDAP, HTTP, and TLS checks with JSON output for automation. - Subnet calculator, phone parsing, LAN discovery, and authorized port checks. - Clear limits: no person identification from IPs and no scans without authorization. ### DocxToPDF - Page: https://johannesgrof.me/projects/docxtopdf/ (German: https://johannesgrof.me/de/projects/docxtopdf/) - Status: archived - Stack: TypeScript, macOS, Word - Platforms: macOS, Microsoft Word - Source: https://github.com/jx-grxf/DocxToPDF Batch-convert DOCX to PDF using Word itself as the engine. A keyboard-driven macOS tool that Spotlight-searches your whole Mac for DOCX files, lets you tick the ones you want, and exports them all in one Word session, so the PDFs match Word's own output, not a parser's guess. Problem: Exporting DOCX to PDF by hand is tedious, and LibreOffice or library converters quietly mangle complex Word layouts. What was built: A TypeScript TUI that finds DOCX via Spotlight, offers keyboard multi-select, and drives Microsoft Word over AppleScript to export in a single batch session. - Uses Microsoft Word itself as the renderer, so PDFs match Word's own export. - Spotlight-searches the whole Mac for DOCX, with a filesystem fallback. - Keyboard multi-select and filter; one Word session exports the whole batch. - Optional OCRmyPDF layer keeps the output searchable. ## Contact - Email: contact@johannesgrof.me - Contact form: https://johannesgrof.me/#contact - github.com: https://github.com/jx-grxf - linkedin.com: https://www.linkedin.com/in/johannes-grof - x.com: https://x.com/johannesgrofdev - Privacy policy (German): https://johannesgrof.me/datenschutz/ - Imprint (German): https://johannesgrof.me/impressum/