<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Fahad Bilal Saleem</title>
    <description>The latest articles on DEV Community by Fahad Bilal Saleem (@fahadbilalsaleem).</description>
    <link>https://dev.to/fahadbilalsaleem</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4143241%2Ff895f2c6-8fca-45d7-9917-7fc8fdadf24c.jpg</url>
      <title>DEV Community: Fahad Bilal Saleem</title>
      <link>https://dev.to/fahadbilalsaleem</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fahadbilalsaleem"/>
    <language>en</language>
    <item>
      <title>Atlas is an operating system. Its CPU just happens to be a language model.</title>
      <dc:creator>Fahad Bilal Saleem</dc:creator>
      <pubDate>Wed, 14 Oct 2026 14:52:21 +0000</pubDate>
      <link>https://dev.to/fahadbilalsaleem/atlas-is-an-operating-system-its-cpu-just-happens-to-be-a-language-model-5hfd</link>
      <guid>https://dev.to/fahadbilalsaleem/atlas-is-an-operating-system-its-cpu-just-happens-to-be-a-language-model-5hfd</guid>
      <description>&lt;p&gt;Stop picturing a chatbot. Atlas — the system I've been building since mid-February, now v3.1.0, running 24/7 on a free Oracle Cloud ARM VPS — is architected like an operating system. It has a kernel, system calls, a scheduler, virtual memory with garbage collection, a capability-based permission model, device drivers, a boot sequence, and a dmesg. The only unusual component is the processor: it's a language model.&lt;/p&gt;

&lt;p&gt;Once you see it that way, every design decision reads differently. This is the tour, subsystem by subsystem.&lt;/p&gt;

&lt;p&gt;Prefer video? Here's the 2-minute explainer:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/BMnlgIhvWiY" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  The kernel
&lt;/h2&gt;

&lt;p&gt;Every message, text, photo, document, voice note — enters one pipeline: rate limiter, guardrails, a small classifier that routes it into one of six paths, then the orchestrator's tool-use loop (max 10 iterations, 20 tool calls). That loop is the kernel's main loop. It never does work itself; it dispatches.&lt;/p&gt;

&lt;p&gt;The classifier is worth naming because it's the cheapest important decision in the system: a tiny Groq model at temperature 0 decides whether a message needs the paid model at all. Casual chat never touches one. In OS terms, it's the interrupt dispatcher — fast, dumb, and correct enough that everything expensive happens behind it.&lt;/p&gt;

&lt;p&gt;One turn at a time across all interfaces, enforced by a Postgres advisory lock. A mutex, shared between the Telegram, voice, and dashboard processes.&lt;/p&gt;

&lt;h2&gt;
  
  
  System calls
&lt;/h2&gt;

&lt;p&gt;The 116 tools are syscalls. User space (the model) can't touch the world directly — it traps into the kernel, which executes the call and returns the result. The 15 MCP servers are driver modules: mail, calendar, jobs, memory, vault, shell, web — each owning its domain, each failure-contained.&lt;/p&gt;

&lt;p&gt;Two optimizations keep 116 syscalls affordable, and both have OS analogues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Two-tier syscall table.&lt;/strong&gt; The model always sees name + ~80-char description + parameter types (~15 tokens per call). Full schemas expand only for calls already made — like keeping the hot path of the syscall table in cache. ~85% off.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-route syscall filtering.&lt;/strong&gt; Each dispatch path sees only the calls it needs. Another 40–60% off.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After heavy turns, a background pass compresses the trajectory into a ≤150-word summary, the equivalent of compacting the kernel log so the next boot stays fast. Measured ~69% token reduction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Permissions
&lt;/h2&gt;

&lt;p&gt;This is the subsystem I care about most, because an OS that runs your life needs a real security model.&lt;/p&gt;

&lt;p&gt;Five tiers: &lt;strong&gt;read, write, sensitive, critical, nuclear.&lt;/strong&gt; Think Unix permissions crossed with capabilities(7), except the top two tiers require interactive authentication: the kernel sends a one-time token to my phone, and the call executes only after I reply &lt;code&gt;confirm tool &amp;lt;TOKEN&amp;gt;&lt;/code&gt;. Nuclear actions are capped at one per hour. It's sudo with a 30-minute expiry and a paper trail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;External content is untrusted input, structurally.&lt;/strong&gt; Anything arriving from a document, image, email, or web page is data — it can never trigger a write-tier syscall without my approval. That's the prompt-injection defense, enforced by the gateway, not by asking the model to be careful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No shell where the model can reach.&lt;/strong&gt; Everywhere a message could touch a command executes shell-free; the shell tool accepts only flags and plain words. The sandbox where Atlas builds its own tools gets credentials injected at the network layer — &lt;strong&gt;the container never sees a raw secret&lt;/strong&gt;, the way a process never sees the kernel's keyring.&lt;/p&gt;

&lt;p&gt;A September audit registered 43 defects against this model. All fixed, deployed, and verified live within 24 hours. The register is permanent: every entry names the defect, the fix, and the command that proves whether it's still alive.&lt;/p&gt;

&lt;p&gt;The 60-second demo of the guard in action — one message, three jobs, asked before saving:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/S7oE1W7qjIk" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory management
&lt;/h2&gt;

&lt;p&gt;Three retrieval paths fused with reciprocal-rank fusion: vector search (local embeddings into pgvector), full-text search (for the exact names and dates vectors fumble), and message history search. Virtual memory with three page tables.&lt;/p&gt;

&lt;p&gt;Then the parts that make it feel like memory instead of storage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Contextual retrieval&lt;/strong&gt; — a small model writes a 1–2 sentence context summary for every fact before embedding, so "the meeting" resolves to the right meeting. Like tagging pages with their address space.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The gardener&lt;/strong&gt; — a nightly garbage collector. Prunes low-importance facts, merges duplicates, archives everything it deletes first. Nothing is freed without a backup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The dreaming pass&lt;/strong&gt; — weekly offline maintenance. Distills new facts and behavioral patterns from the week's conversations. fsck for the mind.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The lesson it taught me: retrieval quality is 90% of whether the system feels intelligent. The CPU barely matters if memory hands it the wrong pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  The scheduler
&lt;/h2&gt;

&lt;p&gt;Cron jobs as the OS scheduler: job-board scans, email reading, tracker syncs, the morning briefing — all in UAE time, each with a 15-minute timeout, missed ticks caught up for 15 minutes max. Twelve enabled jobs, all verified firing on schedule.&lt;/p&gt;

&lt;p&gt;On top of that, an agent layer for complex work: a Queen process spawning parallel workers per domain (finance, career, health, research, memory, scheduling, email, docs), each with only its own syscalls — process isolation by construction. Workers must state assumptions instead of inventing facts and report with explicit "Not done" and "Open questions" sections. A planner decomposes, a supervisor executes with parallel steps, a verifier re-checks results, and a self-improving agent captures my corrections into future runs.&lt;/p&gt;

&lt;p&gt;There's even a weekly AutoML loop rewriting the job-scorer's training code — kept only if error improves ≥1%, otherwise code &lt;em&gt;and&lt;/em&gt; artifacts revert. The OS tunes its own scheduler heuristics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fault tolerance
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;DeepSeek → Groq → Gemma → Qwen&lt;/strong&gt;, with automatic cooldowns and climb-back. When the main provider fails, the system degrades to free local models instead of dying — redundant hardware, except the hardware is models. Per-role routing lets each subsystem (main, voice, workers, vision) fail over independently.&lt;/p&gt;

&lt;p&gt;Circuit breakers on every syscall: consecutive failures trip the breaker, a half-open probe closes it only on a genuinely successful call, and the router escalates around tools whose reliability score drops. The kernel watches its own drivers fail and routes around them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Power management
&lt;/h2&gt;

&lt;p&gt;Under $5/month isn't achieved with cheap models — it's achieved by not spending cycles:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Technique&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free-tier Groq for chat, routing, tool-free reasoning&lt;/td&gt;
&lt;td&gt;$0 for most messages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Main role on DeepSeek, not Claude&lt;/td&gt;
&lt;td&gt;Paid tokens at a fraction of the price&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Two-tier syscall table + per-route filtering&lt;/td&gt;
&lt;td&gt;~85%, then ~40–60% off&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trajectory compaction&lt;/td&gt;
&lt;td&gt;~69% off heavy turns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prompt caching&lt;/td&gt;
&lt;td&gt;Cache reads at 0.1×&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local embeddings&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Measured: $0 for chat, ~$0.015 for a DeepSeek turn with tools, ~$0.09 for a full job analysis. Recent 30-day windows: ~$2.45–$2.57. Lifetime since February: $24.71.&lt;/p&gt;

&lt;p&gt;And since this month, the meter is honest: &lt;strong&gt;every API call writes one row&lt;/strong&gt; — provider, model, tokens, cost, latency. A &lt;strong&gt;$5 weekly hard limit&lt;/strong&gt; moves paid calls to free Groq past the threshold, with a visible note on every affected reply. Never silent — a design decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Device drivers
&lt;/h2&gt;

&lt;p&gt;Telegram, the dashboard, voice (English, Urdu, Punjabi — transcribed in the language spoken), and now a device fabric: per-device tokens over a private network, one-time-code pairing, a decision log of every allow &lt;em&gt;and refusal&lt;/em&gt;. Drivers for bodies; one kernel. The current focus is the laptop as the first full device.&lt;/p&gt;

&lt;p&gt;Boot is &lt;code&gt;warmMCP()&lt;/code&gt; — all driver modules probed in parallel at startup, graceful degradation for anything that doesn't answer. PM2 is init. The JSON logs plus a 33-gauge Grafana dashboard are dmesg.&lt;/p&gt;

&lt;h2&gt;
  
  
  The engineering culture (why I trust it)
&lt;/h2&gt;

&lt;p&gt;Nine months ago I measured progress in features. Now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nothing closes until seen working live.&lt;/strong&gt; I run every verification myself. 88 open, 98 closed in the register.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests first, shown failing.&lt;/strong&gt; 1,191 across 74 files, isolated so they can never touch production. (One test reaching the real vault and locking it is why.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compute it or delete it.&lt;/strong&gt; An audit found the system's own reports printing numbers nobody computed — a model-written "Reliability: 20%", a pressure alert multiplying by a constant. Now a number is either computed from rows with its window named, or it isn't printed. Four vanity metrics were retired.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs audited against the code&lt;/strong&gt;, citing files and symbols, with the command that produces any countable claim instead of the number. Numbers decay; commands don't.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;February me built a chatbot with tools. The OS taught me to run it like infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Known bugs (dmesg doesn't lie)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Found this week:&lt;/strong&gt; past the $5 limit, the moved-to-Groq turn ran without syscalls and once promised to check my calendar without doing it. The visible-note mechanism caught it; fix in progress.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routing is the weakest link.&lt;/strong&gt; A complex dispatch once misrouted into the email worker and never completed. Mitigated, not solved.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The whole auth model reduces to Telegram account security.&lt;/strong&gt; One messaging account holds every approval. Named plainly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's a second job.&lt;/strong&gt; The gardener, the dreaming pass, the nightly reflection are maintenance-avoidance mechanisms — which tells you the maintenance load is real.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The laptop as the first full device body. DeepSeek per-role characterization before anything else moves. Scheduled jobs onto local models, one verified at a time. Standing priority since July: fewer new syscalls, more proof the existing ones deserve trust.&lt;/p&gt;




&lt;p&gt;It started in February as frustration with assistants that forgot everything and couldn't act. It became an operating system — kernel, syscalls, scheduler, memory management, permissions, drivers — that happens to run on a language model. That's the interesting part. Not the AI. The OS.&lt;/p&gt;

&lt;p&gt;Not the MongoDB one.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I write about building in public: personal AI systems, Rust forensics tooling, and open-source devtools. More at fahadbilal.com.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>node</category>
      <category>oracle</category>
      <category>agenticai</category>
    </item>
    <item>
      <title>Export ChatGPT, Claude, Gemini, Grok, DeepSeek, Kimi, and Qwen chats to Markdown with Convolvger 0.6.0</title>
      <dc:creator>Fahad Bilal Saleem</dc:creator>
      <pubDate>Fri, 02 Oct 2026 13:34:45 +0000</pubDate>
      <link>https://dev.to/fahadbilalsaleem/export-chatgpt-claude-gemini-grok-deepseek-kimi-and-qwen-chats-to-markdown-with-convolvger-56ie</link>
      <guid>https://dev.to/fahadbilalsaleem/export-chatgpt-claude-gemini-grok-deepseek-kimi-and-qwen-chats-to-markdown-with-convolvger-56ie</guid>
      <description>&lt;p&gt;If you have ever tried to export a ChatGPT conversation to Markdown, or save a Claude chat as a .md file, you already know the options are bad. Copy-paste destroys the formatting. Screenshots are not text. And most "exporter" browser extensions want your login cookies, which is a hard no from me.&lt;/p&gt;

&lt;p&gt;So I built Convolvger. It is a Python CLI that takes a public AI chat share link and turns it into a clean Markdown file, plus a full-fidelity JSON archive for safekeeping. No browser automation, no cookies, no API keys. It talks to each provider's own JSON endpoint directly.&lt;br&gt;
Version 0.6.0 is out now, and it adds DeepSeek, Kimi, and Qwen. That brings the total to seven providers: ChatGPT, Claude, Gemini, Grok, DeepSeek, Kimi, and Qwen.&lt;/p&gt;

&lt;p&gt;How to export a ChatGPT chat to Markdown&lt;br&gt;
This is the simplest case. Paste the share link, run one command:&lt;br&gt;
pip install convolvger&lt;br&gt;
convolvger export &lt;br&gt;
You get a readable .md file and a JSON archive with everything the share carried. That is the whole flow for ChatGPT, Gemini, and Grok.&lt;/p&gt;

&lt;p&gt;How to save a Claude conversation as Markdown?&lt;br&gt;
Claude is the stubborn one. Its share page refuses non-browser clients no matter what headers you send. A lot of tools get around this by impersonating a browser. I did not want to do that.&lt;br&gt;
Instead, convolvger export --capture waits for your own browser. You open the share link yourself, a small bookmarklet hands the snapshot to a listener running on loopback, and the listener accepts it only when the browser's origin matches. Nothing is impersonated and nothing leaves your machine. The output is the same: clean Markdown plus the JSON archive.&lt;/p&gt;

&lt;p&gt;What is new in 0.6.0?&lt;/p&gt;

&lt;p&gt;Three new providers, each with their own quirks:&lt;br&gt;
DeepSeek, Its share page blocks non-browser clients with a 403 from the CDN. But the JSON endpoint behind the share page serves fine. I verified this against a real browser's network traffic and checked robots.txt before shipping it. I am mentioning this explicitly because "working around a block" is the kind of thing that should be done in the open.&lt;br&gt;
Kimi, Accepts kimi.ai, kimi.com, and the older kimi.moonshot.cn. Same share, three domains.&lt;br&gt;
Qwen, Accepts chat.qwen.ai and chat.qwenlm.ai, and ignores the ?fev= query string some share links carry.&lt;/p&gt;

&lt;p&gt;A few details that apply across the new providers. DeepSeek and Qwen use inline citation markers in their Markdown. Convolvger only strips those markers out when they resolve to a search result the share actually carries, and never inside code blocks. The JSON archive keeps the served text exactly as-is either way. Reasoning traces (Kimi, Qwen) and sharer identity stay in the JSON archive and never reach the Markdown. And the weekly contract check now covers all three new providers, each tested against a throwaway share, so upstream format changes get caught early.&lt;/p&gt;

&lt;p&gt;Why not just copy-paste?&lt;/p&gt;

&lt;p&gt;Because copy-paste silently loses content and you never find out. Every gap Convolvger hits during extraction gets recorded as a structured finding instead of being dropped quietly, and convolvger verify checks an archive's integrity afterward. If something is missing from your export, you will know about it. That is the entire point of the tool: an archive you cannot verify is not an archive.&lt;/p&gt;

&lt;p&gt;The boring fixes in 0.6.0 that matter for real archives&lt;br&gt;
A conversation titled in Arabic, Chinese, Hindi, or Russian now gets a filename in that script, instead of every non-Latin title from one provider colliding on a single file.&lt;br&gt;
A default filename is never silently replaced. The next export gets -2, -3, and so on, in any language.&lt;/p&gt;

&lt;p&gt;export -o - and inspect write UTF-8 regardless of the system's encoding, so they no longer crash on a legacy Windows terminal.&lt;br&gt;
A half-truncated emoji (cut off by a truncated reply) becomes U+FFFD and gets reported, instead of crashing the export and leaving an empty file behind.&lt;/p&gt;

&lt;p&gt;A 141-phrase, 138-language, 62-script corpus now runs through every provider on every release. Multilingual bugs are real and this catches them.&lt;/p&gt;

&lt;p&gt;Try it&lt;br&gt;
pip install convolvger&lt;br&gt;
GitHub: &lt;a href="https://github.com/bilalmughal1/convolvger" rel="noopener noreferrer"&gt;https://github.com/bilalmughal1/convolvger&lt;/a&gt;&lt;br&gt;
PyPI: &lt;a href="https://pypi.org/project/convolvger/" rel="noopener noreferrer"&gt;https://pypi.org/project/convolvger/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One honest note: share links rot. Providers change formats and delete old shares. If there is a conversation you care about, archive it now rather than later.&lt;/p&gt;

&lt;p&gt;Which provider or export format should I add next? I read every comment.&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>opensource</category>
      <category>cli</category>
    </item>
    <item>
      <title>Convolvger 0.5.0: archive your AI conversations locally — ChatGPT, Claude, Gemini, and now Grok</title>
      <dc:creator>Fahad Bilal Saleem</dc:creator>
      <pubDate>Sun, 27 Sep 2026 10:40:35 +0000</pubDate>
      <link>https://dev.to/fahadbilalsaleem/convolvger-050-archive-your-ai-conversations-locally-chatgpt-claude-gemini-and-now-grok-3o81</link>
      <guid>https://dev.to/fahadbilalsaleem/convolvger-050-archive-your-ai-conversations-locally-chatgpt-claude-gemini-and-now-grok-3o81</guid>
      <description>&lt;p&gt;Every AI provider lets you share a conversation with a link. None of them lets you keep it. Share links rot, pages get redesigned, providers quietly change what a URL serves. Convolvger is a small CLI that takes a public share URL and archives the conversation into Markdown you can read and JSON you can verify — on your machine, with no account, no telemetry, and no LLM involved.&lt;/p&gt;

&lt;p&gt;0.5.0 adds Grok to the lineup. The supported providers are now ChatGPT, Claude, Gemini, and Grok.&lt;/p&gt;

&lt;p&gt;Each provider is deceptive in its own way&lt;br&gt;
ChatGPT. The share snapshot is served as a turbo-stream that Convolvger decodes directly. And snapshots move: fetching the same share link eight hours apart once returned the same 31 message IDs with four assistant messages silently re-typed. That is why every archive records when it was retrieved.&lt;/p&gt;

&lt;p&gt;Claude. The share page cannot be fetched — the service refuses non-browser clients whatever headers they send. Rather than impersonate a browser, Convolvger waits for yours: convolvger bookmarklet prints a bookmarklet, you click it on the share page, and the snapshot is handed to a listener on loopback (127.0.0.1, one snapshot, three-minute timeout).&lt;/p&gt;

&lt;p&gt;Gemini. The share page carries no conversation at all — it is an application shell whose only prose is Google's marketing examples. A plain scrape gives you a plausible archive of the wrong conversation. Convolvger queries the same endpoint the web UI asks, sending only the single necessary query parameter, under its own User-Agent. It handles all three link forms Google issues and catches deleted shares, which Google quietly returns as 200 OK with a null payload.&lt;/p&gt;

&lt;p&gt;Grok — new in 0.5.0. Same app-shell shape: the page loads its conversation as JSON afterwards, so Convolvger asks that endpoint directly. No browser, no cookie, no token. The share id is kept whole whatever its prefix. Citations arrive as inline markup and are lifted out of the text — the message exactly as served stays in the JSON. The sender arrived as human, ASSISTANT, and assistant within one conversation, and is kept as-served. The reasoning trace is kept whole but reported as unmodelled (seen in only one conversation so far). Files a response names but doesn't carry are reported as withheld; nothing is fetched to fill the gap. A missing share is reported whether the provider answers 404, 400, or 200 with a title and no messages — the last seen on a real public share.&lt;/p&gt;

&lt;p&gt;The rules it holds to&lt;br&gt;
Everything runs locally. convolvger --version answers fully offline, and there is no update check — a test fails the build if the tool ever tries to contact an index about itself.&lt;br&gt;
It never impersonates a browser and never dereferences a URL it archives.&lt;br&gt;
Every archive records its schema version, its retrieval time, and every extraction finding. convolvger verify reports an archive's integrity without re-fetching anything.&lt;br&gt;
Content this version cannot model is flagged, never silently dropped.&lt;br&gt;
A weekly scheduled job queries each live provider in its own job, so an upstream format shift breaks in CI — naming the provider that changed — before it reaches your machine.&lt;br&gt;
Also in 0.5.0&lt;br&gt;
A capture-port bug on Windows is fixed, and the test suite now runs on Windows in CI as well as Linux.&lt;br&gt;
Try it&lt;br&gt;
bash&lt;/p&gt;

&lt;p&gt;pip install convolvger   # or: uv tool install convolvger / pipx install convolvger&lt;br&gt;
convolvger export &lt;a href="https://grok.com/share/SHARE_ID" rel="noopener noreferrer"&gt;https://grok.com/share/SHARE_ID&lt;/a&gt;&lt;br&gt;
convolvger export &lt;a href="https://gemini.google.com/share/SHARE_ID" rel="noopener noreferrer"&gt;https://gemini.google.com/share/SHARE_ID&lt;/a&gt;&lt;br&gt;
convolvger inspect &lt;a href="https://chatgpt.com/share/SHARE_ID" rel="noopener noreferrer"&gt;https://chatgpt.com/share/SHARE_ID&lt;/a&gt;  # look without saving&lt;br&gt;
convolvger verify mychat.json                          # check an archive&lt;br&gt;
Needs Python 3.12+. MIT licensed. GitHub · PyPI&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>opensource</category>
      <category>community</category>
    </item>
    <item>
      <title>Taphonomy: FAT32 file recovery that refuses to guess</title>
      <dc:creator>Fahad Bilal Saleem</dc:creator>
      <pubDate>Fri, 25 Sep 2026 16:32:32 +0000</pubDate>
      <link>https://dev.to/fahadbilalsaleem/taphonomy-fat32-file-recovery-that-refuses-to-guess-16l2</link>
      <guid>https://dev.to/fahadbilalsaleem/taphonomy-fat32-file-recovery-that-refuses-to-guess-16l2</guid>
      <description>&lt;p&gt;I built Taphonomy, a deleted-file recovery tool for FAT32 disk images written in Rust: &lt;a href="https://github.com/bilalmughal1/taphonomy" rel="noopener noreferrer"&gt;https://github.com/bilalmughal1/taphonomy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It recovers deleted files and files orphaned by a quick format. Evidence is opened read-only and every byte is SHA-256-hashed before anything is reported.&lt;/p&gt;

&lt;p&gt;The design rule: most recovery tools silently return plausible-looking bytes. Taphonomy treats "plausible but wrong" as a failure, not a partial success. Every recovery carries a caveat stating exactly what is and isn't established, and it refuses recoveries it can't support instead of guessing. It also reports its own coverage — every partition, directory, or listing it did not analyse is counted and named.&lt;/p&gt;

&lt;p&gt;Validation: I ran it against three of NIST's CFReDS deleted-file-recovery images, checking each recovery against the sectors NIST documents, and compared side-by-side with The Sleuth Kit 4.12.1. On dfr-01 and dfr-11, every recovery matched NIST's sectors. On dfr-02 — a file fragmented around a live file — Taphonomy refused, because the implied run crosses a cluster still in use. TSK recovered it correctly; its heuristic happened to land on the right one. 4 of 15 deleted files reached; 10 sit on FAT12/16 partitions not yet supported.&lt;/p&gt;

&lt;p&gt;How it's built: every capability starts as an Architecture Decision Record (17 so far); experiments record the hypothesis before the measurement, including wrong predictions; all test fixtures are generated from standard tools, byte-identical on every build, digests committed.&lt;/p&gt;

&lt;p&gt;Limitations: FAT32 only, disk images (not devices), MBR/512-byte sectors, 8.3 filenames. GPL-3.0.&lt;/p&gt;

&lt;p&gt;Where would you draw the line between a defensible recovery and a guess?&lt;/p&gt;

</description>
      <category>rust</category>
      <category>forensics</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
