<?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: Ayush Pandey</title>
    <description>The latest articles on DEV Community by Ayush Pandey (@ayush_77).</description>
    <link>https://dev.to/ayush_77</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%2F492401%2F9f0de5ef-6687-4b30-ac65-5e31bedbb745.jpeg</url>
      <title>DEV Community: Ayush Pandey</title>
      <link>https://dev.to/ayush_77</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ayush_77"/>
    <language>en</language>
    <item>
      <title>ofrenda</title>
      <dc:creator>Ayush Pandey</dc:creator>
      <pubDate>Sat, 31 Oct 2026 06:46:00 +0000</pubDate>
      <link>https://dev.to/ayush_77/ofrenda-4opf</link>
      <guid>https://dev.to/ayush_77/ofrenda-4opf</guid>
      <description>&lt;p&gt;An altar for everything that died on your machine.&lt;/p&gt;

&lt;p&gt;ofrenda finds the real deaths on your computer this week (OOM kills, crashed services, dead containers, app crash reports, or fatal lines in any log), asks a local open-weight model to write each one a short calavera literaria (the wry Mexican epitaph tradition) and one practical offering (the fix that would keep the next one alive), then builds a terminal altar and a single-file HTML ofrenda. Taller candle, longer life.&lt;/p&gt;

&lt;p&gt;Built for the DEV Hacktoberfest Open-Source AI Challenge, Week 4: Ghost in the Machine.&lt;/p&gt;

&lt;p&gt;Quick start&lt;/p&gt;

&lt;p&gt;Needs Python 3.9+ and Ollama. No pip packages.&lt;/p&gt;

&lt;p&gt;bash&lt;br&gt;
ollama pull gemma3:4b          # any Ollama model works; Gemma is the default&lt;br&gt;
git clone &lt;a href="https://github.com/Ayush7-BIT/ofrenda" rel="noopener noreferrer"&gt;https://github.com/Ayush7-BIT/ofrenda&lt;/a&gt; &amp;amp;&amp;amp; cd ofrenda&lt;br&gt;
python3 ofrenda.py --demo      # made-up deaths, so you can see it work anywhere&lt;br&gt;
python3 ofrenda.py             # the real ones, last 7 days&lt;br&gt;
open ofrenda.html              # xdg-open on Linux&lt;/p&gt;

&lt;p&gt;No model handy? python3 ofrenda.py --demo --no-llm uses plain template epitaphs.&lt;/p&gt;

&lt;p&gt;Where the dead come from&lt;br&gt;
Source  Reads   Works on&lt;br&gt;
Docker  exited containers with a non-zero code: exit code, OOMKilled, start and finish times, last log lines    anywhere Docker runs&lt;br&gt;
systemd systemctl --failed, plus the unit's last journal lines  Linux&lt;br&gt;
Kernel OOM  journalctl -k (or dmesg) lines for "Out of memory: Killed process"  Linux (may need the adm group or root)&lt;br&gt;
Crash reports   ~/Library/Logs/DiagnosticReports/*.ips and *.crash: exception type, signal, launch and crash time   macOS&lt;br&gt;
Any log --logfile PATH (repeatable): lines that look like a death (OOM, segfault, panic, fatal, non-zero exit)  anywhere&lt;/p&gt;

&lt;p&gt;Copy a log off a server and scan it offline: ssh prod 'journalctl -k --since "7 days ago"' &amp;gt; kernel.log, then python3 ofrenda.py --logfile kernel.log.&lt;/p&gt;

&lt;p&gt;Privacy&lt;/p&gt;

&lt;p&gt;Logs are the most sensitive text a machine produces. So:&lt;/p&gt;

&lt;p&gt;Inference runs through Ollama on localhost. Nothing is sent anywhere unless you set OLLAMA_HOST to another host (the HTML footer says so when you do).&lt;br&gt;
Before the model sees anything, secrets are scrubbed: AWS keys, JWTs, token=/password=-style pairs, emails, IPv4 addresses, and your home directory. Turn it off with --no-redact.&lt;br&gt;
Control characters are stripped from every log line, so a hostile log cannot write escape codes to your terminal. All text in the HTML is escaped.&lt;br&gt;
The model gets only the facts for one process at a time: name, how long it lived, how it died, and up to three last lines.&lt;br&gt;
Options&lt;br&gt;
Flag    Meaning&lt;br&gt;
--days N    how far back to look (default 7)&lt;br&gt;
--max N most souls to honor (default 8)&lt;br&gt;
--logfile PATH  also scan this log (repeatable)&lt;br&gt;
--demo  use made-up deaths&lt;br&gt;
--html FILE where to write the altar (default ofrenda.html)&lt;br&gt;
--model NAME    any Ollama model; or set OFRENDA_MODEL&lt;br&gt;
--no-llm    template epitaphs, no model&lt;br&gt;
--no-redact do not scrub secrets, IPs and emails&lt;br&gt;
How it works&lt;br&gt;
Each collector turns a death into a Dead record: name, kind, cause, how long it lived, when it died, last words.&lt;br&gt;
The record is scrubbed and sent to the model with a system prompt that allows only the facts given, and a JSON schema (epitaph, offering) passed through Ollama's structured-output format option. That is what keeps a 4B model from rambling.&lt;br&gt;
The HTML renderer draws one candle per process. Candle height is 26 + 38 * log10(1 + minutes_lived) pixels, capped; a dashed stub means the lifespan was never recorded.&lt;br&gt;
Limits&lt;br&gt;
Small models sometimes write lines that do not rhyme, or add a fifth line. The facts are still right, because the prompt forbids inventing any.&lt;br&gt;
The model only sees what is in the logs. If a cause of death is unclear, the offering says what to check first rather than guessing.&lt;br&gt;
The first call fails fast with a clear message if Ollama is not running or the model is not pulled.&lt;br&gt;
Tested on&lt;/p&gt;

&lt;p&gt;Fill in before publishing: OS, Python version, Ollama version, model, which sources actually found deaths.&lt;/p&gt;

&lt;p&gt;Timeline&lt;/p&gt;

&lt;p&gt;First commit: 31 October 2026, inside the challenge window. Any commit after the deadline will be listed here.&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>ai</category>
      <category>hackathon</category>
    </item>
  </channel>
</rss>
