<?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: FireXCore</title>
    <description>The latest articles on DEV Community by FireXCore (@firexcore).</description>
    <link>https://dev.to/firexcore</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%2F3391534%2Fb80ffd49-3bc1-4beb-9c34-b9e53c14297c.png</url>
      <title>DEV Community: FireXCore</title>
      <link>https://dev.to/firexcore</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/firexcore"/>
    <language>en</language>
    <item>
      <title>Building an Evidence-First Email Archiver for Gmail and IMAP with Python</title>
      <dc:creator>FireXCore</dc:creator>
      <pubDate>Mon, 13 Jul 2026 11:16:47 +0000</pubDate>
      <link>https://dev.to/firexcore/building-an-evidence-first-email-archiver-for-gmail-and-imap-with-python-209n</link>
      <guid>https://dev.to/firexcore/building-an-evidence-first-email-archiver-for-gmail-and-imap-with-python-209n</guid>
      <description>&lt;p&gt;Email archiving looks simple until the archive needs to answer a real question.&lt;/p&gt;

&lt;p&gt;Downloading attachments is easy. Preserving enough context to prove &lt;strong&gt;where a file came from, which message contained it, who sent it, how it appeared in the mailbox, whether the same bytes appeared elsewhere, and whether the archive is still intact&lt;/strong&gt; is a different problem.&lt;/p&gt;

&lt;p&gt;That is the problem I set out to solve with &lt;strong&gt;FireXCore MailVault&lt;/strong&gt;, a read-only, open-source email evidence archiver written in Python.&lt;/p&gt;

&lt;p&gt;MailVault connects to Gmail or a standards-compatible IMAP server, preserves complete messages as immutable raw EML objects, stores MIME payloads by SHA-256 content identity, records provenance in SQLite, and generates traceable manifests for downstream analysis.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/FireXCore" rel="noopener noreferrer"&gt;
        FireXCore
      &lt;/a&gt; / &lt;a href="https://github.com/FireXCore/mailvault" rel="noopener noreferrer"&gt;
        mailvault
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A provider-neutral, read-only email evidence archiver. MailVault acquires complete messages via IMAP, preserves immutable raw EML objects, records every MIME part and mailbox occurrence, deduplicates attachment content by SHA-256, and produces traceable manifests for analytics, eDiscovery, migration staging, and procurement intelligence. Apache-2.0
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/FireXCore/mailvault/docs/assets/banner.svg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FFireXCore%2Fmailvault%2FHEAD%2Fdocs%2Fassets%2Fbanner.svg" alt="FireXCore MailVault" width="100%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://github.com/FireXCore/mailvault/actions/workflows/ci.yml" rel="noopener noreferrer"&gt;&lt;img alt="Continuous integration" src="https://camo.githubusercontent.com/8c44a227759485adb6849c2a12c11f900a1acb091a9cfd021a5ba86f7f5222e9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f4669726558436f72652f6d61696c7661756c742f63692e796d6c3f6272616e63683d6d61696e266c6162656c3d4349"&gt;&lt;/a&gt;
  &lt;a href="https://www.python.org/" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Python 3.12 or newer" src="https://camo.githubusercontent.com/4f04660470b7eef8d1310fa0fac14736bfc8c3012145dd6c13aaec1b04f67afa/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507974686f6e2d332e31322532422d314533413546"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/FireXCore/mailvault/LICENSE" rel="noopener noreferrer"&gt;&lt;img alt="Apache License 2.0" src="https://camo.githubusercontent.com/adfdaf2bbf9b27cd63d5d3b9249a6a26e081ace145e0537ae7ae6e44fbbf3cd1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4170616368652d2d322e302d324237413738"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/FireXCore/mailvault/security" rel="noopener noreferrer"&gt;&lt;img alt="Security policy" src="https://camo.githubusercontent.com/ffdcc9d5f5e0082dd2a8a7710a79a5b1e91e3f8660588a3692a7ac61ce14411c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53656375726974792d706f6c6963792d354237303841"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://github.com/FireXCore/mailvault/docs/README.fa.md" rel="noopener noreferrer"&gt;راهنمای فارسی&lt;/a&gt; ·
  &lt;a href="https://github.com/FireXCore/mailvault/docs/GETTING_STARTED.md" rel="noopener noreferrer"&gt;Getting started&lt;/a&gt; ·
  &lt;a href="https://github.com/FireXCore/mailvault/docs/ARCHITECTURE.md" rel="noopener noreferrer"&gt;Architecture&lt;/a&gt; ·
  &lt;a href="https://github.com/FireXCore/mailvault/docs/PROCUREMENT_READINESS.md" rel="noopener noreferrer"&gt;Procurement readiness&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;FireXCore MailVault is a provider-neutral, read-only email evidence archiver. It acquires complete messages through IMAP, preserves immutable raw EML objects, records every MIME part and mailbox occurrence, deduplicates attachment content by SHA-256, and produces traceable manifests for analytics, eDiscovery, migration staging, and procurement intelligence.&lt;/p&gt;

&lt;p&gt;MailVault is not an attachment downloader. The canonical unit is the complete email message, including headers, bodies, MIME structure, inline resources, nested messages, signatures, encrypted containers, attachment occurrences, provider identifiers, mailbox identifiers, labels, flags, and timestamps.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Project status&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;MailVault is in public beta. The archive model and read-only acquisition guarantees are stable. Provider adapters beyond Gmail and generic IMAP, including OAuth-based Microsoft 365 and JMAP, are planned as separate milestones.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Design objectives&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Preserve raw evidence before deriving metadata.&lt;/li&gt;
&lt;li&gt;Keep provider-specific behavior outside the archive domain.&lt;/li&gt;
&lt;li&gt;Use stable provider identifiers where available and standards-based fallbacks elsewhere.&lt;/li&gt;
&lt;li&gt;Store…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/FireXCore/mailvault" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This article explains the engineering decisions behind it, the problems that appeared when real-world email data met Python's email parser, and what a resumable evidence-first archive looks like in practice.&lt;/p&gt;
&lt;h2&gt;
  
  
  The real problem is provenance, not file downloading
&lt;/h2&gt;

&lt;p&gt;A basic attachment downloader usually produces something like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;downloads/
├── invoice.pdf
├── quotation.xlsx
├── technical-drawing.pdf
└── invoice-2.pdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That is useful until someone asks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which email contained &lt;code&gt;invoice.pdf&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Was it attached or embedded inline?&lt;/li&gt;
&lt;li&gt;Who sent it, and to whom?&lt;/li&gt;
&lt;li&gt;Which thread did it belong to?&lt;/li&gt;
&lt;li&gt;Did the same bytes appear under another filename?&lt;/li&gt;
&lt;li&gt;Was the message in Inbox, All Mail, Spam, or Trash?&lt;/li&gt;
&lt;li&gt;Can an extracted price be traced to an exact message and MIME part?&lt;/li&gt;
&lt;li&gt;Has the file changed since it was archived?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A filename cannot answer those questions.&lt;/p&gt;

&lt;p&gt;The complete message must remain the primary evidence object. Attachments are only parts of that object.&lt;/p&gt;

&lt;h2&gt;
  
  
  The design goals
&lt;/h2&gt;

&lt;p&gt;I defined a few non-negotiable properties before writing the archive engine.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The mailbox must remain unchanged
&lt;/h3&gt;

&lt;p&gt;An archive tool should not mark messages as read, move them, change labels, or delete anything.&lt;/p&gt;

&lt;p&gt;MailVault uses read-only mailbox selection and fetches complete messages using non-mutating IMAP operations such as &lt;code&gt;BODY.PEEK[]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The archive core intentionally has no operation for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deleting messages;&lt;/li&gt;
&lt;li&gt;moving or copying messages;&lt;/li&gt;
&lt;li&gt;appending mail;&lt;/li&gt;
&lt;li&gt;changing flags;&lt;/li&gt;
&lt;li&gt;changing Gmail labels;&lt;/li&gt;
&lt;li&gt;sending messages.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps acquisition separate from mailbox administration.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Raw evidence must be preserved before parsing
&lt;/h3&gt;

&lt;p&gt;Email is messy input.&lt;/p&gt;

&lt;p&gt;A message may contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;malformed headers;&lt;/li&gt;
&lt;li&gt;invalid Unicode;&lt;/li&gt;
&lt;li&gt;broken encoded words;&lt;/li&gt;
&lt;li&gt;unusual address groups;&lt;/li&gt;
&lt;li&gt;duplicate filenames;&lt;/li&gt;
&lt;li&gt;nested messages;&lt;/li&gt;
&lt;li&gt;encrypted MIME containers;&lt;/li&gt;
&lt;li&gt;TNEF payloads;&lt;/li&gt;
&lt;li&gt;digital signatures;&lt;/li&gt;
&lt;li&gt;incorrect content types.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If parsing fails, the original bytes are still valuable.&lt;/p&gt;

&lt;p&gt;MailVault therefore stores the complete raw EML object before relying on derived interpretation. Metadata can be repaired or regenerated later; the canonical source remains unchanged.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Content identity must not depend on filenames
&lt;/h3&gt;

&lt;p&gt;Two different files can have the same filename.&lt;/p&gt;

&lt;p&gt;The same file can also appear under several filenames.&lt;/p&gt;

&lt;p&gt;MailVault stores retained non-body MIME payloads in a content-addressed object store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;objects/
└── blobs/
    └── sha256/
        └── ab/
            └── cd/
                └── abcdef...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The SHA-256 digest becomes the canonical content identity.&lt;/p&gt;

&lt;p&gt;The original filename is preserved as metadata for each occurrence, but it does not control the storage path.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Deduplication must not destroy history
&lt;/h3&gt;

&lt;p&gt;Suppose the same PDF appears:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;in an original supplier quotation;&lt;/li&gt;
&lt;li&gt;in a forwarded message;&lt;/li&gt;
&lt;li&gt;in a later approval thread;&lt;/li&gt;
&lt;li&gt;under two different filenames.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The bytes should be stored once, but all four occurrences should remain queryable.&lt;/p&gt;

&lt;p&gt;That means the model needs to distinguish between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a unique blob;&lt;/li&gt;
&lt;li&gt;a MIME-part occurrence;&lt;/li&gt;
&lt;li&gt;a canonical message;&lt;/li&gt;
&lt;li&gt;a mailbox occurrence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deduplication is a storage optimization, not a reason to collapse provenance.&lt;/p&gt;
&lt;h2&gt;
  
  
  The archive architecture
&lt;/h2&gt;

&lt;p&gt;At a high level, the pipeline looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Gmail / IMAP
      |
      v
Capability negotiation
      |
      v
Metadata-first discovery
      |
      v
Read-only raw message fetch
      |
      +----------------------+
      |                      |
      v                      v
Immutable raw EML      MIME-part parsing
      |                      |
      |                      v
      |               SHA-256 blob store
      |                      |
      +----------+-----------+
                 |
                 v
          SQLite metadata
                 |
                 v
 JSONL manifests / reports / views
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The archive is divided into four concerns.&lt;/p&gt;
&lt;h2&gt;
  
  
  Read-only provider acquisition
&lt;/h2&gt;

&lt;p&gt;Provider behavior is isolated behind profiles.&lt;/p&gt;

&lt;p&gt;The Gmail profile can retain provider-specific context such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gmail message identity;&lt;/li&gt;
&lt;li&gt;Gmail thread identity;&lt;/li&gt;
&lt;li&gt;Gmail labels;&lt;/li&gt;
&lt;li&gt;Gmail raw-search behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The generic IMAP profile relies on portable concepts such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mailbox name;&lt;/li&gt;
&lt;li&gt;UID;&lt;/li&gt;
&lt;li&gt;UIDVALIDITY;&lt;/li&gt;
&lt;li&gt;flags;&lt;/li&gt;
&lt;li&gt;RFC message headers;&lt;/li&gt;
&lt;li&gt;advertised server capabilities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation matters because Gmail is not just a traditional folder-based mailbox. One canonical message may appear through several labels without becoming several independent messages.&lt;/p&gt;
&lt;h2&gt;
  
  
  Canonical message versus mailbox occurrence
&lt;/h2&gt;

&lt;p&gt;This distinction became central to the data model.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;canonical message&lt;/strong&gt; represents the evidence object itself:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;canonical message
├── raw EML SHA-256
├── provider message identity
├── RFC Message-ID
├── normalized participants
└── immutable object path
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A &lt;strong&gt;mailbox occurrence&lt;/strong&gt; represents where that message appeared:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mailbox occurrence
├── mailbox or Gmail label
├── UID
├── UIDVALIDITY
├── flags
└── provider context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Treating these as separate records prevents double-counting and keeps the model useful for both Gmail and conventional IMAP servers.&lt;/p&gt;
&lt;h2&gt;
  
  
  Metadata-first, resumable synchronization
&lt;/h2&gt;

&lt;p&gt;Large mailboxes should not require a single uninterrupted process.&lt;/p&gt;

&lt;p&gt;MailVault first discovers metadata, stores stable identities, and then archives pending raw messages in bounded batches.&lt;/p&gt;

&lt;p&gt;Operational state includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;checkpoints;&lt;/li&gt;
&lt;li&gt;run records;&lt;/li&gt;
&lt;li&gt;retry state;&lt;/li&gt;
&lt;li&gt;a single-run lock;&lt;/li&gt;
&lt;li&gt;rolling bandwidth accounting;&lt;/li&gt;
&lt;li&gt;archived-object status.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A configured soft cap pauses the run cleanly. Re-running the same command against the same destination resumes from persisted state.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;mailvault&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;gmail.com&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;imap.gmail.com&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--provider&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;gmail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--auth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;app-password&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--destination&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;E:\MailVault&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--scope&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--soft-cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2GiB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--hard-cap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2.25GiB&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A paused run is not a failed run. It means the engine reached an operator-defined transfer boundary and preserved enough state to continue safely later.&lt;/p&gt;
&lt;h2&gt;
  
  
  What happened with real-world email
&lt;/h2&gt;

&lt;p&gt;Synthetic MIME fixtures are useful, but production mailboxes expose much stranger input.&lt;/p&gt;

&lt;p&gt;Two failures were especially instructive.&lt;/p&gt;
&lt;h3&gt;
  
  
  Invalid Unicode surrogates
&lt;/h3&gt;

&lt;p&gt;Some old or malformed metadata contained surrogate code points that could not be encoded as UTF-8:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UnicodeEncodeError:
'utf-8' codec can't encode characters:
surrogates not allowed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The correct response was not to rewrite the raw EML.&lt;/p&gt;

&lt;p&gt;Instead, MailVault now keeps canonical bytes untouched and sanitizes only derived text fields before they enter SQLite, JSON, JSONL, or logs.&lt;/p&gt;
&lt;h3&gt;
  
  
  Malformed address groups
&lt;/h3&gt;

&lt;p&gt;Python's structured header parser encountered a malformed &lt;code&gt;To&lt;/code&gt; header and failed inside &lt;code&gt;email.headerregistry&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AttributeError:
'Group' object has no attribute 'local_part'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A single broken historical address header should not stop an entire archive.&lt;/p&gt;

&lt;p&gt;The metadata path was changed to use a more tolerant parsing strategy for hostile address headers while preserving the raw header bytes in the original message.&lt;/p&gt;

&lt;p&gt;The general lesson was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An evidence archiver must be more tolerant of source defects than the systems that originally produced the data.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  A live archive run
&lt;/h2&gt;

&lt;p&gt;One live Gmail archive produced these intermediate statistics before the configured rolling bandwidth cap paused the run:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Messages                   3,250
Raw Messages               2,312
Raw Bytes          2,151,518,027
Occurrences                3,250
Parts                      8,172
Blobs                      2,526
Blob Bytes         1,097,947,979
Duplicate Part Occurrences 1,378
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A few observations:&lt;/p&gt;
&lt;h3&gt;
  
  
  Raw storage is expected to be larger than the downloaded attachment total
&lt;/h3&gt;

&lt;p&gt;An attachment is retained inside the raw EML, often Base64-encoded, and also stored as a decoded blob for direct access and content-addressed deduplication.&lt;/p&gt;

&lt;p&gt;That is intentional. The raw message is evidence; the decoded blob is a usable derived object.&lt;/p&gt;
&lt;h3&gt;
  
  
  The deduplication count is meaningful
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;1,378&lt;/code&gt; duplicate part occurrences means the same blob bytes appeared multiple times, but only one canonical blob object was required for each unique SHA-256 digest.&lt;/p&gt;

&lt;p&gt;The occurrence relationships were still preserved.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pausing proved the resume model
&lt;/h3&gt;

&lt;p&gt;The run reached its rolling 24-hour soft cap with zero processing errors.&lt;/p&gt;

&lt;p&gt;A second invocation immediately paused with zero new bytes because the previous transfer was still inside the bandwidth window. This is the expected behavior of a persistent rolling ledger, not a stalled downloader.&lt;/p&gt;
&lt;h2&gt;
  
  
  Archive layout
&lt;/h2&gt;

&lt;p&gt;A MailVault destination looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MailVault/
├── objects/
│   ├── raw/sha256/          # immutable raw EML
│   └── blobs/sha256/        # content-addressed MIME payloads
├── metadata/messages/       # derived message JSON
├── database/
│   └── mailvault.sqlite3
├── manifests/
│   ├── messages.jsonl
│   ├── message_occurrences.jsonl
│   ├── message_parts.jsonl
│   ├── blobs.jsonl
│   └── procurement_sources.jsonl
├── state/                   # checkpoints, locks, bandwidth ledger
├── reports/
├── logs/
└── views/                   # disposable navigation pointers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The canonical archive is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;immutable objects;&lt;/li&gt;
&lt;li&gt;the relational metadata database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Manifests, reports, per-message JSON, and navigation views are reproducible outputs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;MailVault requires Python 3.12 or newer.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/FireXCore/mailvault.git
&lt;span class="nb"&gt;cd &lt;/span&gt;mailvault
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Using &lt;code&gt;pipx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pipx &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or with a virtual environment:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Windows PowerShell:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\.venv\Scripts\Activate.ps1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--upgrade&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pip&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Linux or macOS:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--upgrade&lt;/span&gt; pip
python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Verify the installed version:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mailvault version
python &lt;span class="nt"&gt;-m&lt;/span&gt; firexcore_mailvault version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Both commands should report the same package version.&lt;/p&gt;
&lt;h2&gt;
  
  
  Validate the mailbox first
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;doctor&lt;/code&gt; command tests TLS, authentication, capabilities, provider behavior, and mailbox discovery before a full archive begins.&lt;/p&gt;

&lt;p&gt;For Gmail:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;mailvault&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;doctor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;gmail.com&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;imap.gmail.com&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--provider&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;gmail&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--auth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;app-password&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The App Password is entered through a hidden prompt. It should never be included directly in the command, committed to Git, or written into a shared configuration file.&lt;/p&gt;
&lt;h2&gt;
  
  
  Inspect and verify an archive
&lt;/h2&gt;

&lt;p&gt;Archive statistics:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;mailvault&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--destination&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;E:\MailVault&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--account&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;gmail.com&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Integrity verification:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;mailvault&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;verify&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--destination&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;E:\MailVault&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;--sample&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The verifier checks stored sizes, expected objects, and SHA-256 identity.&lt;/p&gt;
&lt;h2&gt;
  
  
  Security boundaries
&lt;/h2&gt;

&lt;p&gt;MailVault deliberately does not try to solve every email-security problem.&lt;/p&gt;

&lt;p&gt;It does not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;execute attachments;&lt;/li&gt;
&lt;li&gt;render untrusted HTML;&lt;/li&gt;
&lt;li&gt;claim to be a malware sandbox;&lt;/li&gt;
&lt;li&gt;decrypt arbitrary protected documents;&lt;/li&gt;
&lt;li&gt;provide legal-hold certification;&lt;/li&gt;
&lt;li&gt;replace enterprise journaling;&lt;/li&gt;
&lt;li&gt;infer business facts inside the archive core.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The archive itself may contain sensitive information. Operators still need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;encrypted storage;&lt;/li&gt;
&lt;li&gt;restricted filesystem permissions;&lt;/li&gt;
&lt;li&gt;protected backups;&lt;/li&gt;
&lt;li&gt;retention rules;&lt;/li&gt;
&lt;li&gt;access reviews;&lt;/li&gt;
&lt;li&gt;legal authorization to collect the mailbox.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open-source code does not remove the need for operational governance.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why procurement evidence influenced the design
&lt;/h2&gt;

&lt;p&gt;The original use case involved procurement communication.&lt;/p&gt;

&lt;p&gt;A later analytics system may need to extract:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;supplier identity;&lt;/li&gt;
&lt;li&gt;RFQ and quotation relationships;&lt;/li&gt;
&lt;li&gt;price, currency, quantity, and validity;&lt;/li&gt;
&lt;li&gt;freight, payment terms, and Incoterms;&lt;/li&gt;
&lt;li&gt;requested versus offered part numbers;&lt;/li&gt;
&lt;li&gt;technical substitutions;&lt;/li&gt;
&lt;li&gt;delivery promises;&lt;/li&gt;
&lt;li&gt;approval or rejection history.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those facts should not be produced as detached text.&lt;/p&gt;

&lt;p&gt;A trustworthy extraction record needs an evidence anchor:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;derived fact
├── canonical message ID
├── MIME part path
├── blob SHA-256
├── source filename
├── extractor version
├── confidence
└── exact citation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That is why MailVault stops at evidence preservation and source-manifest generation. Business interpretation belongs in a separate, versioned layer.&lt;/p&gt;
&lt;h2&gt;
  
  
  Current status and roadmap
&lt;/h2&gt;

&lt;p&gt;The current public release supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gmail through IMAP and App Password authentication;&lt;/li&gt;
&lt;li&gt;generic standards-compatible IMAP;&lt;/li&gt;
&lt;li&gt;metadata-first discovery;&lt;/li&gt;
&lt;li&gt;resumable raw EML acquisition;&lt;/li&gt;
&lt;li&gt;MIME-part preservation;&lt;/li&gt;
&lt;li&gt;SHA-256 content-addressed blobs;&lt;/li&gt;
&lt;li&gt;SQLite provenance;&lt;/li&gt;
&lt;li&gt;JSONL exports;&lt;/li&gt;
&lt;li&gt;archive statistics and verification;&lt;/li&gt;
&lt;li&gt;Windows, Linux, and macOS CI smoke tests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Planned provider work includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OAuth-based authentication;&lt;/li&gt;
&lt;li&gt;Microsoft 365 integration;&lt;/li&gt;
&lt;li&gt;JMAP support;&lt;/li&gt;
&lt;li&gt;additional evidence export formats.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Lessons from building it
&lt;/h2&gt;

&lt;p&gt;A few principles became clearer during implementation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Store source bytes before trusting a parser.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Treat email as hostile input.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Separate canonical identity from mailbox occurrence.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deduplicate content, not history.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Make interruption an expected operating state.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keep provider behavior behind explicit adapters.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Do not let derived convenience overwrite source truth.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verification is part of archival, not an optional extra.&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Try it, inspect it, or challenge the design
&lt;/h2&gt;

&lt;p&gt;MailVault is open source under Apache License 2.0.&lt;/p&gt;

&lt;p&gt;The repository includes the source code, tests, architecture decisions, archive format, security model, operations guide, troubleshooting documentation, and contribution workflow.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/FireXCore" rel="noopener noreferrer"&gt;
        FireXCore
      &lt;/a&gt; / &lt;a href="https://github.com/FireXCore/mailvault" rel="noopener noreferrer"&gt;
        mailvault
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A provider-neutral, read-only email evidence archiver. MailVault acquires complete messages via IMAP, preserves immutable raw EML objects, records every MIME part and mailbox occurrence, deduplicates attachment content by SHA-256, and produces traceable manifests for analytics, eDiscovery, migration staging, and procurement intelligence. Apache-2.0
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/FireXCore/mailvault/docs/assets/banner.svg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FFireXCore%2Fmailvault%2FHEAD%2Fdocs%2Fassets%2Fbanner.svg" alt="FireXCore MailVault" width="100%"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;a href="https://github.com/FireXCore/mailvault/actions/workflows/ci.yml" rel="noopener noreferrer"&gt;&lt;img alt="Continuous integration" src="https://camo.githubusercontent.com/8c44a227759485adb6849c2a12c11f900a1acb091a9cfd021a5ba86f7f5222e9/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f4669726558436f72652f6d61696c7661756c742f63692e796d6c3f6272616e63683d6d61696e266c6162656c3d4349"&gt;&lt;/a&gt;
  &lt;a href="https://www.python.org/" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Python 3.12 or newer" src="https://camo.githubusercontent.com/4f04660470b7eef8d1310fa0fac14736bfc8c3012145dd6c13aaec1b04f67afa/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f507974686f6e2d332e31322532422d314533413546"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/FireXCore/mailvault/LICENSE" rel="noopener noreferrer"&gt;&lt;img alt="Apache License 2.0" src="https://camo.githubusercontent.com/adfdaf2bbf9b27cd63d5d3b9249a6a26e081ace145e0537ae7ae6e44fbbf3cd1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4170616368652d2d322e302d324237413738"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/FireXCore/mailvault/security" rel="noopener noreferrer"&gt;&lt;img alt="Security policy" src="https://camo.githubusercontent.com/ffdcc9d5f5e0082dd2a8a7710a79a5b1e91e3f8660588a3692a7ac61ce14411c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53656375726974792d706f6c6963792d354237303841"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
  &lt;a href="https://github.com/FireXCore/mailvault/docs/README.fa.md" rel="noopener noreferrer"&gt;راهنمای فارسی&lt;/a&gt; ·
  &lt;a href="https://github.com/FireXCore/mailvault/docs/GETTING_STARTED.md" rel="noopener noreferrer"&gt;Getting started&lt;/a&gt; ·
  &lt;a href="https://github.com/FireXCore/mailvault/docs/ARCHITECTURE.md" rel="noopener noreferrer"&gt;Architecture&lt;/a&gt; ·
  &lt;a href="https://github.com/FireXCore/mailvault/docs/PROCUREMENT_READINESS.md" rel="noopener noreferrer"&gt;Procurement readiness&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;FireXCore MailVault is a provider-neutral, read-only email evidence archiver. It acquires complete messages through IMAP, preserves immutable raw EML objects, records every MIME part and mailbox occurrence, deduplicates attachment content by SHA-256, and produces traceable manifests for analytics, eDiscovery, migration staging, and procurement intelligence.&lt;/p&gt;
&lt;p&gt;MailVault is not an attachment downloader. The canonical unit is the complete email message, including headers, bodies, MIME structure, inline resources, nested messages, signatures, encrypted containers, attachment occurrences, provider identifiers, mailbox identifiers, labels, flags, and timestamps.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Project status&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;MailVault is in public beta. The archive model and read-only acquisition guarantees are stable. Provider adapters beyond Gmail and generic IMAP, including OAuth-based Microsoft 365 and JMAP, are planned as separate milestones.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Design objectives&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Preserve raw evidence before deriving metadata.&lt;/li&gt;
&lt;li&gt;Keep provider-specific behavior outside the archive domain.&lt;/li&gt;
&lt;li&gt;Use stable provider identifiers where available and standards-based fallbacks elsewhere.&lt;/li&gt;
&lt;li&gt;Store…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/FireXCore/mailvault" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I would especially value review from developers who have worked with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hostile or malformed MIME;&lt;/li&gt;
&lt;li&gt;long-running IMAP synchronization;&lt;/li&gt;
&lt;li&gt;digital evidence systems;&lt;/li&gt;
&lt;li&gt;eDiscovery pipelines;&lt;/li&gt;
&lt;li&gt;records management;&lt;/li&gt;
&lt;li&gt;procurement document intelligence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The original version of this article is published on the &lt;a href="https://firexcore.com/blog/mailvault-open-source-email-archiving/" rel="noopener noreferrer"&gt;FireXCore blog&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Editorial note: This article was drafted with AI assistance and reviewed by the project author against the source code, CI results, and live MailVault archive output before publication.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>security</category>
      <category>showdev</category>
    </item>
    <item>
      <title>🚀 NPM-GitNameCheck: Instantly Check NPM Package Names &amp; GitHub Usernames</title>
      <dc:creator>FireXCore</dc:creator>
      <pubDate>Sat, 08 Nov 2025 10:03:27 +0000</pubDate>
      <link>https://dev.to/firexcore/npm-gitnamecheck-instantly-check-npm-package-names-github-usernames-1l5a</link>
      <guid>https://dev.to/firexcore/npm-gitnamecheck-instantly-check-npm-package-names-github-usernames-1l5a</guid>
      <description>&lt;p&gt;
  &lt;a href="https://www.npmjs.com/package/npm-gitnamecheck" rel="noopener noreferrer"&gt;
    &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fnpm%2Fv%2Fnpm-gitnamecheck%3Fcolor%3D00ff9d%26label%3Dnpm%2520package%26style%3Dfor-the-badge" alt="NPM package badge — NPM package name checker" width="178" height="28"&gt;
  &lt;/a&gt;
  &lt;a href="https://github.com/FireXCore/npm-gitnamecheck" rel="noopener noreferrer"&gt;
    &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fgithub%2Fstars%2FFireXCore%2Fnpm-gitnamecheck%3Fstyle%3Dfor-the-badge%26color%3D0d0d0d" alt="GitHub stars — GitHub name availability checker" width="95" height="28"&gt;
  &lt;/a&gt;
  &lt;a href="https://github.com/FireXCore/npm-gitnamecheck/blob/main/LICENSE" rel="noopener noreferrer"&gt;
    &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Fbadge%2FLicense-MIT-yellow.svg%3Fstyle%3Dfor-the-badge" alt="MIT License" width="124" height="28"&gt;
  &lt;/a&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Focus keyword:&lt;/strong&gt; &lt;code&gt;NPM package name checker&lt;/code&gt; — this article shows how to use &lt;strong&gt;NPM-GitNameCheck&lt;/strong&gt; (CLI + library) to verify NPM package name availability and GitHub username/repo availability quickly, reliably, and in bulk.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;If you need an &lt;strong&gt;NPM package name checker&lt;/strong&gt; that also validates GitHub usernames and repositories, &lt;code&gt;NPM-GitNameCheck&lt;/code&gt; is a CLI tool and Node library built for speed and auditability. It outputs &lt;code&gt;TXT&lt;/code&gt;, &lt;code&gt;JSON&lt;/code&gt;, and &lt;code&gt;CSV&lt;/code&gt; reports, supports GitHub tokens for higher rate limits, and includes concurrency + retry logic to handle large lists.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why run an NPM package name checker?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Avoid brand collision&lt;/strong&gt;: You don't want to publish a package with a name someone else owns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent cross-platform branding&lt;/strong&gt;: Make sure your package name matches your GitHub username or organization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automate naming checks&lt;/strong&gt;: Manual checking is slow and error-prone; integrate checks into CI/CD.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auditability&lt;/strong&gt;: Keep CSV/JSON logs for proof your team checked names before launch.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Key features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Checks &lt;strong&gt;NPM registry&lt;/strong&gt; for package availability&lt;/li&gt;
&lt;li&gt;Validates &lt;strong&gt;GitHub usernames&lt;/strong&gt; and &lt;strong&gt;repositories&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Outputs &lt;code&gt;free-names.txt&lt;/code&gt;, &lt;code&gt;free-names.json&lt;/code&gt;, and &lt;code&gt;names-report.csv&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Concurrency control, retries, exponential backoff, and jitter&lt;/li&gt;
&lt;li&gt;Supports &lt;strong&gt;GitHub tokens&lt;/strong&gt; and proxies&lt;/li&gt;
&lt;li&gt;DNS-compliant name validation&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Global (recommended)&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; npm-gitnamecheck

&lt;span class="c"&gt;# Or as a local dependency&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;npm-gitnamecheck
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Quick start (example)
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;wordlist.txt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;myapp
cool-toolkit
brandx
superlib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx npm-gitnamecheck wordlist.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outputs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;free-names.txt&lt;/code&gt; — a newline-separated list of available names&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;free-names.json&lt;/code&gt; — structured output with timestamps and services checked&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;names-report.csv&lt;/code&gt; — detailed log for auditing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sample &lt;code&gt;free-names.json&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"myapp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"when"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-11-08T20:30:45.123Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"services"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"npm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"github:user"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Advanced usage
&lt;/h2&gt;

&lt;p&gt;Use more concurrency and a GitHub token for higher throughput:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm-gitnamecheck wordlist.txt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--concurrency&lt;/span&gt; 30 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--retries&lt;/span&gt; 5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--github-token&lt;/span&gt; ghp_yourtokenhere &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--out&lt;/span&gt; ./results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Notes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Without a token, GitHub limits you to 60 requests/hour (IP-based). With a token, limits jump to 5,000/hour per token.&lt;/li&gt;
&lt;li&gt;Be conservative with concurrency and use jitter/backoff to avoid being blocked.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Programmatic API (Node.js)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;checkName&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;npm-gitnamecheck&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;checkName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myapp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;githubToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GH_TOKEN&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Available!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Taken:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;details&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets you integrate the &lt;code&gt;NPM package name checker&lt;/code&gt; directly into scripts, build pipelines, or web UIs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best practices &amp;amp; pitfalls
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Use a GitHub token for bulk checks.&lt;/strong&gt; Don’t rely on anonymous requests for lists &amp;gt; 100 names.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Respect API terms and rate limits.&lt;/strong&gt; Aggressive scraping will get your IP or token blocked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate names first.&lt;/strong&gt; Filter out invalid DNS names before checking to save requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache results.&lt;/strong&gt; If your CI checks the same list repeatedly, cache verified results to avoid waste.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log everything.&lt;/strong&gt; Keep CSV results in your repo or artifacts for compliance and postmortems.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Example CI job snippet (GitHub Actions)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name-check&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;check-names&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Node&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install tool&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install -g npm-gitnamecheck&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run name checker&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GH_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GH_TOKEN }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx npm-gitnamecheck wordlist.txt --github-token $GH_TOKEN --out ./name-check-results&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload artifact&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;name-check-results&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./name-check-results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Where to go from here
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fork the repo and open issues: &lt;a href="https://github.com/FireXCore/npm-gitnamecheck" rel="noopener noreferrer"&gt;https://github.com/FireXCore/npm-gitnamecheck&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Want PyPI, Docker Hub, or social handle checks? Add these as feature requests or PRs.&lt;/li&gt;
&lt;li&gt;Add progress bars, resume capabilities, or a GUI wrapper if you need desktop-friendly UX.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Closing / CTA
&lt;/h2&gt;

&lt;p&gt;If you publish an NPM package or maintain open-source projects, integrate an &lt;strong&gt;NPM package name checker&lt;/strong&gt; like &lt;code&gt;NPM-GitNameCheck&lt;/code&gt; into your workflow &lt;strong&gt;before&lt;/strong&gt; your launch checklist. It’s a tiny step that prevents a massive brand headache later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it now:&lt;/strong&gt; &lt;code&gt;npx npm-gitnamecheck wordlist.txt&lt;/code&gt; — then open &lt;code&gt;names-report.csv&lt;/code&gt; and see the audit trail.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Author: Farbod Akvan — Full-Stack Developer &amp;amp; Open-Source Creator&lt;/em&gt;&lt;br&gt;
Published by &lt;strong&gt;FireXCore&lt;/strong&gt; • &lt;a href="https://github.com/FireXCore/npm-gitnamecheck" rel="noopener noreferrer"&gt;https://github.com/FireXCore/npm-gitnamecheck&lt;/a&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>npm</category>
      <category>javascript</category>
      <category>cli</category>
    </item>
    <item>
      <title>🔥 CascadeX – Smart CSS Optimization for Modern Developers</title>
      <dc:creator>FireXCore</dc:creator>
      <pubDate>Mon, 04 Aug 2025 04:48:19 +0000</pubDate>
      <link>https://dev.to/firexcore/cascadex-smart-css-optimization-for-modern-developers-4kb6</link>
      <guid>https://dev.to/firexcore/cascadex-smart-css-optimization-for-modern-developers-4kb6</guid>
      <description>&lt;p&gt;Is your CSS bloated with duplicates, messy selectors, or outdated styles?&lt;br&gt;&lt;br&gt;
Say hello to &lt;strong&gt;&lt;a href="https://cascadex.firexcore.com" rel="noopener noreferrer"&gt;CascadeX&lt;/a&gt;&lt;/strong&gt; — a smart, blazing-fast CSS optimizer built for developers who care about performance and clean code.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ What is CascadeX?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CascadeX&lt;/strong&gt; is a free web-based tool that automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🧹 Removes duplicate CSS selectors
&lt;/li&gt;
&lt;li&gt;🧠 Merges matching declarations
&lt;/li&gt;
&lt;li&gt;🧪 Lets you preview changes before applying
&lt;/li&gt;
&lt;li&gt;📉 Minimizes file size while keeping styles intact
&lt;/li&gt;
&lt;li&gt;🔐 Works 100% locally in your browser (no upload required)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you're working on a legacy project or a sleek new UI, CascadeX helps you clean your stylesheets without the risk of breaking layouts.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Key Features
&lt;/h2&gt;

&lt;p&gt;✅ Easy-to-use, no installation needed&lt;br&gt;&lt;br&gt;
✅ Works with large and complex CSS files&lt;br&gt;&lt;br&gt;
✅ Smart merging of duplicate rules&lt;br&gt;&lt;br&gt;
✅ Real-time output preview&lt;br&gt;&lt;br&gt;
✅ Built by &lt;a href="https://firexcore.com" rel="noopener noreferrer"&gt;FireXCore&lt;/a&gt; for modern dev teams&lt;/p&gt;




&lt;h2&gt;
  
  
  💻 Try it now
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://cascadex.firexcore.com" rel="noopener noreferrer"&gt;https://cascadex.firexcore.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Just paste your CSS and hit &lt;strong&gt;Optimize&lt;/strong&gt;. You'll instantly see a cleaner, smaller version of your stylesheet.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧬 Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Before */&lt;/span&gt;
&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
`&lt;/p&gt;

&lt;p&gt;⬇️&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;css&lt;br&gt;
/* After CascadeX Optimization */&lt;br&gt;
.card {&lt;br&gt;
  background: white;&lt;br&gt;
  padding: 20px;&lt;br&gt;
  border-radius: 10px;&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Why It Matters
&lt;/h2&gt;

&lt;p&gt;Optimized CSS improves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Page load speed&lt;/li&gt;
&lt;li&gt;Code maintainability&lt;/li&gt;
&lt;li&gt;Readability and collaboration&lt;/li&gt;
&lt;li&gt;Overall UX performance&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💬 Contribute or Share Feedback
&lt;/h2&gt;

&lt;p&gt;We're actively improving CascadeX and welcome your feedback!&lt;br&gt;
📩 Contact us via &lt;a href="https://firexcore.com/contact" rel="noopener noreferrer"&gt;FireXCore.com&lt;/a&gt; or share suggestions/issues directly from the site.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 About FireXCore
&lt;/h2&gt;

&lt;p&gt;We're a team focused on building high-performance tools for developers and enterprises.&lt;br&gt;
From cybersecurity to smart automation — CascadeX is one of many tools designed to simplify your workflow.&lt;/p&gt;




&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://cascadex.firexcore.com" rel="noopener noreferrer"&gt;Use CascadeX Now →&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
Cleaner CSS. Faster websites. Smarter development.&lt;/p&gt;

</description>
      <category>css</category>
      <category>opensource</category>
      <category>tools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>🧱 Building a Modular ERP System with Laravel 10</title>
      <dc:creator>FireXCore</dc:creator>
      <pubDate>Sun, 03 Aug 2025 04:50:49 +0000</pubDate>
      <link>https://dev.to/firexcore/building-a-modular-erp-system-with-laravel-10-1joc</link>
      <guid>https://dev.to/firexcore/building-a-modular-erp-system-with-laravel-10-1joc</guid>
      <description>&lt;p&gt;In a recent project, I refactored a custom ERP system that had grown over two years. It was time to clean up the monolithic structure and prepare it for scale. Here's how I redesigned the architecture using a &lt;strong&gt;modular approach with Laravel 10&lt;/strong&gt; and &lt;strong&gt;PHP 8.2&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 Why Refactor?
&lt;/h2&gt;

&lt;p&gt;As more features were added—purchase inquiries, document management, RFQ workflows, role permissions—the codebase started feeling heavy. Controllers became bloated. Files were scattered. We needed a better way to &lt;strong&gt;scale without chaos&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Solution: Modular Architecture
&lt;/h2&gt;

&lt;p&gt;I used &lt;a href="https://github.com/nWidart/laravel-modules" rel="noopener noreferrer"&gt;nWidart/laravel-modules&lt;/a&gt;, a well-maintained package that enables Laravel to support modular structure out of the box.&lt;/p&gt;

&lt;p&gt;Each feature was moved into its own module:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Inquiry&lt;/code&gt; module – manages purchase requests and workflows
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Document&lt;/code&gt; module – handles categorized file uploads (tech, inquiry, PO, etc.)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RFQ&lt;/code&gt; modules – separate for Sales and Procurement
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;User &amp;amp; Roles&lt;/code&gt; module – integrated with Spatie Permissions
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🛠️ Key Tools &amp;amp; Techniques
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Service-Repository Pattern&lt;/strong&gt; for separation of concerns
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swagger/OpenAPI&lt;/strong&gt; for documenting each module's API
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Laravel Sanctum&lt;/strong&gt; for secure authentication
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spatie MediaLibrary&lt;/strong&gt; for handling file uploads
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom Middleware&lt;/strong&gt; for module-based permissions
&lt;/li&gt;
&lt;li&gt;Database migrations scoped per module&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📈 What Changed?
&lt;/h2&gt;

&lt;p&gt;After refactoring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The codebase became &lt;strong&gt;easier to test and extend&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Teams could work in parallel on isolated modules
&lt;/li&gt;
&lt;li&gt;Adding new features doesn’t require editing 10 unrelated files
&lt;/li&gt;
&lt;li&gt;CI/CD pipeline was adjusted to test modules independently&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💬 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;If you’re building a long-term Laravel project with growing complexity, &lt;strong&gt;don’t wait too long to go modular&lt;/strong&gt;. It’s an upfront effort, but it pays off as your system scales.&lt;/p&gt;

&lt;p&gt;Let me know if you'd like me to share a sample structure or even turn this into a starter template. Always happy to contribute back to the community.&lt;/p&gt;




</description>
      <category>laravel</category>
      <category>backend</category>
      <category>architecture</category>
      <category>php</category>
    </item>
    <item>
      <title>5 AI Tools I Wish I’d Had as a Developer — Now in 2025</title>
      <dc:creator>FireXCore</dc:creator>
      <pubDate>Mon, 28 Jul 2025 09:47:27 +0000</pubDate>
      <link>https://dev.to/firexcore/5-ai-tools-i-wish-id-had-as-a-developer-now-in-2025-37mm</link>
      <guid>https://dev.to/firexcore/5-ai-tools-i-wish-id-had-as-a-developer-now-in-2025-37mm</guid>
      <description>&lt;h1&gt;
  
  
  🧠 5 AI Tools I Wish I’d Had as a Developer — Now in 2025
&lt;/h1&gt;

&lt;p&gt;AI coding assistants aren’t new — but in 2025, they’ve transformed from clever autocomplete plugins into full-scale developer agents.&lt;br&gt;&lt;br&gt;
According to a survey by Jellyfish, &lt;strong&gt;90% of engineering teams&lt;/strong&gt; now use at least one AI coding tool, and nearly half use &lt;strong&gt;two or more&lt;/strong&gt; simultaneously — often Copilot plus Cursor or Gemini Code Assist.&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.businessinsider.com/ai-coding-tools-popular-github-gemini-code-assist-cursor-q-2025-7?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Source »&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  1. GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;Still the most mainstream choice, used by &lt;strong&gt;42% of developers&lt;/strong&gt;, Copilot has evolved into a full agent with deep GitHub integration.&lt;/p&gt;

&lt;p&gt;✅ Supports multiple models: GPT‑4o, Claude, Gemini&lt;br&gt;&lt;br&gt;
✅ Integrates with: VS Code, Visual Studio, JetBrains, Neovim&lt;br&gt;&lt;br&gt;
✅ Offers suggestions, test generation, inline docs, and refactors&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/GitHub_Copilot?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;🔗 Learn more&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Google Gemini Code Assist / “Jules” Agent
&lt;/h2&gt;

&lt;p&gt;Unveiled at Google I/O Connect India 2025, Gemini Code Assist introduces a dev agent named &lt;em&gt;Jules&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;✅ Automatically fixes bugs, writes PRs&lt;br&gt;&lt;br&gt;
✅ Works well with Firebase Studio &amp;amp; cloud workflows&lt;br&gt;&lt;br&gt;
✅ Designed to reduce repetitive dev tasks&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.theverge.com/2024/12/11/24318628/jules-google-ai-coding-agent-gemini-2-0-announcement?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;🔗 The Verge coverage&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Cursor + Bugbot
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cursor&lt;/strong&gt; is an AI-first IDE built on VS Code, and now includes &lt;strong&gt;Bugbot&lt;/strong&gt;, a debugging agent.&lt;/p&gt;

&lt;p&gt;✅ Understands full codebases and supports multi-step queries&lt;br&gt;&lt;br&gt;
✅ Bugbot catches logic and security flaws caused by LLMs&lt;br&gt;&lt;br&gt;
✅ Cursor 1.0 released June 2025 (Windows, macOS, Linux)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Cursor_%28code_editor%29?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;🔗 Learn more&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.wired.com/story/cursor-releases-new-ai-tool-for-debugging-code?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;🔗 Bugbot announcement (Wired)&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Claude 4 (Opus &amp;amp; Sonnet)
&lt;/h2&gt;

&lt;p&gt;Anthropic’s latest model line is currently &lt;strong&gt;the strongest coding LLM&lt;/strong&gt; available.&lt;/p&gt;

&lt;p&gt;✅ Claude Opus 4 outperforms GPT‑4.1 and Gemini 2.5 in SWE-bench&lt;br&gt;&lt;br&gt;
✅ Autonomous agents can reason for up to &lt;strong&gt;7+ hours&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✅ Sonnet 4 is a cheaper, slightly lighter alternative&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Claude_%28language_model%29?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;🔗 Claude Wiki&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Tabnine &amp;amp; Amazon Q (formerly CodeWhisperer)
&lt;/h2&gt;

&lt;p&gt;Both lightweight alternatives with strong adoption among enterprise teams.&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Tabnine&lt;/strong&gt;: Fast, context-aware, simple&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Amazon Q&lt;/strong&gt;: Secure enterprise integration with AWS stack&lt;br&gt;&lt;br&gt;
✅ Often used as Copilot complements&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Tabnine?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;🔗 Tabnine&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.designgurus.io/blog/10-best-ai-tools-for-developers-in-2025?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;🔗 Amazon Q comparison&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ Why These Tools Matter
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GitHub Copilot&lt;/td&gt;
&lt;td&gt;Fast coding, inline docs, refactoring&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini Code Assist (Jules)&lt;/td&gt;
&lt;td&gt;Automated bug fixing, PR generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cursor + Bugbot&lt;/td&gt;
&lt;td&gt;IDE-level refactoring + error catching&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude 4&lt;/td&gt;
&lt;td&gt;Autonomous planning &amp;amp; long tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tabnine / Amazon Q&lt;/td&gt;
&lt;td&gt;Lightweight, private coding assistant&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;According to TechRadar, mid‑2025 marks a generational shift — tools now automate &lt;strong&gt;entire SDLC pipelines&lt;/strong&gt;, not just snippets.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠ A Reality Check
&lt;/h2&gt;

&lt;p&gt;A 2025 randomized control study of open-source developers found:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;While devs &lt;strong&gt;felt&lt;/strong&gt; AI made them 20% faster, they actually took &lt;strong&gt;19% longer&lt;/strong&gt; to solve tasks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Intentional use is key.&lt;br&gt;&lt;br&gt;
&lt;a href="https://arxiv.org/abs/2507.09089?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;🔗 Full study (arXiv)&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ What I Recommend
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Goal&lt;/th&gt;
&lt;th&gt;Recommended Tool&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fast code generation&lt;/td&gt;
&lt;td&gt;GitHub Copilot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Debugging &amp;amp; preventing AI faults&lt;/td&gt;
&lt;td&gt;Cursor + Bugbot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intelligent agents for planning&lt;/td&gt;
&lt;td&gt;Gemini Code Assist / Jules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Autonomous long-running tasks&lt;/td&gt;
&lt;td&gt;Claude Opus 4 or Sonnet 4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lightweight coding assistance&lt;/td&gt;
&lt;td&gt;Tabnine or Amazon Q&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  💬 Let’s Chat
&lt;/h2&gt;

&lt;p&gt;At &lt;strong&gt;FireXCore&lt;/strong&gt;, we build developer-centric AI tools like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DevLog AI&lt;/code&gt; — automatic coding activity logger
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Smart AutoCSS&lt;/code&gt; — one-click CSS cleanup tool
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SecureEdge&lt;/code&gt; — AI-assisted secure API gateway &lt;em&gt;(in dev)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🔗 &lt;a href="https://firexcore.com" rel="noopener noreferrer"&gt;firexcore.com&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Which AI tool has helped you most in 2025?&lt;br&gt;&lt;br&gt;
Drop a comment — or DM me if you're building something similar!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>developers</category>
      <category>firexcore</category>
    </item>
    <item>
      <title>I Built a One-Click VS Code Extension That Cleans Up Ugly CSS (Open Source)</title>
      <dc:creator>FireXCore</dc:creator>
      <pubDate>Sun, 27 Jul 2025 11:17:39 +0000</pubDate>
      <link>https://dev.to/firexcore/i-built-a-one-click-vs-code-extension-that-cleans-up-ugly-css-open-source-5cn8</link>
      <guid>https://dev.to/firexcore/i-built-a-one-click-vs-code-extension-that-cleans-up-ugly-css-open-source-5cn8</guid>
      <description>&lt;p&gt;`# I Built a One-Click VS Code Extension That Cleans Up Ugly CSS (Open Source)&lt;/p&gt;

&lt;p&gt;Hey Devs 👋&lt;/p&gt;

&lt;p&gt;You know that moment when you open a legacy &lt;code&gt;.css&lt;/code&gt; file and it hits you with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💀 3000+ lines of messy code
&lt;/li&gt;
&lt;li&gt;👻 duplicate properties
&lt;/li&gt;
&lt;li&gt;😩 inconsistent indentation
&lt;/li&gt;
&lt;li&gt;🤡 properties in random order
&lt;/li&gt;
&lt;li&gt;and a lot of &lt;code&gt;!important&lt;/code&gt; everywhere?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yeah. Same here.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://marketplace.visualstudio.com/items?itemName=FireXCore.smart-autocss" rel="noopener noreferrer"&gt;&lt;strong&gt;Smart AutoCSS&lt;/strong&gt;&lt;/a&gt; — a &lt;strong&gt;VS Code extension&lt;/strong&gt; that fixes all of it with just one click.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ What it does (in one click):
&lt;/h2&gt;

&lt;p&gt;✅ Auto-cleans indentation&lt;br&gt;&lt;br&gt;
✅ Removes duplicate properties&lt;br&gt;&lt;br&gt;
✅ Sorts CSS properties logically&lt;br&gt;&lt;br&gt;
✅ Works on &lt;code&gt;.css&lt;/code&gt; and &lt;code&gt;.scss&lt;/code&gt;&lt;br&gt;&lt;br&gt;
✅ No setup required — just right-click → "Smart AutoCSS"&lt;/p&gt;




&lt;h2&gt;
  
  
  📷 Before vs After
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`css&lt;br&gt;
/* Before */&lt;br&gt;
.btn  {color:#fff; background-color:#000;padding:10px;margin:0px;color:#fff;}&lt;/p&gt;

&lt;p&gt;/* After */&lt;br&gt;
.btn {&lt;br&gt;
  background-color: #000;&lt;br&gt;
  color: #fff;&lt;br&gt;
  margin: 0px;&lt;br&gt;
  padding: 10px;&lt;br&gt;
}&lt;br&gt;
`&lt;/p&gt;

</description>
      <category>css</category>
      <category>vscode</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
