<?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: 254 Stack</title>
    <description>The latest articles on DEV Community by 254 Stack (@254stack).</description>
    <link>https://dev.to/254stack</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%2F4070928%2Fccaba7ce-d935-40ac-aebf-1d322c5e84c2.png</url>
      <title>DEV Community: 254 Stack</title>
      <link>https://dev.to/254stack</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/254stack"/>
    <language>en</language>
    <item>
      <title>My first real terminal project - setting up Git and SSH as a complete beginner</title>
      <dc:creator>254 Stack</dc:creator>
      <pubDate>Sat, 29 Aug 2026 20:40:52 +0000</pubDate>
      <link>https://dev.to/254stack/my-first-real-terminal-project-setting-up-git-and-ssh-as-a-complete-beginner-hm6</link>
      <guid>https://dev.to/254stack/my-first-real-terminal-project-setting-up-git-and-ssh-as-a-complete-beginner-hm6</guid>
      <description>&lt;p&gt;I'm a student learning data analytics, working my way toward data engineering eventually. A few weeks ago, I started building out a proper Ubuntu setup for it — Python, Anaconda, Jupyter, the usual list you get told to install before you've written a single line of code. Git and GitHub were on that list too, and I figured it would be the easy part. Install it, connect it, move on to the actual data stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Doing all this on Ubuntu
&lt;/h2&gt;

&lt;p&gt;Quick note before I get into it: everything here happened on Ubuntu, using the built-in terminal. If you're on Windows or Mac, most of the concepts carry over, but some of the specific paths and package commands won't match exactly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait, what exactly is Git?
&lt;/h2&gt;

&lt;p&gt;Before touching any commands, I had to figure out what Git even was.&lt;/p&gt;

&lt;p&gt;Think about writing a big assignment in Google Docs. You make changes, your lecturer or a classmate suggests edits, you accept some and reject others, and at any point you can look back at the version history and see exactly what the document looked like yesterday, or roll back to before you deleted that one paragraph you actually needed. &lt;/p&gt;

&lt;p&gt;Git is that idea, but for code and data projects instead of documents, and it works even when nobody's connected to the internet at the moment they're making changes.&lt;/p&gt;

&lt;p&gt;Every time you save a "checkpoint" of your work (called a &lt;em&gt;commit&lt;/em&gt;), Git remembers exactly what changed, who changed it, and when. If you break something, you can go back to any earlier checkpoint. If two people are working on the same project, Git can combine both sets of changes instead of one person's work silently overwriting the other's. &lt;/p&gt;

&lt;p&gt;GitHub, then, is just a website that hosts a copy of that project online, so you and your classmates (or your future employer) can see it, download it, and contribute to it from anywhere.&lt;/p&gt;

&lt;p&gt;For someone studying to be a data analyst, this matters more than it might seem at first. Datasets and analysis scripts change constantly; you clean the data one way, then realize you need to redo it, then want to compare your old approach against the new one. Git is what makes that safe to do without ever losing earlier work. It's less "extra tool to learn" and more "safety net for every project you're about to start."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I even needed this
&lt;/h2&gt;

&lt;p&gt;Part of my coursework involves pushing projects to GitHub, and I already had two accounts sitting around: an old one I'd made last year ago and barely touched — I think I used it for one small project for a couple of days and then forgot about it — and a newer one I set up specifically for my current data analyst studies, which is the one that actually matters to me now. &lt;/p&gt;

&lt;p&gt;I didn't think having two accounts would be a problem. It became the entire problem. Let's talk about it, especially the mistakes I made while learning and implementing git at one sitting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistake #1: one lowercase letter took down the whole command
&lt;/h2&gt;

&lt;p&gt;The very first real command I typed was supposed to generate an SSH key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"your_email@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-t&lt;/code&gt; sets the type of key (Ed25519 is the modern default you're supposed to use), and &lt;code&gt;-C&lt;/code&gt; attaches a comment — usually your email — so you can tell your keys apart later if you ever have more than one.&lt;/p&gt;

&lt;p&gt;I typed &lt;code&gt;-c&lt;/code&gt; instead of &lt;code&gt;-C&lt;/code&gt;. As a total beginner, that felt like an insignificant difference. It is not. Ssh-keygen threw "Too many arguments" at me along with a wall of usage text that meant nothing to me at the time. &lt;/p&gt;

&lt;p&gt;It turns out lowercase &lt;code&gt;-c&lt;/code&gt; is an entirely different flag, used for editing the comment on a key that already exists, and it doesn't even work alongside &lt;code&gt;-t&lt;/code&gt;. Nobody warns you that the terminal treats uppercase and lowercase letters as completely different instructions. I do now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistake #2: GitHub told me my key was "already in use"
&lt;/h2&gt;

&lt;p&gt;Once I actually generated a key correctly, I copied the public half and pasted it into GitHub's "New SSH key" page. GitHub's response: &lt;strong&gt;"Key is already in use."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I assumed I had broken something. I hadn't. What actually happened is that a key already existed at the default location from an earlier attempt, and when ssh-keygen asked if I wanted to overwrite it, I said no without understanding what that choice actually meant. &lt;/p&gt;

&lt;p&gt;So it kept the old key instead of making a new one — and that old key was already sitting on my other, barely-used GitHub account from way back. I wasn't generating anything new; I was just re-pasting something that had already been claimed somewhere else.&lt;/p&gt;

&lt;p&gt;The actual fix was giving the new key its own filename instead of relying on the default path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"your_email@example.com"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/id_ed25519_github
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;-f&lt;/code&gt; flag turned out to matter a lot more than I expected. Without it, I kept colliding with whatever was already sitting at the default location.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistake #3: a space I couldn't even see
&lt;/h2&gt;

&lt;p&gt;This one is embarrassing in hindsight. Trying to load my new key into the agent, I typed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-add ~/.ssh/id_ed 25519_github
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's a space between &lt;code&gt;id_ed&lt;/code&gt; and &lt;code&gt;25519_github&lt;/code&gt; in there. I didn't notice it. The terminal doesn't interpret that as a typo — it reads it as two completely separate filenames, neither of which exists, and complains about both. &lt;/p&gt;

&lt;p&gt;As someone brand new to typing commands instead of clicking buttons, I hadn't yet learned to read my own input carefully before hitting enter. I now use Tab to auto-complete filenames specifically so this can't happen again.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mistake #4: copying the wrong file, three times in a row
&lt;/h2&gt;

&lt;p&gt;I was using &lt;code&gt;xclip&lt;/code&gt; to copy a key straight to my clipboard instead of manually highlighting text in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;xclip &lt;span class="nt"&gt;-sel&lt;/span&gt; clip &amp;lt; ~/.ssh/id_ed25519_github.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Except I ran this exact command pointed at the &lt;em&gt;old&lt;/em&gt; key file, three separate times, without catching it — because the two filenames only differed by one word, and I genuinely couldn't tell them apart at a glance yet. &lt;/p&gt;

&lt;p&gt;Every time I pasted into GitHub afterward, I was pasting the same already-claimed key from Mistake #2. &lt;/p&gt;

&lt;p&gt;If you're new to this too: when something you think you already fixed keeps failing in the exact same way, don't assume your approach is wrong. Check whether you actually did the thing you meant to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one that really got me: SSH was authenticating as the wrong account
&lt;/h2&gt;

&lt;p&gt;With a key finally added successfully, I ran the standard connection test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-T&lt;/span&gt; git@github.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And it replied with something like: &lt;strong&gt;"Hi [my old, barely-used account]!"&lt;/strong&gt; Not the account I actually wanted to use for my coursework.&lt;/p&gt;

&lt;p&gt;This is the part that no beginner guide had prepared me for. &lt;code&gt;ssh-agent&lt;/code&gt; holds onto every key you've loaded during your current terminal session, and when you connect to GitHub without telling it which one to use, it just offers them up one at a time until GitHub accepts one — whichever loads first wins, correct account or not. There's no warning. It just quietly logs you in as someone else. If I'd pushed a project right after that test, it would have gone up under the wrong identity with Git not batting an eye.&lt;/p&gt;

&lt;p&gt;The real fix is a config file at &lt;code&gt;~/.ssh/config&lt;/code&gt; that tells SSH exactly which key belongs to which account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ssh"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Old account&lt;/span&gt;
&lt;span class="k"&gt;Host&lt;/span&gt; github.com-old
    &lt;span class="k"&gt;HostName&lt;/span&gt; github.com
    &lt;span class="k"&gt;User&lt;/span&gt; git
    &lt;span class="k"&gt;IdentityFile&lt;/span&gt; ~/.ssh/id_ed25519
    &lt;span class="k"&gt;IdentitiesOnly&lt;/span&gt; &lt;span class="no"&gt;yes&lt;/span&gt;

&lt;span class="c1"&gt;# Current studies account&lt;/span&gt;
&lt;span class="k"&gt;Host&lt;/span&gt; github.com-studies
    &lt;span class="k"&gt;HostName&lt;/span&gt; github.com
    &lt;span class="k"&gt;User&lt;/span&gt; git
    &lt;span class="k"&gt;IdentityFile&lt;/span&gt; ~/.ssh/id_ed25519_github
    &lt;span class="k"&gt;IdentitiesOnly&lt;/span&gt; &lt;span class="no"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;IdentitiesOnly yes&lt;/code&gt; line isn't optional extra credit — without it, SSH goes right back to trying every key in the agent regardless of what you told it, which quietly undoes the entire point of setting this up. I left it out my first attempt and couldn't understand why nothing had changed.&lt;/p&gt;

&lt;p&gt;With that saved, testing each identity separately actually worked the way I expected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-T&lt;/span&gt; git@github.com-old
ssh &lt;span class="nt"&gt;-T&lt;/span&gt; git@github.com-studies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each one greeted me with the correct, matching username. First time that happened, I actually said "finally" out loud to an empty room.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing the repo I'd already cloned
&lt;/h2&gt;

&lt;p&gt;The config file only affects new connections going forward. A project I'd already cloned earlier was still pointed at a plain &lt;code&gt;github.com&lt;/code&gt; URL with no account attached to it at all. I checked it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and pointed it at the correct alias:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote set-url origin git@github.com-studies:username/repo-name.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same repo path, just swapping out the host for my new alias. Running &lt;code&gt;git fetch&lt;/code&gt; afterward confirmed it actually worked end-to-end, not just in theory.&lt;/p&gt;

&lt;h3&gt;
  
  
  The thing that still trips me up
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ssh-agent&lt;/code&gt; forgets everything the second I close the terminal or restart my laptop. The config file stays put, the keys stay on disk, but the agent itself resets constantly. So most sessions I still have to run:&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;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;ssh-agent &lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
ssh-add ~/.ssh/id_ed25519_github
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;before doing anything else. I don't love it, but at least now I understand &lt;em&gt;why&lt;/em&gt; it's asking again instead of assuming I broke something new.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd tell another beginner starting this today
&lt;/h2&gt;

&lt;p&gt;Read your own commands back before hitting enter, especially flag casing and filenames — your terminal will not guess what you meant. If an error repeats after you think you've fixed it, check whether you actually ran the fixed version, not just whether your reasoning was sound. &lt;/p&gt;

&lt;p&gt;And if you're a student like me juggling more than one GitHub account for different parts of your life, set up the &lt;code&gt;~/.ssh/config&lt;/code&gt; file &lt;em&gt;before&lt;/em&gt; you start pasting keys into GitHub, not after four rounds of confusion like I did.&lt;/p&gt;

&lt;p&gt;None of this was actually complicated once I understood what was happening underneath it. It just wasn't explained anywhere I looked as a total beginner — so hopefully now, for someone else starting exactly where I did, it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick reference, if you're doing this right now
&lt;/h2&gt;

&lt;p&gt;The commands I actually needed, in order, minus every detour above:&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="c"&gt;# 1. Generate a uniquely named key&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"your_email@example.com"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/id_ed25519_accountname

&lt;span class="c"&gt;# 2. View it so you can paste it into GitHub&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_ed25519_accountname.pub

&lt;span class="c"&gt;# 3. Load it into the agent (repeat after every reboot/new terminal)&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;ssh-agent &lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
ssh-add ~/.ssh/id_ed25519_accountname

&lt;span class="c"&gt;# 4. Add a matching Host block to ~/.ssh/config, then test it&lt;/span&gt;
ssh &lt;span class="nt"&gt;-T&lt;/span&gt; git@github.com-accountname

&lt;span class="c"&gt;# 5. Point any existing repo at the right alias&lt;/span&gt;
git remote set-url origin git@github.com-accountname:org-name/repo-name.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you only remember one thing from this: type slowly around flags and filenames, and set up your &lt;code&gt;~/.ssh/config&lt;/code&gt; aliases &lt;em&gt;before&lt;/em&gt; you have two accounts competing for the same terminal session. Future you — probably mid-assignment, on a deadline — will thank you for it.&lt;/p&gt;

&lt;p&gt;Go get Git!&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>github</category>
      <category>git</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Programmable business email infra for teams and AI agents</title>
      <dc:creator>254 Stack</dc:creator>
      <pubDate>Fri, 28 Aug 2026 09:14:29 +0000</pubDate>
      <link>https://dev.to/254stack/programmable-business-email-for-teams-and-ai-agents-3401</link>
      <guid>https://dev.to/254stack/programmable-business-email-for-teams-and-ai-agents-3401</guid>
      <description>&lt;p&gt;We've been rethinking business email for a while. I'm Stefan, and Chibu and I are building &lt;a href="https://venmail.io" rel="noopener noreferrer"&gt;Venmail&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Business email is needlessly expensive and fragmented. Per-seat pricing turns headcount into a tax. And even for teams fully on Gmail or Outlook, the tools that actually run the business around email — CRM, payments, prospecting, workflow automation — still live in a separate stack of subscriptions Google and Microsoft don't include.&lt;/p&gt;

&lt;p&gt;We started from a simple premise: email is business infrastructure, but it's still sold like per-user SaaS. So we rebuilt the underlying model around identities, storage, permissions, and usage instead of headcount. Email as a hub, not a silo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storage, not seats
&lt;/h2&gt;

&lt;p&gt;Venmail scales on storage, not headcount. Paid plans have no per-seat fees. Organizations can bring their own storage — S3, Azure Blob, or self-hosted — instead of storage we control on your behalf. A company with 10x the employees doesn't need 10x the infrastructure, so a five-person team and a fifty-person team on similar mail volume pay roughly the same.&lt;/p&gt;

&lt;p&gt;For a human team, that's a compliance and portability story: your mail data lives on infrastructure you already govern.&lt;/p&gt;

&lt;p&gt;Sending mail is a plain REST call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://m.venmail.io/api/v1/send/message &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Server-API-Key: YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "to": ["user@example.com"],
    "from": "hello@yourdomain.com",
    "subject": "Test email",
    "html_body": "&amp;lt;p&amp;gt;Hello from Venmail API!&amp;lt;/p&amp;gt;"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or with the Node/TypeScript SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @venmail/vsm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Then AI agents came along
&lt;/h2&gt;

&lt;p&gt;We didn't start with AI agents. We started with the idea that email should be infrastructure. Once we had an API-native email layer, giving agents their own identities and scoped access followed naturally.&lt;/p&gt;

&lt;p&gt;It's a bigger deal than it sounds. Machine and agent identities already outnumber human identities in the average enterprise by roughly 109 to 1 — up from 82 to 1 the year before — and agent-specific identities are projected to grow another 85% over the next twelve months (&lt;a href="https://www.paloaltonetworks.com/idira/idira-identity-security-landscape" rel="noopener noreferrer"&gt;Palo Alto Networks, 2026 Identity Security Landscape&lt;/a&gt;). Most of those agents are still getting access the same bad way: a shared OAuth grant, or someone's personal app password.&lt;/p&gt;

&lt;p&gt;An agent shouldn't need a human-style paid seat, and it shouldn't need to borrow a person's inbox. It should have its own identity, its own inbox, and permissions scoped to exactly what it does.&lt;/p&gt;

&lt;p&gt;So we built an agent API: dedicated inboxes, scoped tokens for read/send/reply, independent rotation and revocation, a full audit trail, and MCP support so Claude Desktop or Claude Code can use it as a tool directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;vvs&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;@venmail/vsm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Generate a keypair for the agent (once)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keyPair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vvs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateKeyPair&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  VVS-1: knowing which agent actually sent a message
&lt;/h2&gt;

&lt;p&gt;Email has no native way to verify that a message from &lt;code&gt;billing@yourcompany.com&lt;/code&gt; was actually sent by your billing agent, and not spoofed or tampered with in transit. DKIM proves the &lt;em&gt;domain&lt;/em&gt; sent it. It says nothing about which agent, script, or process behind that domain actually authored it.&lt;/p&gt;

&lt;p&gt;That's what &lt;strong&gt;VVS-1&lt;/strong&gt; (Venmail Verification Standard) is for — Ed25519 signatures, standard SMTP headers, and existing DNS/HTTPS infrastructure. It doesn't touch SMTP itself; it layers on top of delivery, so a receiver that doesn't support it just gets the message normally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sender side:&lt;/strong&gt; each agent gets an Ed25519 keypair, publishes its public key at &lt;code&gt;/.well-known/venmail-agent/{name}&lt;/code&gt; or as a DNS TXT record, and signs the message body and headers before DKIM is applied.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;vvs&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;@venmail/vsm&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;vvs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, world!&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;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;billing@yourco.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invoice #1234&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toUTCString&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;span class="na"&gt;agentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;billing@yourco.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;keyPair&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;verifyMethods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;well-known&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="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// result.headers = { 'X-Venmail-Agent': '...', 'X-Venmail-Signature': '...', ... }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Receiver side:&lt;/strong&gt; extract the &lt;code&gt;X-Venmail-*&lt;/code&gt; headers, resolve the sender's public key (well-known, DNS, or embedded), and verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;vvs&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;@venmail/vsm&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;vvs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verifyMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;vvsHeaders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;emailBody&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;emailHeaders&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="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trustLevel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'VERIFIED' | 'PARTIAL' | 'FAILED' | 'UNKNOWN'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four trust levels, deliberately non-blocking:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;VERIFIED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Signature valid, key resolved via &lt;code&gt;.well-known&lt;/code&gt; or DNS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PARTIAL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Signature valid, key from embedded header only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FAILED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Headers present but verification failed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;UNKNOWN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No VVS headers — a normal email&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Nothing gets blocked at the SMTP layer. Trust levels are annotations, shown as a badge in the Venmail inbox, not gatekeepers that bounce mail.&lt;/p&gt;

&lt;p&gt;This matters most for AI agents sending on your behalf, automated workflows where authenticity is load-bearing, financial communications that need to be tamper-evident, and agent-to-agent mail across organizations — cases where "the domain looked right" isn't actually good enough anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is this just Microsoft/Google/Nylas?
&lt;/h2&gt;

&lt;p&gt;Microsoft's Entra Agent ID and Google's Gemini Enterprise both already ship agent identity, and Nylas already offers agent-owned mailboxes with MCP support. We're not claiming to have invented "give an agent an inbox."&lt;/p&gt;

&lt;p&gt;What we think is different: Microsoft and Google bundle agent identity into their most expensive enterprise tiers, stack it on top of per-seat licensing, and build it for an IT team managing thousands of agents — not a small team wanting one scoped inbox via a single API call. Nylas is a sync layer over your existing Gmail or Outlook account; Venmail hosts the mailbox itself. And VVS-1's cross-organization verification — any mail server, not just Venmail, can check a signature — isn't something we've seen elsewhere yet.&lt;/p&gt;

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

&lt;p&gt;It's live: &lt;strong&gt;&lt;a href="https://venmail.io" rel="noopener noreferrer"&gt;venmail.io&lt;/a&gt;&lt;/strong&gt;. Docs are at &lt;a href="https://docs.venmail.io" rel="noopener noreferrer"&gt;docs.venmail.io&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We'd especially like to hear from anyone who's built email infrastructure, run larger teams, self-hosted mail, or built AI agents — drop a comment.&lt;/p&gt;

</description>
      <category>email</category>
      <category>api</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
