<?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: Sebastian Balog</title>
    <description>The latest articles on DEV Community by Sebastian Balog (@sebastian_balog_c88dc2913).</description>
    <link>https://dev.to/sebastian_balog_c88dc2913</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%2F4144671%2Fa6b94a64-45bd-4305-b1d1-46483e984c60.png</url>
      <title>DEV Community: Sebastian Balog</title>
      <link>https://dev.to/sebastian_balog_c88dc2913</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sebastian_balog_c88dc2913"/>
    <language>en</language>
    <item>
      <title>How to Run Multiple Cursor Accounts at Once on Mac and Windows</title>
      <dc:creator>Sebastian Balog</dc:creator>
      <pubDate>Fri, 30 Oct 2026 07:28:14 +0000</pubDate>
      <link>https://dev.to/sebastian_balog_c88dc2913/how-to-run-multiple-cursor-accounts-at-once-on-mac-and-windows-1knk</link>
      <guid>https://dev.to/sebastian_balog_c88dc2913/how-to-run-multiple-cursor-accounts-at-once-on-mac-and-windows-1knk</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure up front: I make &lt;a href="https://cursorsessions.com/" rel="noopener noreferrer"&gt;Sessions Pro for Cursor&lt;/a&gt;, a paid app that does this for you. Everything until the last section is free and needs nothing but Cursor. The Mac commands were tested on macOS 26 and the Windows options on Windows 11, both with Cursor 3.27.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you have a Cursor account for work and another for your own projects, or one per client, you know the routine: Cursor holds one account at a time, so switching means signing out, signing back in through the browser, and finding your place again. Do that a few times a day and it gets old fast.&lt;/p&gt;

&lt;p&gt;The good news is that you can run multiple Cursor accounts at once, side by side, with no logging out. Here is how it works, the free way to do it on Mac and Windows, and the catches nobody mentions until they bite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can you have two Cursor accounts?
&lt;/h2&gt;

&lt;p&gt;Yes. A Cursor team member put it plainly on the forum: "Having multiple accounts is totally fine. The only restriction is sharing a single account." So a work account paid for by your employer and a personal Pro account are fine. Two people sharing one login is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  What decides which account Cursor uses
&lt;/h2&gt;

&lt;p&gt;Cursor is built on VS Code, which is built on Electron. Your login lives in Cursor's data folder, not in some system setting:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Mac&lt;/th&gt;
&lt;th&gt;Windows&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Data folder (login, chats, settings, window state)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/Library/Application Support/Cursor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;%APPDATA%\Cursor&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extensions&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.cursor/extensions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;%USERPROFILE%\.cursor\extensions&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The sign-in token sits in &lt;code&gt;User/globalStorage/state.vscdb&lt;/code&gt; inside the data folder. One data folder, one account. Give Cursor a second data folder and you get a second, completely separate sign-in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free method on a Mac: run two instances of Cursor with --user-data-dir
&lt;/h2&gt;

&lt;p&gt;Cursor accepts VS Code's &lt;code&gt;--user-data-dir&lt;/code&gt; and &lt;code&gt;--extensions-dir&lt;/code&gt; options. Point them at new folders and &lt;code&gt;open -n&lt;/code&gt; starts a second copy of Cursor next to the one you already have:&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;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/CursorWork/data ~/CursorWork/extensions

open &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; Cursor &lt;span class="nt"&gt;--args&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--user-data-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/CursorWork/data"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--extensions-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/CursorWork/extensions"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--disable-updates&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new window starts signed out. Choose &lt;strong&gt;Log In&lt;/strong&gt;, finish the sign-in in your browser, and that folder stays signed in to the second account from then on. Your normal Cursor keeps its own account, and both run at the same time.&lt;/p&gt;

&lt;p&gt;What each option does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--user-data-dir&lt;/code&gt; gives the second copy its own login, chats, settings and window state.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--extensions-dir&lt;/code&gt; keeps its extensions apart. Without it both copies share one extensions folder.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--disable-updates&lt;/code&gt; stops the second copy from running Cursor's updater and nagging you about updates. Your normal Cursor still updates, and since both copies run the same installed app, the second one picks the update up too.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Keep the folder path short.&lt;/strong&gt; This one is easy to miss. Cursor opens a socket file inside the data folder (&lt;code&gt;&amp;lt;data&amp;gt;/3.27-main.sock&lt;/code&gt;), and macOS refuses socket paths longer than 103 characters. With a long path, say a folder nested under &lt;code&gt;Library/Application Support/...&lt;/code&gt;, the second Cursor flashes up and quits without any error. &lt;code&gt;~/CursorWork/data&lt;/code&gt; is fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free method on Windows: the same options in PowerShell
&lt;/h2&gt;

&lt;p&gt;On Windows, Cursor installs per user. Start a second instance with its own folders:&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="nv"&gt;$work&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;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;USERPROFILE&lt;/span&gt;&lt;span class="s2"&gt;\CursorWork"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$work&lt;/span&gt;&lt;span class="s2"&gt;\data"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$work&lt;/span&gt;&lt;span class="s2"&gt;\extensions"&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;span class="n"&gt;Out-Null&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;LOCALAPPDATA&lt;/span&gt;&lt;span class="s2"&gt;\Programs\cursor\Cursor.exe"&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;--user-data-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$work&lt;/span&gt;&lt;span class="s2"&gt;\data"&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;--extensions-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$work&lt;/span&gt;&lt;span class="s2"&gt;\extensions"&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;--disable-updates&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sign in to the second account in the new window. To make it a double-click, create a shortcut whose target is &lt;code&gt;Cursor.exe&lt;/code&gt; followed by the same three options.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep each account's agent data apart too
&lt;/h2&gt;

&lt;p&gt;There is one folder the options above don't move. Cursor's agent keeps per-account stores and per-project data outside the data folder (&lt;code&gt;~/Library/Application Support/Cursor/AgentStores&lt;/code&gt; and &lt;code&gt;~/.cursor/projects&lt;/code&gt; on a Mac). Two environment variables in Cursor's agent code move them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;open &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; Cursor &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="nv"&gt;CURSOR_AGENT_STORE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/CursorWork/agent-stores"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="nv"&gt;CURSOR_DATA_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/CursorWork/cursor-data"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--args&lt;/span&gt; &lt;span class="nt"&gt;--user-data-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/CursorWork/data"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
         &lt;span class="nt"&gt;--extensions-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/CursorWork/extensions"&lt;/span&gt; &lt;span class="nt"&gt;--disable-updates&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Windows, set them in PowerShell first (&lt;code&gt;$env:CURSOR_AGENT_STORE_DIR = "$work\agent-stores"&lt;/code&gt; and &lt;code&gt;$env:CURSOR_DATA_DIR = "$work\cursor-data"&lt;/code&gt;), then start &lt;code&gt;Cursor.exe&lt;/code&gt; from the same window. I verified these on a Mac; Windows runs the same code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the do-it-yourself way breaks
&lt;/h2&gt;

&lt;p&gt;Running two instances of Cursor works. Living with it is where it gets fiddly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;They look identical.&lt;/strong&gt; Same name, same icon, two "Cursor" entries in the Dock and ⌘-Tab, or in the Windows taskbar. Telling work from personal means checking the account in each window. On Windows, people on the Cursor forum report a pinned taskbar shortcut for the second instance opening the first one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You start it from Terminal or a shortcut every time.&lt;/strong&gt; Double-clicking Cursor opens your default account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;cursor://&lt;/code&gt; links go to your normal Cursor&lt;/strong&gt;, not to the copy that asked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Some things stay shared, by design.&lt;/strong&gt; &lt;code&gt;~/.cursor&lt;/code&gt; also holds your MCP servers (&lt;code&gt;mcp.json&lt;/code&gt;), rules and skills. Every copy reads the same ones. That's often what you want, but it isn't total isolation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never copy your existing data folder to seed the second one.&lt;/strong&gt; You'd copy the first account's login with it, and the two copies would end up fighting over one session. Start the new folder empty and sign in.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The ways to switch Cursor accounts, compared
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Way&lt;/th&gt;
&lt;th&gt;Both accounts open at once&lt;/th&gt;
&lt;th&gt;Effort&lt;/th&gt;
&lt;th&gt;Catches&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sign out, sign in&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Every switch&lt;/td&gt;
&lt;td&gt;Lose your place each time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;An account switcher extension&lt;/td&gt;
&lt;td&gt;No, one at a time&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Swaps the session in one window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--user-data-dir&lt;/code&gt; (above)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;One-time setup, then a shortcut&lt;/td&gt;
&lt;td&gt;Identical icons, shared &lt;code&gt;~/.cursor&lt;/code&gt;, short paths only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;An app that makes one copy per account&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Click&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  An app that does it for you
&lt;/h2&gt;

&lt;p&gt;This is the part I build. &lt;a href="https://cursorsessions.com/" rel="noopener noreferrer"&gt;Sessions Pro for Cursor&lt;/a&gt; does the setup above for you and handles what comes after:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;On a Mac, each account becomes its own app&lt;/strong&gt;, like "Cursor Work" and "Cursor Personal", with its own Dock icon and a coloured letter, so ⌘-Tab tells you which is which. A menu bar switcher shows the account in front.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On Windows, each account opens in its own Cursor window&lt;/strong&gt; titled with its name, with a tray switcher.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Each account keeps its own login, chats, settings, extensions and agent data.&lt;/strong&gt; On a Mac you can start a new account from your current Cursor's settings and extensions (never its login).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On a Mac, the account copies are rebuilt automatically when Cursor updates&lt;/strong&gt;, and the update nag stays out of them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On a Mac it also shows each account's usage&lt;/strong&gt; for the billing month, so you can see at a glance which account has room left.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's $15 one-time for 2 computers, Mac or Windows, with a free 1-hour preview that starts once an account signs in, and a 14-day refund. It isn't affiliated with Anysphere, the maker of Cursor; it runs your installed Cursor as it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Can I use two Cursor accounts on the same computer?&lt;/strong&gt; Yes. Each one needs its own data folder: the free method above, or an app that sets that up for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I run two instances of Cursor at the same time?&lt;/strong&gt; Yes, as long as each instance has its own &lt;code&gt;--user-data-dir&lt;/code&gt;. Two windows of the same instance share one account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I switch accounts in Cursor without logging out?&lt;/strong&gt; Keep each account signed in to its own instance and switch between the windows, instead of switching the account inside one window.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Will my work account see my personal chats?&lt;/strong&gt; No. Chats live in each instance's data folder. Only &lt;code&gt;~/.cursor&lt;/code&gt; (MCP servers, rules, skills) is shared.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does this work with Cursor's free plan?&lt;/strong&gt; Running several of your own accounts works on any plan. Using extra free accounts to stretch free limits is against Cursor's terms, and nothing here is meant for that.&lt;/p&gt;

</description>
      <category>cursor</category>
      <category>productivity</category>
      <category>macos</category>
      <category>windows</category>
    </item>
    <item>
      <title>Two ChatGPT accounts in the desktop app on a Mac (and keeping their Codex threads apart)</title>
      <dc:creator>Sebastian Balog</dc:creator>
      <pubDate>Sun, 25 Oct 2026 23:17:30 +0000</pubDate>
      <link>https://dev.to/sebastian_balog_c88dc2913/two-chatgpt-accounts-in-the-desktop-app-on-a-mac-and-keeping-their-codex-threads-apart-o63</link>
      <guid>https://dev.to/sebastian_balog_c88dc2913/two-chatgpt-accounts-in-the-desktop-app-on-a-mac-and-keeping-their-codex-threads-apart-o63</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure up front: I build &lt;a href="https://multiplecodex.com/" rel="noopener noreferrer"&gt;Sessions Pro for Codex&lt;/a&gt;, a paid app that does this for you. Everything until the last section is free and only needs Terminal. The commands were run on macOS 26 with ChatGPT 26.1021.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you use Codex for a client or an employer and also have your own ChatGPT account, you've probably hit this: the ChatGPT desktop app (which absorbed the Codex app in July) is signed in to one account at a time. Switching means signing out, signing back in, and losing your place.&lt;/p&gt;

&lt;p&gt;ChatGPT now has a built-in account switcher, but it only works on the web version, which doesn't help if you build real projects in the desktop app. So here's what actually decides the account in the desktop app, and the ways around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What decides which account the app uses
&lt;/h2&gt;

&lt;p&gt;Two folders, not one:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;th&gt;Default location&lt;/th&gt;
&lt;th&gt;Holds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CODEX_HOME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.codex&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;auth.json&lt;/code&gt; (the Codex login), &lt;code&gt;config.toml&lt;/code&gt; (settings, MCP servers), &lt;code&gt;state_5.sqlite&lt;/code&gt; (threads), &lt;code&gt;.codex-global-state.json&lt;/code&gt; (pins, projects, ordering)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;App data&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/Library/Application Support/Codex&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The app's own (Electron) data: the web session, preferences, caches&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One pair of folders, one account. The app is still &lt;code&gt;com.openai.codex&lt;/code&gt; under the hood, and the Codex CLI reads the same &lt;code&gt;~/.codex&lt;/code&gt;, so by default the app and &lt;code&gt;codex&lt;/code&gt; in your terminal share one login. That's also why &lt;code&gt;codex logout&lt;/code&gt; in a terminal can sign the app out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free method 1: a second copy of the app from Terminal
&lt;/h2&gt;

&lt;p&gt;The app reads &lt;code&gt;CODEX_HOME&lt;/code&gt; for Codex's state, &lt;code&gt;CODEX_ELECTRON_USER_DATA_PATH&lt;/code&gt; for its app data, and also takes Chromium's &lt;code&gt;--user-data-dir&lt;/code&gt;. Point all three at new folders and &lt;code&gt;open -n&lt;/code&gt; starts a second, independent copy next to the first:&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;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.codex-work"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Library/Application Support/Codex-Work"&lt;/span&gt;

open &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; ChatGPT &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="nv"&gt;CODEX_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.codex-work"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="nv"&gt;CODEX_ELECTRON_USER_DATA_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Library/Application Support/Codex-Work"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--args&lt;/span&gt; &lt;span class="nt"&gt;--user-data-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Library/Application Support/Codex-Work"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new window starts signed out (there's no &lt;code&gt;auth.json&lt;/code&gt; in the new folder yet). Sign in to the second account there, and from then on that pair of folders stays signed in to it.&lt;/p&gt;

&lt;p&gt;Two details I found while testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Both copies can run together.&lt;/strong&gt; The app only takes its single-instance lock per data folder when &lt;code&gt;CODEX_ELECTRON_USER_DATA_PATH&lt;/code&gt; is set, so separate folders never block each other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create the folders first.&lt;/strong&gt; &lt;code&gt;open&lt;/code&gt; won't, and Codex expects &lt;code&gt;CODEX_HOME&lt;/code&gt; to exist.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The catches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Both copies look identical.&lt;/strong&gt; Same name, same Dock icon, two "ChatGPT" entries in ⌘-Tab. Telling work from personal means checking the account in each window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;codex://&lt;/code&gt; links go to whichever copy started last.&lt;/strong&gt; Every copy registers itself for &lt;code&gt;codex://&lt;/code&gt; when it launches. Thread links and connector sign-in callbacks (OAuth) can land in the wrong account.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You start it from Terminal every time.&lt;/strong&gt; Double-clicking ChatGPT opens your default account. A shell alias or an Automator app helps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't seed it with a copy of &lt;code&gt;~/.codex&lt;/code&gt;.&lt;/strong&gt; Some files inside hold absolute paths to the original folder, so continuing a copied thread can write into your original account's history. Start the second folder empty and sign in.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Free method 2: just the Codex CLI, with &lt;code&gt;CODEX_HOME&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;If you only need the second account in the terminal, it's simpler: one folder per account.&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;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.codex-work
&lt;span class="nv"&gt;CODEX_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/.codex-work codex login     &lt;span class="c"&gt;# sign in with the other account once&lt;/span&gt;
&lt;span class="nv"&gt;CODEX_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/.codex-work codex login status
&lt;span class="c"&gt;# Not logged in   -&amp;gt; before signing in&lt;/span&gt;
&lt;span class="c"&gt;# Logged in using ChatGPT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plain &lt;code&gt;codex&lt;/code&gt; keeps using &lt;code&gt;~/.codex&lt;/code&gt; and your first account. Add an alias so you don't have to type the variable:&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;alias &lt;/span&gt;codex-work&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'CODEX_HOME="$HOME/.codex-work" codex'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each folder has its own &lt;code&gt;config.toml&lt;/code&gt;, so MCP servers and settings are per account. Copy &lt;code&gt;config.toml&lt;/code&gt; across if you want the same setup, never &lt;code&gt;auth.json&lt;/code&gt;. And &lt;code&gt;logout&lt;/code&gt; is per folder too: &lt;code&gt;codex-work logout&lt;/code&gt; signs out only the work account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other options, briefly
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sign out and back in:&lt;/strong&gt; fine once a week, painful several times a day, and your threads view changes with every switch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A browser profile per account:&lt;/strong&gt; works with ChatGPT on the web, but not with the desktop app's local Codex threads, projects and terminal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A second macOS user:&lt;/strong&gt; complete separation, but only one account in front of you at a time, and fast user switching between them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I ended up building
&lt;/h2&gt;

&lt;p&gt;Method 1 works, but its catches add up if you switch accounts every day: two identical Dock icons, thread links opening in the wrong account, and re-running the command after every reboot. That's what I built &lt;a href="https://multiplecodex.com/" rel="noopener noreferrer"&gt;Sessions Pro for Codex&lt;/a&gt; (Mac and Windows) to fix:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each account becomes its own app, with its own name, colored Dock icon and place in ⌘-Tab.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;codex://&lt;/code&gt; links go to the account you were last using, not to whichever copy started last.&lt;/li&gt;
&lt;li&gt;Each profile has its own Codex CLI (&lt;code&gt;CODEX_HOME&lt;/code&gt;), opened from the app with one click.&lt;/li&gt;
&lt;li&gt;A menu bar switcher, and a meter showing each account's Codex session and weekly usage.&lt;/li&gt;
&lt;li&gt;It keeps ChatGPT itself up to date (checking OpenAI's signature first) and rebuilds every profile from the new version, since copies don't update themselves.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's $24.99 one-time for two computers, with a 1-hour free preview. If the free methods above are enough for you, use them: they're genuinely fine for occasional switching.&lt;/p&gt;

&lt;p&gt;A note on the rules: these methods run the official ChatGPT app with accounts you already have, like a work and a personal account. OpenAI's terms still apply to each account, and none of this is meant for getting around usage limits.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The full guide, with a comparison table of every method, is on &lt;a href="https://multiplecodex.com/run-multiple-codex-accounts-mac/" rel="noopener noreferrer"&gt;multiplecodex.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>chatgpt</category>
      <category>codex</category>
      <category>macos</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Run two Claude Code accounts side by side without logging out (Mac, Windows, VS Code)</title>
      <dc:creator>Sebastian Balog</dc:creator>
      <pubDate>Sat, 24 Oct 2026 20:06:22 +0000</pubDate>
      <link>https://dev.to/sebastian_balog_c88dc2913/run-two-claude-code-accounts-side-by-side-without-logging-out-mac-windows-vs-code-56md</link>
      <guid>https://dev.to/sebastian_balog_c88dc2913/run-two-claude-code-accounts-side-by-side-without-logging-out-mac-windows-vs-code-56md</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure: I make &lt;a href="https://doubleclaude.com/" rel="noopener noreferrer"&gt;Claude Sessions Pro&lt;/a&gt;, a paid Mac and Windows app for running several Claude accounts at once. Everything below works without it. The app gets one section near the end, clearly marked.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You have a work Claude account and a personal one. Maybe one per client. Claude Code signs in to one of them, and switching means &lt;code&gt;/logout&lt;/code&gt;, &lt;code&gt;/login&lt;/code&gt;, a browser tab, and losing your place. An hour later you do it again in the other direction.&lt;/p&gt;

&lt;p&gt;You don't need to. Claude Code keeps everything about an account (the login, settings, history, MCP servers) in one folder, and you can point it at a different folder whenever you start it. Two folders, two accounts, both open at the same time in two terminals.&lt;/p&gt;

&lt;p&gt;This guide covers the setup on macOS, Linux and Windows (PowerShell, cmd and Windows Terminal), how to run both side by side, how to let each project folder pick its own account, VS Code, CI, and the handful of things that quietly put both terminals on the same login. I checked the core of it (the alias, the PowerShell functions, the Windows Terminal profile, the tmux split, &lt;code&gt;auth status&lt;/code&gt; and where MCP servers end up) on macOS and Windows 11.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You want&lt;/th&gt;
&lt;th&gt;Do this&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A second account in the terminal&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;alias claude-work='CLAUDE_CONFIG_DIR=~/.claude-work claude'&lt;/code&gt;, then run &lt;code&gt;claude-work&lt;/code&gt; and sign in once&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The same on Windows&lt;/td&gt;
&lt;td&gt;A small PowerShell function that sets &lt;code&gt;$env:CLAUDE_CONFIG_DIR&lt;/code&gt; for one call (below)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Both accounts on screen at once&lt;/td&gt;
&lt;td&gt;tmux, an iTerm2 or Terminal split, or a Windows Terminal split pane&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Each project to use the right account&lt;/td&gt;
&lt;td&gt;direnv, or a shell function keyed on the folder&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;To check which account you're on&lt;/td&gt;
&lt;td&gt;&lt;code&gt;claude auth status&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;To never confuse them&lt;/td&gt;
&lt;td&gt;A status line or terminal badge that says WORK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No terminal setup at all&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://doubleclaude.com/" rel="noopener noreferrer"&gt;Claude Sessions Pro&lt;/a&gt;, one app or window per account&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How Claude Code decides which account you're on
&lt;/h2&gt;

&lt;p&gt;When Claude Code starts, it looks at one environment variable, &lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt;. If it isn't set, it uses &lt;code&gt;~/.claude&lt;/code&gt;. That folder is the account, for practical purposes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu68wb1sadtv6als09otw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu68wb1sadtv6als09otw.png" alt="Diagram: the default ~/.claude folder and a ~/.claude-work folder, each with its own login, settings, MCP servers, instructions and session history" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The login.&lt;/strong&gt; On macOS the token goes in the Keychain, in an entry tied to the config folder, so a second folder gets its own entry. On Linux and Windows it's a &lt;code&gt;.credentials.json&lt;/code&gt; file inside the folder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Settings&lt;/strong&gt;, including the status line, permissions and model, in &lt;code&gt;settings.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User-scope MCP servers.&lt;/strong&gt; For the default folder these live in &lt;code&gt;~/.claude.json&lt;/code&gt;, which sits &lt;em&gt;next to&lt;/em&gt; &lt;code&gt;~/.claude&lt;/code&gt;, not inside it. When &lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt; is set, Claude Code writes them to &lt;code&gt;.claude.json&lt;/code&gt; &lt;em&gt;inside&lt;/em&gt; that folder instead. Easy to miss, and it matters later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your personal instructions, skills and agents:&lt;/strong&gt; &lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;skills/&lt;/code&gt;, &lt;code&gt;agents/&lt;/code&gt;, &lt;code&gt;commands/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session history&lt;/strong&gt; under &lt;code&gt;projects/&lt;/code&gt;, which is what &lt;code&gt;--resume&lt;/code&gt; and &lt;code&gt;--continue&lt;/code&gt; read.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So "a second account" is just "a second folder". Nothing is copied or patched, and your default setup isn't touched.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 on macOS and Linux: a folder and an alias
&lt;/h2&gt;

&lt;p&gt;Pick a name. I'll use &lt;code&gt;~/.claude-work&lt;/code&gt; throughout; one folder per extra account works the same way (&lt;code&gt;~/.claude-clientA&lt;/code&gt;, &lt;code&gt;~/.claude-personal&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Add this to &lt;code&gt;~/.zshrc&lt;/code&gt; (or &lt;code&gt;~/.bashrc&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;&lt;span class="c"&gt;# Default account: plain `claude`, ~/.claude&lt;/span&gt;
&lt;span class="c"&gt;# Work account: `claude-work`, ~/.claude-work&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;claude-work&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'CLAUDE_CONFIG_DIR="$HOME/.claude-work" claude'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open a new terminal and run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude-work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code doesn't find a login in the new folder, so it walks you through first-run setup and opens the browser. Sign in with the &lt;em&gt;other&lt;/em&gt; account. That's the only time you'll do it. From now on &lt;code&gt;claude&lt;/code&gt; is one account and &lt;code&gt;claude-work&lt;/code&gt; is the other, and you can have both running at once.&lt;/p&gt;

&lt;p&gt;Check that it worked:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude auth status
claude-work auth status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each prints a small JSON block. Look at &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;configDirectory&lt;/code&gt;: the first should show your default account and &lt;code&gt;~/.claude&lt;/code&gt;, the second your work account and &lt;code&gt;~/.claude-work&lt;/code&gt;. (&lt;code&gt;auth status&lt;/code&gt; needs a recent Claude Code; run &lt;code&gt;claude update&lt;/code&gt; if it isn't recognised.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't point the variable at the default folder
&lt;/h3&gt;

&lt;p&gt;It's tempting to make things symmetrical with a second alias, &lt;code&gt;claude-personal='CLAUDE_CONFIG_DIR=~/.claude claude'&lt;/code&gt;. Don't. On macOS, setting the variable &lt;em&gt;at all&lt;/em&gt;, even to the default path, makes Claude Code look for a different Keychain entry, so your personal account suddenly appears signed out. It's tracked as &lt;a href="https://github.com/anthropics/claude-code/issues/92252" rel="noopener noreferrer"&gt;issue #92252&lt;/a&gt;. Leave your main account on plain &lt;code&gt;claude&lt;/code&gt; with the variable unset, and give every &lt;em&gt;extra&lt;/em&gt; account its own new folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 on Windows: PowerShell, cmd and Windows Terminal
&lt;/h2&gt;

&lt;p&gt;The idea is the same, but PowerShell has no &lt;code&gt;VAR=value command&lt;/code&gt; shorthand. If you just run &lt;code&gt;$env:CLAUDE_CONFIG_DIR = ...&lt;/code&gt; and then &lt;code&gt;claude&lt;/code&gt;, the variable stays set for every later command in that window, and the next plain &lt;code&gt;claude&lt;/code&gt; is your work account too.&lt;/p&gt;

&lt;p&gt;This function sets the variable for one call and puts it back afterwards, even if Claude Code exits with an error:&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="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;claude-work&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="nv"&gt;$prev&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;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CONFIG_DIR&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CONFIG_DIR&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;span class="n"&gt;Join-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$HOME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'.claude-work'&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="kr"&gt;try&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="n"&gt;claude&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;args&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="kr"&gt;finally&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="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CONFIG_DIR&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;span class="nv"&gt;$prev&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;p&gt;Put it in your profile so it's always there. &lt;code&gt;notepad $PROFILE&lt;/code&gt; opens the file (create it if Notepad asks). Open a new PowerShell window, run &lt;code&gt;claude-work&lt;/code&gt;, sign in with the second account, and check both with &lt;code&gt;claude auth status&lt;/code&gt; and &lt;code&gt;claude-work auth status&lt;/code&gt; as above. &lt;code&gt;@args&lt;/code&gt; passes everything through, so &lt;code&gt;claude-work --resume&lt;/code&gt; and &lt;code&gt;claude-work mcp list&lt;/code&gt; work as you'd expect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cmd.exe:&lt;/strong&gt; quote the whole assignment, or cmd keeps the space before &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; as part of the folder name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="s2"&gt;"CLAUDE_CONFIG_DIR=&lt;/span&gt;&lt;span class="nv"&gt;%USERPROFILE%&lt;/span&gt;&lt;span class="s2"&gt;\.claude-work"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="kd"&gt;claude&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one does stay set for the rest of that cmd window, so use a dedicated window for it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windows Terminal profile.&lt;/strong&gt; If you'd rather have a "Claude (work)" entry in the new-tab menu, open Settings, then &lt;em&gt;Open JSON file&lt;/em&gt;, and add a profile to &lt;code&gt;profiles.list&lt;/code&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="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;"Claude (work)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"commandline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"powershell.exe -NoExit -Command &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;$env:CLAUDE_CONFIG_DIR = Join-Path $HOME '.claude-work'; claude&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&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;"startingDirectory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"%USERPROFILE%"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tabTitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WORK"&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;p&gt;The variable only exists inside that tab, so every other tab is untouched. &lt;code&gt;-NoExit&lt;/code&gt; keeps the window open when you quit Claude Code, so you can start it again with the same account by typing &lt;code&gt;claude&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: both accounts on screen at once
&lt;/h2&gt;

&lt;p&gt;Once the folders exist, "side by side" is just two terminals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tmux&lt;/strong&gt; (macOS and Linux). One command, two panes, one account each:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tmux new-session &lt;span class="nt"&gt;-s&lt;/span&gt; claude &lt;span class="s1"&gt;'claude'&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt; split-window &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="s1"&gt;'CLAUDE_CONFIG_DIR="$HOME/.claude-work" claude'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Left pane: default account. Right pane: work. Each pane closes when you quit Claude Code in it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;iTerm2.&lt;/strong&gt; Settings, Profiles, duplicate your profile and name it "Claude work". Under General, set &lt;em&gt;Send text at start&lt;/em&gt; to &lt;code&gt;export CLAUDE_CONFIG_DIR="$HOME/.claude-work"&lt;/code&gt;, and put &lt;code&gt;WORK&lt;/code&gt; in &lt;em&gt;Badge&lt;/em&gt;, which draws a large faint label behind the text. Now split a pane with that profile (right-click a pane, &lt;em&gt;Split Pane with Profile&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;macOS Terminal.&lt;/strong&gt; Settings, Profiles, duplicate a profile and name it "Claude work". On the Shell tab, tick &lt;em&gt;Run command&lt;/em&gt; and &lt;em&gt;Run inside shell&lt;/em&gt;, and enter &lt;code&gt;CLAUDE_CONFIG_DIR="$HOME/.claude-work" claude&lt;/code&gt;. A new window with that profile opens straight into Claude Code on the work account. Give the profile a different background colour while you're there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windows Terminal.&lt;/strong&gt; Hold &lt;strong&gt;Alt&lt;/strong&gt; and click "Claude (work)" in the new-tab dropdown: it opens as a split pane next to the current one instead of a new tab. &lt;code&gt;Alt+Shift+-&lt;/code&gt; and &lt;code&gt;Alt+Shift+Plus&lt;/code&gt; split the current pane if you'd rather start from a plain shell.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: let the project folder pick the account
&lt;/h2&gt;

&lt;p&gt;The alias works, but you still have to remember which one to type. If your work repos all live under one folder, let the folder decide.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;direnv&lt;/strong&gt; (macOS, Linux, WSL). Install it (&lt;a href="https://direnv.net/" rel="noopener noreferrer"&gt;direnv.net&lt;/a&gt;), hook it into your shell, then in the root of your work folder:&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;# ~/work/.envrc&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CONFIG_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.claude-work"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;direnv allow&lt;/code&gt; once. Now &lt;code&gt;cd ~/work/anything&lt;/code&gt; sets the variable and leaving unsets it, so plain &lt;code&gt;claude&lt;/code&gt; uses the right account in every repo below that folder. Add &lt;code&gt;.envrc&lt;/code&gt; to your global gitignore if your repos are shared.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No direnv?&lt;/strong&gt; A shell function does the same check every time you start Claude Code:&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;# ~/.zshrc or ~/.bashrc&lt;/span&gt;
claude&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;/"&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/work/"&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;CLAUDE_CONFIG_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.claude-work"&lt;/span&gt; &lt;span class="nb"&gt;command &lt;/span&gt;claude &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;              &lt;span class="nb"&gt;command &lt;/span&gt;claude &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
  &lt;span class="k"&gt;esac&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;command claude&lt;/code&gt; calls the real binary rather than the function again. Add one line per client folder if you have more than two accounts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PowerShell&lt;/strong&gt; can do the same inside the function from earlier:&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="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;claude&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="nv"&gt;$prev&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;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CONFIG_DIR&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;$PWD&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-like&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Join-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$HOME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'work\*'&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="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CONFIG_DIR&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;span class="n"&gt;Join-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$HOME&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'.claude-work'&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="kr"&gt;try&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="n"&gt;claude.exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;args&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="kr"&gt;finally&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="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CONFIG_DIR&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;span class="nv"&gt;$prev&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;p&gt;If &lt;code&gt;claude.exe&lt;/code&gt; isn't found, check what &lt;code&gt;Get-Command claude -All&lt;/code&gt; lists and call that name instead (npm installs a &lt;code&gt;claude.cmd&lt;/code&gt;, so it's &lt;code&gt;claude.cmd @args&lt;/code&gt; in that case).&lt;/p&gt;

&lt;h2&gt;
  
  
  VS Code and other editors
&lt;/h2&gt;

&lt;p&gt;The Claude Code extension has a setting for environment variables, &lt;code&gt;claudeCode.environmentVariables&lt;/code&gt;, and it would be the obvious place for &lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt;. The catch: it's a &lt;em&gt;machine-scoped&lt;/em&gt; setting. VS Code ignores it in a workspace's &lt;code&gt;.vscode/settings.json&lt;/code&gt;, so you can't give one project the work account and another the personal one this way. Set it in your user settings and it applies to every window. If you do set it there, use an absolute path; &lt;code&gt;~&lt;/code&gt; isn't expanded.&lt;/p&gt;

&lt;p&gt;What does work per project is the integrated terminal. In the work project's &lt;code&gt;.vscode/settings.json&lt;/code&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="nl"&gt;"terminal.integrated.env.osx"&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="nl"&gt;"CLAUDE_CONFIG_DIR"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/Users/you/.claude-work"&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;"terminal.integrated.env.linux"&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="nl"&gt;"CLAUDE_CONFIG_DIR"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/home/you/.claude-work"&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;"terminal.integrated.env.windows"&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="nl"&gt;"CLAUDE_CONFIG_DIR"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Users&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;you&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;.claude-work"&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;p&gt;New terminals in that window get the variable, and &lt;code&gt;claude&lt;/code&gt; run there uses the work account. VS Code asks you to trust the workspace before it applies terminal environment settings. Cursor and Windsurf read the same keys. JetBrains IDEs have the same idea under Settings, Tools, Terminal, &lt;em&gt;Environment variables&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make the two accounts impossible to mix up
&lt;/h2&gt;

&lt;p&gt;Two identical terminals with different accounts is a recipe for running the client job on your personal plan. Give the work folder a status line that says so. Create &lt;code&gt;~/.claude-work/statusline.sh&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;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="c"&gt;# Claude Code pipes session info as JSON on stdin; we only need a label.&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'\033[44;97m WORK \033[0m %s'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make it executable (&lt;code&gt;chmod +x ~/.claude-work/statusline.sh&lt;/code&gt;) and point the work folder's &lt;code&gt;~/.claude-work/settings.json&lt;/code&gt; at it:&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="nl"&gt;"statusLine"&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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.claude-work/statusline.sh"&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;p&gt;The default account keeps its own &lt;code&gt;settings.json&lt;/code&gt;, so only the work sessions show the blue WORK tag. Combined with a coloured terminal profile or an iTerm2 badge, you can tell them apart from across the room. And when in doubt, &lt;code&gt;/status&lt;/code&gt; inside a session shows the account it's signed in to.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to share between accounts, and what never to share
&lt;/h2&gt;

&lt;p&gt;A new folder starts empty: no &lt;code&gt;CLAUDE.md&lt;/code&gt;, no skills, no agents. You probably want those to be the same everywhere. Symlink them:&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;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; ~/.claude/CLAUDE.md ~/.claude-work/CLAUDE.md
&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; ~/.claude/skills    ~/.claude-work/skills
&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; ~/.claude/agents    ~/.claude-work/agents
&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; ~/.claude/commands  ~/.claude-work/commands
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(On Windows, &lt;code&gt;New-Item -ItemType SymbolicLink&lt;/code&gt; does the same, but needs Developer Mode or an admin prompt. Copying the files is fine too.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Never share or symlink&lt;/strong&gt; &lt;code&gt;.credentials.json&lt;/code&gt;, &lt;code&gt;.claude.json&lt;/code&gt; or the whole folder. Those hold the login and per-account state. Sharing them is how you end up with one account in both terminals, or each terminal signing the other one out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP servers don't come along.&lt;/strong&gt; User-scope servers live in the account's own &lt;code&gt;.claude.json&lt;/code&gt; (see the diagram), so the work account starts with none. Add them again through the work alias:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude-work mcp add &lt;span class="nt"&gt;--scope&lt;/span&gt; user &lt;span class="nt"&gt;--transport&lt;/span&gt; http notion https://mcp.notion.com/mcp
claude-work mcp list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Project-scope servers (a &lt;code&gt;.mcp.json&lt;/code&gt; checked into the repo) are read from the repo, so they work for both accounts without doing anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Settings&lt;/strong&gt; can be shared by symlinking &lt;code&gt;settings.json&lt;/code&gt;, but most people want the work one to differ, at least for the status line above.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gotchas that put both terminals on the same account
&lt;/h2&gt;

&lt;p&gt;If both &lt;code&gt;auth status&lt;/code&gt; calls show the same email, one of these is almost always why.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;An API key in your shell profile.&lt;/strong&gt; If &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt; is exported in &lt;code&gt;~/.zshrc&lt;/code&gt; or your Windows user environment, and you've approved it in Claude Code, it's used ahead of the subscription login in &lt;em&gt;every&lt;/em&gt; folder. Both "accounts" are then billing the same API key. Unset it, or only set it in the one place you need it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A long-lived token in the environment.&lt;/strong&gt; &lt;code&gt;claude setup-token&lt;/code&gt; prints an OAuth token for CI. If you export it as &lt;code&gt;CLAUDE_CODE_OAUTH_TOKEN&lt;/code&gt; globally, it also wins over &lt;code&gt;/login&lt;/code&gt; in every folder. Same fix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The variable set to the default path.&lt;/strong&gt; The macOS Keychain issue from Step 1.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Settings files can't set it.&lt;/strong&gt; &lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt; in a project's &lt;code&gt;.claude/settings.json&lt;/code&gt; or &lt;code&gt;settings.local.json&lt;/code&gt; is ignored, because Claude Code has already chosen the folder by the time it reads them. It has to come from the environment: the alias, direnv, the terminal profile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your company may force one organisation.&lt;/strong&gt; Managed settings on a work laptop can include &lt;code&gt;forceLoginOrgUUID&lt;/code&gt;, which only allows sign-ins to the company's organisation, in any folder. If your personal login is refused on the work machine, that's policy, not a bug. Ask IT rather than working around it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/logout&lt;/code&gt; only signs out the folder you're in.&lt;/strong&gt; That's the point, but it surprises people who expect it to sign out "Claude".&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Running both accounts in CI
&lt;/h2&gt;

&lt;p&gt;Same idea in a pipeline: one token per account. On your machine, run &lt;code&gt;setup-token&lt;/code&gt; with each account's folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude setup-token          &lt;span class="c"&gt;# default account&lt;/span&gt;
claude-work setup-token     &lt;span class="c"&gt;# work account&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Store each token as a separate secret (&lt;code&gt;CLAUDE_CODE_OAUTH_TOKEN_PERSONAL&lt;/code&gt;, &lt;code&gt;CLAUDE_CODE_OAUTH_TOKEN_WORK&lt;/code&gt;) and map the right one to &lt;code&gt;CLAUDE_CODE_OAUTH_TOKEN&lt;/code&gt; in each job. The runner never needs a config folder or a browser login.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about Claude Desktop?
&lt;/h2&gt;

&lt;p&gt;None of this applies to the Claude Desktop app. It ignores &lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt; and signs in to one account at a time, including in its Code tab. To use two accounts there, you're back to signing out and in, or running a second copy of the app with its own profile, which is fiddly to set up by hand. That's the gap the next section is about.&lt;/p&gt;

&lt;h2&gt;
  
  
  The no-setup way: Claude Sessions Pro
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;This is the product section mentioned at the top.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://doubleclaude.com/" rel="noopener noreferrer"&gt;Claude Sessions Pro&lt;/a&gt; because I wanted my accounts side by side in the desktop app as well as the terminal, without maintaining aliases and profiles on two operating systems.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One app per account on Mac, one window per account on Windows.&lt;/strong&gt; Each is a full Claude Desktop session with its own login, chats and Code tab, open at the same time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Code in the terminal, per profile.&lt;/strong&gt; Each profile has &lt;em&gt;Open in Terminal&lt;/em&gt;, which starts &lt;code&gt;claude&lt;/code&gt; with that profile's own config folder, and &lt;em&gt;Copy Export Command&lt;/em&gt; if you'd rather paste the line into your own shell or script. It's the same &lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt; approach from this post, just managed for you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuvzdx0dn7xjuo5wt4ynf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuvzdx0dn7xjuo5wt4ynf.png" alt="Adding a new profile in Claude Sessions Pro: pick a name and a colour, and it creates a separate Claude app for that account" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhxkxornnqwijwthicj1l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhxkxornnqwijwthicj1l.png" alt="Claude Sessions Pro main window: the profile list, and the Claude Code CLI buttons Open in Terminal and Copy Export Command" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A usage meter for every account&lt;/strong&gt; in the menu bar (Mac) or system tray (Windows), with an alert at 80% and 95% so a long session doesn't hit the limit by surprise.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fylo2dq25w57lqhozygl5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fylo2dq25w57lqhozygl5.png" alt="Usage menu in the macOS menu bar showing each profile's current usage" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's for accounts you already have, not a way to get more usage: each account keeps its own limits, and Anthropic's terms apply to each one. It runs on macOS 14 or later and Windows 10 and 11, costs &lt;strong&gt;$15 once&lt;/strong&gt; for two computers, and has a free one-hour preview and a 14-day refund. It's an independent app, not made by or affiliated with Anthropic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://doubleclaude.com/" rel="noopener noreferrer"&gt;Try Claude Sessions Pro free for an hour →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;Likely cause&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;command not found: claude-work&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The alias or function isn't in the profile this shell reads&lt;/td&gt;
&lt;td&gt;Check you added it to the right file (&lt;code&gt;~/.zshrc&lt;/code&gt; vs &lt;code&gt;~/.bashrc&lt;/code&gt;, or &lt;code&gt;$PROFILE&lt;/code&gt;), then open a new terminal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;claude-work&lt;/code&gt; asks you to sign in again&lt;/td&gt;
&lt;td&gt;The folder path changed (a typo, or a relative path that depends on where you are)&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;$HOME/...&lt;/code&gt; or a full path, and compare &lt;code&gt;configDirectory&lt;/code&gt; in &lt;code&gt;claude-work auth status&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Your main account looks signed out after setup&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt; set to &lt;code&gt;~/.claude&lt;/code&gt; (macOS)&lt;/td&gt;
&lt;td&gt;Unset it; keep the main account on plain &lt;code&gt;claude&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Both terminals show the same email&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt; or &lt;code&gt;CLAUDE_CODE_OAUTH_TOKEN&lt;/code&gt; exported&lt;/td&gt;
&lt;td&gt;Remove it from your shell profile or user environment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MCP tools missing in the work account&lt;/td&gt;
&lt;td&gt;User-scope servers are per folder&lt;/td&gt;
&lt;td&gt;Re-add with &lt;code&gt;claude-work mcp add --scope user ...&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Work account has no &lt;code&gt;CLAUDE.md&lt;/code&gt; or skills&lt;/td&gt;
&lt;td&gt;New folder starts empty&lt;/td&gt;
&lt;td&gt;Symlink or copy them from &lt;code&gt;~/.claude&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PowerShell: every later &lt;code&gt;claude&lt;/code&gt; is the work account&lt;/td&gt;
&lt;td&gt;Variable set directly, not inside the function&lt;/td&gt;
&lt;td&gt;Use the function with &lt;code&gt;try/finally&lt;/code&gt;, or open a fresh window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VS Code workspace setting has no effect&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;claudeCode.environmentVariables&lt;/code&gt; is machine-scoped&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;terminal.integrated.env.*&lt;/code&gt; per workspace, or user settings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--resume&lt;/code&gt; doesn't show yesterday's session&lt;/td&gt;
&lt;td&gt;It was started under the other account&lt;/td&gt;
&lt;td&gt;Resume from the account (folder) you started it in&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is running two accounts like this allowed?&lt;/strong&gt;&lt;br&gt;
You're signing in to two accounts you already have, one per folder, instead of signing out and back in. Each account is still bound by Anthropic's terms and its own plan limits. Don't use extra accounts to get around a limit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do the usage limits combine?&lt;/strong&gt;&lt;br&gt;
No. Each account has its own limits and its own usage, exactly as if you'd switched with &lt;code&gt;/logout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I run three or more?&lt;/strong&gt;&lt;br&gt;
Yes. One folder and one alias (or one direnv folder) per account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it work in WSL?&lt;/strong&gt;&lt;br&gt;
Yes, the Linux instructions apply inside WSL. Note that WSL and Windows keep separate folders, so an account signed in on the Windows side isn't signed in inside WSL, and vice versa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Will a Claude Code update break it?&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt; is a documented setting, so it's been stable across updates. If something changes, &lt;code&gt;claude auth status&lt;/code&gt; is the quickest way to see which folder a session is really using.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I move my existing history to the new account?&lt;/strong&gt;&lt;br&gt;
Session history is per folder. You can copy a project's folder from &lt;code&gt;~/.claude/projects/&lt;/code&gt; to &lt;code&gt;~/.claude-work/projects/&lt;/code&gt; to make it resumable there. Only do it when the conversation belongs with that account, for example work code moving to the work account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;The whole trick is one environment variable: a folder per account, and a way to start Claude Code with the right one. An alias on macOS and Linux, a small function on Windows, direnv if you want it automatic, a status line so you never guess. The rest of this post is the edge cases that bite after the first day.&lt;/p&gt;

&lt;p&gt;If you'd rather have it done for you, in the terminal and in Claude Desktop, &lt;a href="https://doubleclaude.com/" rel="noopener noreferrer"&gt;Claude Sessions Pro&lt;/a&gt; is $15 once, with a free hour to try it. There are longer write-ups on &lt;a href="https://doubleclaude.com/two-claude-code-accounts-terminal/" rel="noopener noreferrer"&gt;running two Claude Code accounts in the terminal&lt;/a&gt; and &lt;a href="https://doubleclaude.com/switch-claude-code-account/" rel="noopener noreferrer"&gt;switching Claude Code accounts&lt;/a&gt; on the site.&lt;/p&gt;

&lt;p&gt;If you've hit a gotcha that isn't here, tell me in the comments and I'll add it.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>claude</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Catching Android adware by behaviour instead of signatures</title>
      <dc:creator>Sebastian Balog</dc:creator>
      <pubDate>Fri, 23 Oct 2026 22:40:30 +0000</pubDate>
      <link>https://dev.to/sebastian_balog_c88dc2913/catching-android-adware-by-behaviour-instead-of-signatures-14m0</link>
      <guid>https://dev.to/sebastian_balog_c88dc2913/catching-android-adware-by-behaviour-instead-of-signatures-14m0</guid>
      <description>&lt;p&gt;Signature-based detection has an obvious weakness against adware: the families rebuild constantly. A new package name, a new signing key, a slightly different payload, and the app is "unknown" again. Meanwhile the user is still getting a full-screen ad every few minutes.&lt;/p&gt;

&lt;p&gt;While building &lt;a href="https://stoppopups.app/" rel="noopener noreferrer"&gt;Impossible Adware Remover&lt;/a&gt; we ended up leaning on a much simpler signal: &lt;strong&gt;which app is putting windows on top of the screen, and how often&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The signal
&lt;/h3&gt;

&lt;p&gt;An adware pop-up has to become the foreground window to be seen. On Android, an accessibility service receives window state changes along with the package name of the app that owns the new window. Most of those events are boring: the launcher, the app the user just tapped, the keyboard. Adware stands out because it takes the foreground when the user didn't ask for it, repeatedly, often right after unlock or on top of another app.&lt;/p&gt;

&lt;p&gt;So the core logic isn't a database lookup. It's bookkeeping:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Track which package takes the foreground, and in what context (user launched it, or it appeared over something else).&lt;/li&gt;
&lt;li&gt;Ignore the expected ones: launchers, the current foreground app's own windows, system UI, the keyboard.&lt;/li&gt;
&lt;li&gt;When the same package keeps appearing over other apps without being launched, flag it. In practice about two pop-ups is enough.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Things that complicate it
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wrapper apps.&lt;/strong&gt; Adware often lives inside an app that also does something useful, so the package name looks legitimate. Behaviour doesn't care what the app is called.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delays.&lt;/strong&gt; Many families wait days before the first ad, which defeats "uninstall what you installed today" advice but not a watcher that's always on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fighting back.&lt;/strong&gt; Some adware throws windows over the uninstall dialog itself. We added a short-lived shield that keeps the system uninstall confirmation on top while the user decides.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notification ads.&lt;/strong&gt; Ads delivered as notifications are a different channel; there you can see which app posted, but not (and you shouldn't read) the content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Privacy constraints we kept
&lt;/h3&gt;

&lt;p&gt;The service only needs package names and timestamps. It never reads screen content, takes screenshots or performs taps, and it never uninstalls anything itself: it opens Android's own uninstall dialog and the user confirms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Signatures still help
&lt;/h3&gt;

&lt;p&gt;Behaviour catches the unknown; a signed list catches the known before they show a single ad. We publish ours openly: the &lt;a href="https://stoppopups.app/android-adware-list/" rel="noopener noreferrer"&gt;Android adware list&lt;/a&gt; covers 470 apps from published campaigns plus 98 confirmed adware builds, with a JSON download for anyone who wants to use it.&lt;/p&gt;

</description>
      <category>android</category>
      <category>security</category>
      <category>mobile</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>Converting HEIC, WebP and AVIF to JPG without losing EXIF: where the metadata lives</title>
      <dc:creator>Sebastian Balog</dc:creator>
      <pubDate>Fri, 23 Oct 2026 16:25:52 +0000</pubDate>
      <link>https://dev.to/sebastian_balog_c88dc2913/converting-heic-webp-and-avif-to-jpg-without-losing-exif-where-the-metadata-lives-2d85</link>
      <guid>https://dev.to/sebastian_balog_c88dc2913/converting-heic-webp-and-avif-to-jpg-without-losing-exif-where-the-metadata-lives-2d85</guid>
      <description>&lt;p&gt;Most "convert this image to JPG" code looks like decode, then encode, and it works until someone notices that every converted photo now says it was taken today, has no location, and the portrait shots are lying on their side.&lt;/p&gt;

&lt;p&gt;The reason is simple: image encoders encode pixels. SkiaSharp, System.Drawing, most Python one-liners: you hand them a bitmap, you get a JPG back, and the EXIF block, the XMP packet and the file's own timestamps are gone. If you want them in the output, you have to dig them out of the source container yourself and write them back.&lt;/p&gt;

&lt;p&gt;I had to do exactly this for &lt;a href="https://plainjpg.com/" rel="noopener noreferrer"&gt;PlainJPG&lt;/a&gt;, a small Windows converter for WebP, HEIC and AVIF. Here's where the metadata actually sits in each format, and the three gotchas that cost me the most time.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebP: RIFF chunks
&lt;/h2&gt;

&lt;p&gt;A WebP file is a RIFF container: &lt;code&gt;RIFF&lt;/code&gt;, a little-endian size, &lt;code&gt;WEBP&lt;/code&gt;, then a flat list of chunks, each a FourCC plus a 4-byte little-endian length (padded to an even size).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;EXIF&lt;/code&gt; holds a raw TIFF structure (starting &lt;code&gt;II*\0&lt;/code&gt; or &lt;code&gt;MM\0*&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;XMP&lt;/code&gt; (note the trailing space) holds the XMP packet.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;VP8X&lt;/code&gt; is the extended header. Bit &lt;code&gt;0x10&lt;/code&gt; of its first byte says the image has alpha, bit &lt;code&gt;0x02&lt;/code&gt; says it's animated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Walking the chunk list takes about twenty lines. The alpha flag is useful too: it's how you decide whether a WebP should become a PNG instead of a JPG.&lt;/p&gt;

&lt;h2&gt;
  
  
  HEIC and AVIF: items inside the &lt;code&gt;meta&lt;/code&gt; box
&lt;/h2&gt;

&lt;p&gt;HEIC and AVIF are both HEIF, which is ISO base media (the MP4 box format). Metadata isn't a chunk you stumble over; it's an &lt;em&gt;item&lt;/em&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find the top-level &lt;code&gt;meta&lt;/code&gt; box (a FullBox, so skip 4 bytes of version and flags).&lt;/li&gt;
&lt;li&gt;In &lt;code&gt;iinf&lt;/code&gt;, list the items. EXIF is an item of type &lt;code&gt;Exif&lt;/code&gt;. XMP is an item of type &lt;code&gt;mime&lt;/code&gt; whose content type is &lt;code&gt;application/rdf+xml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In &lt;code&gt;iloc&lt;/code&gt;, look up where each item's bytes are: one or more extents, either as absolute file offsets (construction method 0) or relative to the &lt;code&gt;idat&lt;/code&gt; box (method 1).&lt;/li&gt;
&lt;li&gt;Concatenate the extents.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Gotcha 1: the HEIF Exif item isn't bare TIFF.&lt;/strong&gt; It starts with a 4-byte big-endian offset to the TIFF header, and some writers put &lt;code&gt;Exif\0\0&lt;/code&gt; in front of the TIFF as well. Skip the offset, skip the optional prefix, and only then do you have something you can drop into a JPEG.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing it back
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;JPEG.&lt;/strong&gt; EXIF goes in an APP1 segment (&lt;code&gt;FF E1&lt;/code&gt;, a 2-byte big-endian length, &lt;code&gt;Exif\0\0&lt;/code&gt;, then the TIFF bytes). XMP goes in a second APP1 whose payload starts with &lt;code&gt;http://ns.adobe.com/xap/1.0/\0&lt;/code&gt;. Insert them right after SOI, or after the JFIF APP0 if your encoder wrote one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gotcha 2: APP1 has a 64 KB ceiling.&lt;/strong&gt; The length field is 16 bits and counts itself, so the payload can't exceed 65,533 bytes. Some phones embed large maker notes or thumbnails; if the block doesn't fit, you need a plan (skip it, or strip the thumbnail) rather than writing a corrupt file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PNG.&lt;/strong&gt; EXIF has its own chunk, &lt;code&gt;eXIf&lt;/code&gt;, containing the TIFF bytes. XMP goes in an &lt;code&gt;iTXt&lt;/code&gt; chunk with the keyword &lt;code&gt;XML:com.adobe.xmp&lt;/code&gt;. Put both right after &lt;code&gt;IHDR&lt;/code&gt; and compute each chunk's CRC over the type and data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotcha 3: orientation, twice
&lt;/h2&gt;

&lt;p&gt;Phones rarely rotate pixels. They store the sensor's orientation and set EXIF &lt;code&gt;Orientation&lt;/code&gt; (1 to 8) so viewers rotate on display.&lt;/p&gt;

&lt;p&gt;If your converter bakes the rotation into the pixels (sensible, because plenty of software ignores the tag), you must then &lt;strong&gt;set Orientation to 1&lt;/strong&gt; in the EXIF you copy across. Otherwise a viewer that honours the tag rotates the already-upright image again.&lt;/p&gt;

&lt;p&gt;HEIF adds a twist: rotation and mirroring are container properties (&lt;code&gt;irot&lt;/code&gt; and &lt;code&gt;imir&lt;/code&gt;), and a decoder that follows the spec applies them, so the pixels it hands you are already display-oriented. iPhone HEICs usually &lt;em&gt;also&lt;/em&gt; carry an EXIF Orientation value. Apply that one as well and every portrait photo ends up sideways. For HEIF, trust &lt;code&gt;irot&lt;/code&gt;/&lt;code&gt;imir&lt;/code&gt; and treat the EXIF tag as informational.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't forget the file's own dates
&lt;/h2&gt;

&lt;p&gt;EXIF &lt;code&gt;DateTimeOriginal&lt;/code&gt; is what photo apps sort by, but File Explorer sorts by the file system's created and modified times, and a new file gets "now". After writing the output, copy them over:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetLastWriteTimeUtc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetLastWriteTimeUtc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetCreationTimeUtc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetCreationTimeUtc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A quick check
&lt;/h2&gt;

&lt;p&gt;After converting, open the JPG's Properties, then Details in Windows. If "Date taken" is filled in and portrait photos stand upright in both Photos and a browser, the EXIF made it across and the orientation was handled once, not twice.&lt;/p&gt;

&lt;p&gt;If you'd rather not write any of this, &lt;a href="https://plainjpg.com/" rel="noopener noreferrer"&gt;PlainJPG&lt;/a&gt; does it for whole folders of WebP, HEIC and AVIF on Windows, offline. There's also a plain-English guide to &lt;a href="https://plainjpg.com/articles/batch-convert-heic-to-jpg-windows/" rel="noopener noreferrer"&gt;batch converting HEIC to JPG on Windows&lt;/a&gt; for the non-developers in your life who keep sending you .heic files.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>webdev</category>
      <category>windows</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Two Codex accounts on Windows: CODEX_HOME in PowerShell, cmd and Windows Terminal</title>
      <dc:creator>Sebastian Balog</dc:creator>
      <pubDate>Wed, 21 Oct 2026 18:48:31 +0000</pubDate>
      <link>https://dev.to/sebastian_balog_c88dc2913/two-codex-accounts-on-windows-codexhome-in-powershell-cmd-and-windows-terminal-44ef</link>
      <guid>https://dev.to/sebastian_balog_c88dc2913/two-codex-accounts-on-windows-codexhome-in-powershell-cmd-and-windows-terminal-44ef</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure up front: I build &lt;a href="https://multiplecodex.com/" rel="noopener noreferrer"&gt;Sessions Pro for Codex&lt;/a&gt;, a paid app that does this for the desktop app too. Everything up to the last section is free and needs nothing but the commands below.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Most guides for running two Codex accounts are written for macOS and Linux: &lt;code&gt;export CODEX_HOME=...&lt;/code&gt;, an alias in &lt;code&gt;~/.zshrc&lt;/code&gt;, done. On Windows the idea is the same, but the syntax isn't, and there are a few Windows-only details worth knowing. All the commands here were run on Windows 11.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Codex decides which account you're signed in to
&lt;/h2&gt;

&lt;p&gt;The Codex CLI doesn't keep a login per terminal window. It keeps one login per folder: &lt;code&gt;CODEX_HOME&lt;/code&gt;. On Windows that's &lt;code&gt;%USERPROFILE%\.codex&lt;/code&gt; unless you set the variable. The folder holds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;auth.json&lt;/code&gt;: the login&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;config.toml&lt;/code&gt;: your settings, including MCP servers&lt;/li&gt;
&lt;li&gt;your session history and threads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One folder, one account. Point &lt;code&gt;CODEX_HOME&lt;/code&gt; at a second folder, sign in there once, and that folder stays signed in to the second account.&lt;/p&gt;

&lt;p&gt;The ChatGPT desktop app from the Microsoft Store (its package is called &lt;code&gt;OpenAI.Codex&lt;/code&gt;) uses the same &lt;code&gt;%USERPROFILE%\.codex&lt;/code&gt; for its Codex data. So by default, &lt;code&gt;codex&lt;/code&gt; in your terminal and Codex in the app share one login. Keep that in mind for &lt;code&gt;codex logout&lt;/code&gt;, below. ChatGPT's built-in account switcher doesn't change this either: it only works on the web version, which doesn't help if you build real projects in the desktop app, and it doesn't touch the CLI's login.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which codex are you running?
&lt;/h2&gt;

&lt;p&gt;If you installed the CLI yourself (for example with &lt;code&gt;npm install -g @openai/codex&lt;/code&gt;), &lt;code&gt;codex&lt;/code&gt; is on your PATH. The Store app also ships its own &lt;code&gt;codex.exe&lt;/code&gt; inside its package folder, and you can find it from 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="n"&gt;Join-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Get-AppxPackage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OpenAI.Codex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;InstallLocation&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'app\resources\codex.exe'&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Either one reads &lt;code&gt;CODEX_HOME&lt;/code&gt; the same way.&lt;/p&gt;

&lt;h2&gt;
  
  
  PowerShell
&lt;/h2&gt;

&lt;p&gt;Create the folder first. Codex won't create it for you:&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;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="bp"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;\.codex-work"&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;span class="n"&gt;Out-Null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then start Codex pointed at it:&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="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;CODEX_HOME&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;span class="s2"&gt;"&lt;/span&gt;&lt;span class="bp"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;\.codex-work"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;codex&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sign in with your second account. From now on, any &lt;code&gt;codex&lt;/code&gt; started from this PowerShell window uses &lt;code&gt;.codex-work&lt;/code&gt;. Open a new window and plain &lt;code&gt;codex&lt;/code&gt; is back on your first account.&lt;/p&gt;

&lt;p&gt;To check where you stand before doing anything:&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="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;CODEX_HOME&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="c"&gt;# empty means the default %USERPROFILE%\.codex&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;codex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="c"&gt;# "Logged in using ChatGPT" or "Not logged in"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you forget to create the folder, Codex stops with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error loading configuration: CODEX_HOME points to "C:\\Users\\you\\.codex-work", but that path does not exist
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Make it one word
&lt;/h3&gt;

&lt;p&gt;Add a function to your PowerShell profile (&lt;code&gt;notepad $PROFILE&lt;/code&gt;, create the file if it doesn't exist):&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="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;codex-work&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="nv"&gt;$previous&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;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;CODEX_HOME&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;CODEX_HOME&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;span class="s2"&gt;"&lt;/span&gt;&lt;span class="bp"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;\.codex-work"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;try&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="n"&gt;codex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;args&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="kr"&gt;finally&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="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;CODEX_HOME&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;span class="nv"&gt;$previous&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;p&gt;&lt;code&gt;codex-work&lt;/code&gt; now runs Codex in the work account and puts the window back the way it was afterwards, so a later plain &lt;code&gt;codex&lt;/code&gt; in the same window still uses your first account. Add one function per account.&lt;/p&gt;

&lt;h2&gt;
  
  
  cmd
&lt;/h2&gt;

&lt;p&gt;In Command Prompt, set the variable for the session, then run Codex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;%USERPROFILE%&lt;/span&gt;&lt;span class="s2"&gt;\.codex-work"&lt;/span&gt;
&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="s2"&gt;"CODEX_HOME=&lt;/span&gt;&lt;span class="nv"&gt;%USERPROFILE%&lt;/span&gt;&lt;span class="s2"&gt;\.codex-work"&lt;/span&gt;
&lt;span class="kd"&gt;codex&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the quoted form of &lt;code&gt;set&lt;/code&gt;. Without quotes, &lt;code&gt;set CODEX_HOME=... &amp;amp;&amp;amp; codex&lt;/code&gt; stores the space before &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; as part of the value. Codex happened to cope with that in my tests, but a variable with an invisible trailing space is the kind of thing that breaks something else later.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Windows Terminal profile per account
&lt;/h2&gt;

&lt;p&gt;Windows Terminal makes this tidy: one profile per account, each opening already pointed at the right folder. In Settings, add a new profile and set its &lt;strong&gt;Command line&lt;/strong&gt; to:&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;powershell.exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-NoExit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;CODEX_HOME&lt;/span&gt;&lt;span class="s2"&gt; = Join-Path &lt;/span&gt;&lt;span class="bp"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt; '.codex-work'; codex"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Name it something like "Codex (work)" and give it its own tab color, so you can tell at a glance which account a tab is using.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't set it permanently
&lt;/h2&gt;

&lt;p&gt;It's tempting to run &lt;code&gt;setx CODEX_HOME ...&lt;/code&gt; and be done. Don't: a user-level variable is inherited by every program you start afterwards, so every &lt;code&gt;codex&lt;/code&gt; would use that folder and you'd be back to one account, just a different one. Set &lt;code&gt;CODEX_HOME&lt;/code&gt; per window, per function or per Terminal profile instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about WSL?
&lt;/h2&gt;

&lt;p&gt;Inside WSL, &lt;code&gt;~&lt;/code&gt; is your Linux home, not your Windows one. So &lt;code&gt;codex&lt;/code&gt; running in WSL uses &lt;code&gt;~/.codex&lt;/code&gt; on the Linux side, a different folder from the Windows &lt;code&gt;%USERPROFILE%\.codex&lt;/code&gt;. That makes WSL a second, separate login by accident. It's fine if you want it, confusing if you don't. The same &lt;code&gt;CODEX_HOME&lt;/code&gt; trick works there with the usual &lt;code&gt;export&lt;/code&gt; syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;codex logout&lt;/code&gt; and the shared folder
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;codex logout&lt;/code&gt; removes the login from the current &lt;code&gt;CODEX_HOME&lt;/code&gt;. If that's the default folder, every &lt;code&gt;codex&lt;/code&gt; reading it is signed out at once, and by default that includes Codex in the desktop app. With one folder per account, logging out of one leaves the others alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to copy between folders
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Copy &lt;code&gt;config.toml&lt;/code&gt;&lt;/strong&gt; if you want the same settings and MCP servers in both accounts: &lt;code&gt;Copy-Item "$HOME\.codex\config.toml" "$HOME\.codex-work\"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't copy &lt;code&gt;auth.json&lt;/code&gt;.&lt;/strong&gt; That's the login. Copying it puts your first account into the second folder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leave history alone.&lt;/strong&gt; Each folder keeps its own sessions, which is the point.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The desktop app is the hard part
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;CODEX_HOME&lt;/code&gt; only separates the command line. The ChatGPT desktop app keeps using its own data and &lt;code&gt;%USERPROFILE%\.codex&lt;/code&gt;, so it still holds one account at a time.&lt;/p&gt;

&lt;p&gt;On a Mac you can make a second copy of the app with its own data folder. On Windows the app comes from the Microsoft Store and lives in a protected package folder, so that route isn't really open. The free option on Windows is a &lt;strong&gt;second Windows user account&lt;/strong&gt;: each user gets their own app data and their own &lt;code&gt;.codex&lt;/code&gt;, and both can stay signed in if you switch users instead of signing out. It works well when two people share a PC, and it's clumsy for one person flipping between work and personal all day.&lt;/p&gt;

&lt;p&gt;That gap is what &lt;a href="https://multiplecodex.com/" rel="noopener noreferrer"&gt;Sessions Pro for Codex&lt;/a&gt; fills. Each account gets its own profile that runs the ChatGPT app you already have in its own window, with its own login, chats, Codex threads and settings, and its own taskbar button, title and color. The "Codex CLI in Terminal" button opens a terminal with that profile's own &lt;code&gt;CODEX_HOME&lt;/code&gt;, so the command line is signed in to the same account as the window. It's $24.99 once, for two computers (Mac or PC), with a free 1-hour preview, and needs Windows 10 or 11 with the ChatGPT app from the Microsoft Store.&lt;/p&gt;

&lt;p&gt;For the command line alone, though, everything above is free. One folder per account, one function or Terminal profile per folder, and you'll stop signing out to switch.&lt;/p&gt;

</description>
      <category>codex</category>
      <category>windows</category>
      <category>powershell</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to run multiple Claude accounts at once (Desktop + Claude Code), and why the obvious hacks break</title>
      <dc:creator>Sebastian Balog</dc:creator>
      <pubDate>Mon, 12 Oct 2026 23:52:50 +0000</pubDate>
      <link>https://dev.to/sebastian_balog_c88dc2913/how-to-run-multiple-claude-accounts-at-once-desktop-claude-code-and-why-the-obvious-hacks-break-19jb</link>
      <guid>https://dev.to/sebastian_balog_c88dc2913/how-to-run-multiple-claude-accounts-at-once-desktop-claude-code-and-why-the-obvious-hacks-break-19jb</guid>
      <description>&lt;p&gt;&lt;em&gt;Disclosure up front: I build &lt;a href="https://doubleclaude.com" rel="noopener noreferrer"&gt;Claude Sessions Pro&lt;/a&gt;, a paid app for Mac and Windows that does this. Most of this post is the free way to do it yourself, plus what I learned about why the DIY versions misbehave. The app gets one short section near the end.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you have a company Claude account and a personal one, or one account per client, you've hit this: Claude Desktop is signed in to &lt;strong&gt;one&lt;/strong&gt; account. To check the other one, you sign out, sign in, lose your place, and do it again an hour later.&lt;/p&gt;

&lt;p&gt;Claude Code in the terminal has the same problem, just with a different config folder.&lt;/p&gt;

&lt;p&gt;Here's how to fix it, from "free, two lines of shell" to "one click", and the gotchas nobody mentions until you've already set it up.&lt;/p&gt;

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

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You want&lt;/th&gt;
&lt;th&gt;Do this&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Two Claude Code (CLI) accounts&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;CLAUDE_CONFIG_DIR=~/.claude-work claude&lt;/code&gt; for the second one&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Two Claude Desktop windows, free&lt;/td&gt;
&lt;td&gt;Start a second copy with &lt;code&gt;--user-data-dir&lt;/code&gt; (commands below)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Separate Dock icons, ‚åò-Tab, Google sign-in that lands in the right window, survives updates&lt;/td&gt;
&lt;td&gt;You need each account to be its own &lt;em&gt;app&lt;/em&gt;, not just its own folder (see "Why the hacks break")&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Why Claude Desktop can only hold one login
&lt;/h2&gt;

&lt;p&gt;Claude Desktop is an Electron app, so it's Chromium underneath. Everything for the signed-in account (session cookies, settings, connectors, MCP config, the list of Claude Code sessions) lives in one &lt;strong&gt;user data directory&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;macOS: &lt;code&gt;~/Library/Application Support/Claude&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Windows: &lt;code&gt;%APPDATA%\Claude&lt;/code&gt; (the Microsoft Store version redirects this into its package folder, under &lt;code&gt;%LOCALAPPDATA%\Packages\Claude_‚Ä¶\LocalCache\Roaming\Claude&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One folder, one cookie jar, one login. Signing in to account B overwrites account A's session.&lt;/p&gt;

&lt;p&gt;Your chats aren't lost when you switch; they live in your account on Anthropic's side. What you lose is time, context, and the ability to see both at once.&lt;/p&gt;

&lt;p&gt;So every working solution comes down to the same idea: &lt;strong&gt;give each account its own data directory.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude Code (CLI): one environment variable
&lt;/h2&gt;

&lt;p&gt;The CLI is the easy part. It reads its login and settings from a config directory, which you can override:&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;# second account, one-off&lt;/span&gt;
&lt;span class="nv"&gt;CLAUDE_CONFIG_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;~/.claude-work claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make it permanent with an alias in &lt;code&gt;~/.zshrc&lt;/code&gt; or &lt;code&gt;~/.bashrc&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;&lt;span class="nb"&gt;alias &lt;/span&gt;claude-work&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'CLAUDE_CONFIG_DIR="$HOME/.claude-work" claude'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;claude-personal&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'CLAUDE_CONFIG_DIR="$HOME/.claude-personal" claude'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;claude-work&lt;/code&gt; once, log in with the work account, done. Each folder keeps its own login, history and settings. This works the same on macOS, Linux and Windows (in PowerShell: &lt;code&gt;$env:CLAUDE_CONFIG_DIR="$HOME\.claude-work"; claude&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;For the full Claude Code setup, with Windows Terminal profiles, tmux splits, VS Code, an account per project folder and the gotchas that quietly put both terminals on the same login, see &lt;a href="https://dev.to/sebastian_balog_c88dc2913/run-two-claude-code-accounts-side-by-side-without-logging-out-mac-windows-vs-code-56md"&gt;Run two Claude Code accounts side by side without logging out&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude Desktop on macOS: a second copy, for free
&lt;/h2&gt;

&lt;p&gt;Chromium apps accept &lt;code&gt;--user-data-dir&lt;/code&gt;, and Claude Desktop honors it. This starts a second, independent Claude next to your normal one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;open &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; Claude &lt;span class="nt"&gt;--args&lt;/span&gt; &lt;span class="nt"&gt;--user-data-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Library/Application Support/Claude-Work"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-n&lt;/code&gt; opens a new instance even though Claude is already running.&lt;/li&gt;
&lt;li&gt;Everything after &lt;code&gt;--args&lt;/code&gt; goes to Claude itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sign in to the second account in the new window. Wrap it in a shell function so you can have as many as you want:&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;# ~/.zshrc&lt;/span&gt;
claude-profile&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;:?usage:&lt;span class="p"&gt; claude-profile &amp;lt;name&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  open &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; Claude &lt;span class="nt"&gt;--args&lt;/span&gt; &lt;span class="nt"&gt;--user-data-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/Library/Application Support/Claude-&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude-profile Work
claude-profile ClientA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Want it clickable? Open &lt;strong&gt;Script Editor&lt;/strong&gt;, paste &lt;code&gt;do shell script "open -n -a Claude --args --user-data-dir=$HOME/Library/Application\\ Support/Claude-Work"&lt;/code&gt;, then &lt;strong&gt;File ‚Üí Export ‚Üí File Format: Application&lt;/strong&gt;. Drop it in the Dock.&lt;/p&gt;

&lt;p&gt;That's the whole free method, and for a lot of people it's enough. Now the part the copy-paste guides skip.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the hacks break (the interesting part)
&lt;/h2&gt;

&lt;p&gt;All of these come from one fact: &lt;strong&gt;to the operating system, both windows are still the same app.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. One Dock icon, one ‚åò-Tab entry
&lt;/h3&gt;

&lt;p&gt;macOS groups windows by bundle identifier (&lt;code&gt;com.anthropic.claudefordesktop&lt;/code&gt;). Your two instances share it, so they share a Dock icon, a name, and a single ‚åò-Tab slot. You can't tell which window is which account without looking inside it.&lt;/p&gt;

&lt;p&gt;A Script Editor launcher doesn't fix this. The launcher is its own app, but the Claude window it opens still belongs to Claude.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Google sign-in comes back to the wrong window
&lt;/h3&gt;

&lt;p&gt;This one costs people the most time. When you click &lt;strong&gt;Continue with Google&lt;/strong&gt;, Claude opens your browser. After you log in, the browser hands the result back through a &lt;code&gt;claude://&lt;/code&gt; link.&lt;/p&gt;

&lt;p&gt;The OS routes that link to &lt;em&gt;the app registered for &lt;code&gt;claude://&lt;/code&gt;&lt;/em&gt;, not to the specific window that started the login. With two instances of the same app, the link goes to whichever instance the OS picks, usually the first one. So you sign in to your work account and it lands in your personal window, or nowhere useful.&lt;/p&gt;

&lt;p&gt;On Windows it's even more deterministic. Chromium's single-instance logic means a new launch first checks for a lock file in the &lt;strong&gt;default&lt;/strong&gt; data folder; if that instance is running, the link gets forwarded to it. So the default &lt;code&gt;Claude&lt;/code&gt; window always wins.&lt;/p&gt;

&lt;p&gt;Workarounds: use email sign-in for the extra profiles, or quit every other Claude window while you sign in to the new one.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Claude Code sessions don't follow you
&lt;/h3&gt;

&lt;p&gt;The Code tab in Claude Desktop lists sessions from the data directory it's using. A fresh &lt;code&gt;Claude-Work&lt;/code&gt; folder starts empty, even if that account has sessions in your main Claude. They aren't gone; they're in the other folder. You'd have to copy the right ones over by hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. "Just copy Claude.app and rename it" doesn't survive updates
&lt;/h3&gt;

&lt;p&gt;The natural next step is duplicating &lt;code&gt;Claude.app&lt;/code&gt;, changing its bundle ID and name in &lt;code&gt;Info.plist&lt;/code&gt;, and re-signing it, so each account really is a separate app with its own Dock icon. That does fix #1.&lt;/p&gt;

&lt;p&gt;But Claude updates itself, and an update can bring back the original bundle or leave you with a copy that's stuck on an old version. Then you're redoing the copy, re-signing, and re-pointing it at the right data folder after every Claude release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude Desktop on Windows: the same trick
&lt;/h2&gt;

&lt;p&gt;Claude for Windows installs through the Microsoft Store, with a command alias you can call directly. In 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="n"&gt;Start-Process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;LOCALAPPDATA&lt;/span&gt;&lt;span class="s2"&gt;\Microsoft\WindowsApps\claude-desktop.exe"&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;-ArgumentList&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"--user-data-dir=&lt;/span&gt;&lt;span class="se"&gt;`"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;USERPROFILE&lt;/span&gt;&lt;span class="s2"&gt;\ClaudeProfiles\Work&lt;/span&gt;&lt;span class="se"&gt;`"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same rules as on the Mac: each &lt;code&gt;--user-data-dir&lt;/code&gt; is a separate login. And the same gotchas apply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All windows share one taskbar icon and the title "Claude".&lt;/li&gt;
&lt;li&gt;Google sign-in returns to the &lt;em&gt;default&lt;/em&gt; Claude window (see #2), so sign in to extra profiles with email, or close the main Claude first.&lt;/li&gt;
&lt;li&gt;If Claude's own "start with Windows" setting is on, the default instance is always running and always catches the sign-in.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The other options, briefly
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A second browser profile with claude.ai.&lt;/strong&gt; Totally fine for chatting. You lose the desktop-only features for that account: the Code tab, local MCP servers and desktop connectors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A second OS user account.&lt;/strong&gt; Fully isolated, including Claude Code. But you only see one user's desktop at a time, and none of your files or apps come along.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sign out and back in.&lt;/strong&gt; Free and built in. Fine weekly, painful hourly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apps that do it for you.&lt;/strong&gt; Parall (a general launcher for many apps, $9.99 in the Mac App Store), Multi-Claude ($20) and Claude Sessions Pro ($15) all turn each account into its own app.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;I got tired of doing all of the above by hand, so I built &lt;a href="https://doubleclaude.com" rel="noopener noreferrer"&gt;Claude Sessions Pro&lt;/a&gt; for macOS and Windows. On a Mac it makes each account a real, separate Mac app built from your installed Claude, which is what fixes the gotchas above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Own app per account:&lt;/strong&gt; "Claude Work", "Claude Personal", each with a colored letter badge on its Dock icon and its own ‚åò-Tab spot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google sign-in works with the other accounts still open&lt;/strong&gt;, and returns to the profile that asked for it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Code sessions and pins come along:&lt;/strong&gt; sessions from your main Claude move into the matching account's profile, and the CLI opens per profile with its own &lt;code&gt;CLAUDE_CONFIG_DIR&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Survives Claude updates:&lt;/strong&gt; when Claude updates, each profile app is rebuilt from the new version the next time it isn't running. Logins and data stay put.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Menu bar switcher&lt;/strong&gt; to open or switch accounts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's $15 one-time for up to 2 computers, with a &lt;strong&gt;1-hour free preview&lt;/strong&gt; that starts once you've signed in to a profile. I'd rather you see it working with your own accounts before paying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It runs on Windows too.&lt;/strong&gt; Same idea, built for Windows' quirks: each account opens in its own Claude window labeled with the account name, and Google sign-in is routed back to the window that started it. It works on Windows 10 and 11, and one license covers 2 computers, Mac or PC.&lt;/p&gt;

&lt;p&gt;Here's the full comparison table with every method: &lt;a href="https://doubleclaude.com/run-multiple-claude-accounts-mac/" rel="noopener noreferrer"&gt;How to run multiple Claude accounts on one Mac&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A one-page overview is also on Google Sites: &lt;a href="https://sites.google.com/view/claude-sessions-pro" rel="noopener noreferrer"&gt;Claude Sessions Pro&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is this allowed?
&lt;/h2&gt;

&lt;p&gt;Plenty of people have legitimate separate accounts: a company Team account plus a personal Pro one, or one per client. Everything above runs the official Claude app and doesn't change how Claude works.&lt;/p&gt;

&lt;p&gt;But Anthropic's terms apply to &lt;em&gt;each&lt;/em&gt; account. Creating extra accounts specifically to dodge usage limits is the kind of thing that gets accounts suspended. Read the Consumer Terms and Usage Policy, and only use accounts you're allowed to use.&lt;/p&gt;




&lt;p&gt;If you've found another approach (or another gotcha), drop it in the comments. I'm especially curious how people handle this on Linux, where Claude Desktop isn't official.&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>productivity</category>
      <category>macos</category>
    </item>
    <item>
      <title>Stop Instagram and TikTok labelling your Photoshop and Premiere exports as AI</title>
      <dc:creator>Sebastian Balog</dc:creator>
      <pubDate>Mon, 05 Oct 2026 01:58:20 +0000</pubDate>
      <link>https://dev.to/sebastian_balog_c88dc2913/stop-instagram-and-tiktok-labelling-your-photoshop-and-premiere-exports-as-ai-27lk</link>
      <guid>https://dev.to/sebastian_balog_c88dc2913/stop-instagram-and-tiktok-labelling-your-photoshop-and-premiere-exports-as-ai-27lk</guid>
      <description>&lt;p&gt;&lt;strong&gt;Quick fix:&lt;/strong&gt; the label comes from Content Credentials (C2PA) that Photoshop and Premiere Pro write into your export after a generative edit, and export settings don't switch them off. Check every file as it lands in your export folder and remove those credentials before posting: below is a free script that does it, and &lt;a href="https://metacleanai.com/remove-metadata-photoshop/" rel="noopener noreferrer"&gt;an app that does it for you&lt;/a&gt; on Mac and Windows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why your exports get labelled
&lt;/h2&gt;

&lt;p&gt;If you edit for clients or post every day, the "AI info" problem isn't one photo. It's every export. One Generative Fill in Photoshop or two seconds of Generative Extend in Premiere Pro, and the file you deliver carries &lt;strong&gt;Content Credentials (C2PA)&lt;/strong&gt; that Instagram, Facebook, TikTok, YouTube and LinkedIn read and turn into a label.&lt;/p&gt;

&lt;p&gt;Adobe's own FAQ says that when its generative tools create or modify content, C2PA metadata is attached automatically and can't be switched off for that content. Photoshop's &lt;em&gt;Export As → Metadata: None&lt;/em&gt; controls camera and copyright info, not that record. So the dependable place to check is &lt;strong&gt;the exported file&lt;/strong&gt;, right after it lands in your export folder.&lt;/p&gt;

&lt;p&gt;Here's how to automate that check yourself, and the gotchas that make it harder than it looks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to look for
&lt;/h2&gt;

&lt;p&gt;Two markers do almost all the labelling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;C2PA manifest&lt;/strong&gt;: JUMBF boxes labelled &lt;code&gt;c2pa&lt;/code&gt; (in JPEG they sit in &lt;code&gt;APP11&lt;/code&gt; segments; in MP4/MOV in a top-level &lt;code&gt;uuid&lt;/code&gt; box).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPTC digital source type&lt;/strong&gt;: &lt;code&gt;Iptc4xmpExt:DigitalSourceType&lt;/code&gt; set to &lt;code&gt;trainedAlgorithmicMedia&lt;/code&gt; or &lt;code&gt;compositeWithTrainedAlgorithmicMedia&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A quick check for one file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;c2patool &lt;span class="s2"&gt;"export.jpg"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"C2PA manifest present"&lt;/span&gt;
exiftool &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-if&lt;/span&gt; &lt;span class="s1"&gt;'$XMP-iptcExt:DigitalSourceType =~ /TrainedAlgorithmic/i'&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s1"&gt;'$FileName: AI source tag'&lt;/span&gt; &lt;span class="s2"&gt;"export.jpg"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A DIY watcher (macOS, fswatch)
&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;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="c"&gt;# watch-exports.sh: flag new exports that carry AI metadata&lt;/span&gt;
&lt;span class="c"&gt;# needs: brew install fswatch exiftool c2patool&lt;/span&gt;
&lt;span class="nv"&gt;DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="p"&gt;/Exports&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

settled&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;               &lt;span class="c"&gt;# wait until the editor has finished writing&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; a b
  &lt;span class="k"&gt;while&lt;/span&gt; :&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;stat&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; %z &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;1
    &lt;span class="nb"&gt;sleep &lt;/span&gt;2
    &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;stat&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; %z &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;1
    &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$b&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return &lt;/span&gt;0
  &lt;span class="k"&gt;done&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

check&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;hits&lt;/span&gt;&lt;span class="o"&gt;=()&lt;/span&gt;
  c2patool &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; hits+&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"C2PA"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  exiftool &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;-if&lt;/span&gt; &lt;span class="s1"&gt;'$XMP-iptcExt:DigitalSourceType =~ /TrainedAlgorithmic/i'&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; x &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; x &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; hits+&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="s2"&gt;"IPTC AI tag"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="k"&gt;${#&lt;/span&gt;&lt;span class="nv"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;[@]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;osascript &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"display notification &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;[*]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; with title &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;AI metadata: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

fswatch &lt;span class="nt"&gt;-0&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s1"&gt;'.*'&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'\.(jpe?g|png|mp4|mov)$'&lt;/span&gt; &lt;span class="nt"&gt;--event&lt;/span&gt; Created &lt;span class="nt"&gt;--event&lt;/span&gt; Updated &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; |
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; f&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; clean_&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;continue
  &lt;/span&gt;settled &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; check &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works, and it's a good way to see how often your exports actually carry these markers. The parts that take the most care:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Finished writing" is the hard part.&lt;/strong&gt; Premiere and Media Encoder write large files over minutes; Photoshop writes a temp file and renames it. The size-stable loop above is the simplest heuristic; a render that pauses mid-write can still fool it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recursion and noise.&lt;/strong&gt; Editors create sidecar and cache files; filter by extension and ignore your own &lt;code&gt;clean_&lt;/code&gt; outputs or you'll loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cleaning without damage.&lt;/strong&gt; The naive &lt;code&gt;exiftool -all=&lt;/code&gt; also deletes the colour profile and orientation. Use &lt;code&gt;exiftool -all= -tagsfromfile @ -icc_profile -orientation file.jpg&lt;/code&gt; for photos, and a stream-copy remux for video: &lt;code&gt;ffmpeg -i in.mp4 -map 0 -c copy -map_metadata -1 out.mp4&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verifying.&lt;/strong&gt; Re-run the checks on the output (&lt;code&gt;c2patool&lt;/code&gt; should say &lt;em&gt;No claim found&lt;/em&gt;), and for video compare &lt;code&gt;ffmpeg -f streamhash&lt;/code&gt; of input and output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows.&lt;/strong&gt; No fswatch; you'd rebuild this around PowerShell's &lt;code&gt;FileSystemWatcher&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The app version
&lt;/h2&gt;

&lt;p&gt;I got tired of maintaining scripts like this, so it became a feature in &lt;a href="https://metacleanai.com/remove-metadata-photoshop/" rel="noopener noreferrer"&gt;MetaClean&lt;/a&gt;, my Mac and Windows metadata app. &lt;strong&gt;Watch Folders&lt;/strong&gt; runs in the background on your export folders, subfolders included. Every new JPG, PNG, MP4 or MOV is checked once it has finished saving, whether it came from Photoshop, Lightroom, &lt;a href="https://metacleanai.com/premiere-pro-ai-label/" rel="noopener noreferrer"&gt;Premiere Pro or Media Encoder&lt;/a&gt;, CapCut or was just copied in. Files without AI metadata never interrupt you. When one carries Content Credentials or an AI-origin tag, a compact prompt lists what was found, and &lt;strong&gt;Clean&lt;/strong&gt; saves a verified &lt;code&gt;clean_&lt;/code&gt; copy next to the original: no re-encoding, colour profile and orientation kept, video streams copied as they are. For existing archives there's a batch mode for whole folders. Everything stays on your machine. 3-day free trial, then $5 once.&lt;/p&gt;

&lt;p&gt;Disclosure: I'm the developer of MetaClean.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Generative edits in Photoshop and Premiere attach C2PA automatically; export settings don't remove it.&lt;/li&gt;
&lt;li&gt;Check exports with &lt;code&gt;c2patool&lt;/code&gt; and the IPTC &lt;code&gt;DigitalSourceType&lt;/code&gt; tag.&lt;/li&gt;
&lt;li&gt;Automate with a folder watcher, but handle "file finished", recursion, safe cleaning and verification.&lt;/li&gt;
&lt;li&gt;Or let &lt;a href="https://metacleanai.com/remove-metadata-photoshop/" rel="noopener noreferrer"&gt;MetaClean's Watch Folders&lt;/a&gt; do it on Mac and Windows.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>photography</category>
      <category>video</category>
      <category>automation</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to remove the "AI-generated" label from your TikTok videos (CapCut fix)</title>
      <dc:creator>Sebastian Balog</dc:creator>
      <pubDate>Mon, 05 Oct 2026 01:57:49 +0000</pubDate>
      <link>https://dev.to/sebastian_balog_c88dc2913/how-to-remove-the-ai-generated-label-from-your-tiktok-videos-capcut-fix-9op</link>
      <guid>https://dev.to/sebastian_balog_c88dc2913/how-to-remove-the-ai-generated-label-from-your-tiktok-videos-capcut-fix-9op</guid>
      <description>&lt;p&gt;&lt;strong&gt;Quick fix:&lt;/strong&gt; TikTok reads AI metadata inside the MP4, not your footage. Delete the labelled post, strip the metadata from your original export with one &lt;code&gt;ffmpeg&lt;/code&gt; command (below, no re-encoding) or with &lt;a href="https://metacleanai.com/remove-ai-generated-label-tiktok/" rel="noopener noreferrer"&gt;MetaClean&lt;/a&gt;, and repost the clean copy with the AI-generated content switch off.&lt;/p&gt;

&lt;p&gt;Here's why it happens, how to see it in your own files, and how to prove the fix didn't touch quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why your real video got labelled
&lt;/h2&gt;

&lt;p&gt;You film something yourself, add one AI effect in CapCut, export, post, and TikTok puts &lt;strong&gt;"AI-generated"&lt;/strong&gt; on it. The footage is yours. The label disagrees.&lt;/p&gt;

&lt;p&gt;Like Instagram's "AI info", TikTok's automatic label is mostly a &lt;strong&gt;metadata&lt;/strong&gt; decision. TikTok has said it reads &lt;a href="https://newsroom.tiktok.com/en-us/partnering-with-our-industry-to-advance-ai-transparency-and-literacy" rel="noopener noreferrer"&gt;Content Credentials (C2PA)&lt;/a&gt; to label AI content automatically, and editing apps write AI markers into the files they export after an AI feature is used. So the useful question isn't "what does the video look like?" but "what does the MP4 say about itself?"&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the label comes from
&lt;/h2&gt;

&lt;p&gt;TikTok adds "AI-generated" in two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;You switch it on&lt;/strong&gt; in the post settings ("AI-generated content").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatically&lt;/strong&gt;, when the uploaded file carries AI metadata.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The second one is the surprise. Typical sources:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;App or feature&lt;/th&gt;
&lt;th&gt;What you did&lt;/th&gt;
&lt;th&gt;What ends up in the file&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CapCut AI features&lt;/td&gt;
&lt;td&gt;AI effects, enhancements, generated elements&lt;/td&gt;
&lt;td&gt;AI metadata in the export&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Premiere Pro Generative Extend&lt;/td&gt;
&lt;td&gt;Stretched a clip by a few frames&lt;/td&gt;
&lt;td&gt;C2PA Content Credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI video generators&lt;/td&gt;
&lt;td&gt;B-roll, backgrounds, intros&lt;/td&gt;
&lt;td&gt;C2PA Content Credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI upscalers / enhancers&lt;/td&gt;
&lt;td&gt;Sharpen, stabilise, upscale&lt;/td&gt;
&lt;td&gt;C2PA or IPTC, depending on the app&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One AI touch is enough for the whole video, because the note describes the file, not the frame.&lt;/p&gt;

&lt;h2&gt;
  
  
  Look inside the MP4
&lt;/h2&gt;

&lt;p&gt;An MP4 is a tree of boxes (atoms). Regular metadata lives in &lt;code&gt;moov/udta&lt;/code&gt; and &lt;code&gt;meta&lt;/code&gt;; a C2PA manifest is stored as its own JUMBF payload in a top-level &lt;code&gt;uuid&lt;/code&gt; box, next to the audio and video data rather than inside it. That's why the usual "Properties → Details" view doesn't show it.&lt;/p&gt;

&lt;p&gt;Dump everything ExifTool can see, grouped by where it lives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;exiftool &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-G1&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; clip.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for the encoder and creation tool (&lt;code&gt;Encoder&lt;/code&gt;, &lt;code&gt;Software&lt;/code&gt;, &lt;code&gt;HandlerVendorID&lt;/code&gt;), any XMP block, and anything mentioning AI, AIGC or C2PA:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;exiftool &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-G1&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; clip.mp4 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s1"&gt;'c2pa|jumd|aigc|digitalsource|encoder|software'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the signed manifest itself, the official &lt;a href="https://github.com/contentauth/c2pa-rs" rel="noopener noreferrer"&gt;c2patool&lt;/a&gt; reads MP4 and MOV directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;c2patool clip.mp4
&lt;span class="c"&gt;# prints the manifest: claim generator, actions, digitalSourceType...&lt;/span&gt;
&lt;span class="c"&gt;# or "No claim found" if there is none&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And while you're in there, check the stuff you probably didn't mean to share: phones write a recording location and the device model into the &lt;code&gt;udta&lt;/code&gt; atoms.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;exiftool &lt;span class="nt"&gt;-GPSCoordinates&lt;/span&gt; &lt;span class="nt"&gt;-Model&lt;/span&gt; &lt;span class="nt"&gt;-Make&lt;/span&gt; &lt;span class="nt"&gt;-CreationDate&lt;/span&gt; clip.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Removing it without re-encoding
&lt;/h2&gt;

&lt;p&gt;Re-exporting the video to "shake off" metadata costs quality and often writes the same markers again. The clean way is a &lt;strong&gt;remux&lt;/strong&gt;: copy the existing video and audio streams into a new container and leave the metadata boxes behind.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; clip.mp4 &lt;span class="nt"&gt;-map&lt;/span&gt; 0 &lt;span class="nt"&gt;-c&lt;/span&gt; copy &lt;span class="nt"&gt;-map_metadata&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;-movflags&lt;/span&gt; +faststart clean.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-c copy&lt;/code&gt; means no decoding and no re-encoding: same frames, same bitrate.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-map_metadata -1&lt;/code&gt; drops the global metadata (including the location and device atoms).&lt;/li&gt;
&lt;li&gt;The C2PA &lt;code&gt;uuid&lt;/code&gt; box isn't carried over by the remux.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;+faststart&lt;/code&gt; moves the index to the front, which upload pipelines like.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then prove it, because a clean-looking command isn't proof:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;c2patool clean.mp4                    &lt;span class="c"&gt;# should say: No claim found&lt;/span&gt;
exiftool &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-G1&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; clean.mp4 | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s1"&gt;'c2pa|jumd|aigc|gps'&lt;/span&gt;   &lt;span class="c"&gt;# should print nothing&lt;/span&gt;

&lt;span class="c"&gt;# and the streams are bit-for-bit identical:&lt;/span&gt;
ffmpeg &lt;span class="nt"&gt;-loglevel&lt;/span&gt; error &lt;span class="nt"&gt;-i&lt;/span&gt; clip.mp4  &lt;span class="nt"&gt;-map&lt;/span&gt; 0 &lt;span class="nt"&gt;-c&lt;/span&gt; copy &lt;span class="nt"&gt;-f&lt;/span&gt; streamhash &lt;span class="nt"&gt;-hash&lt;/span&gt; sha256 -
ffmpeg &lt;span class="nt"&gt;-loglevel&lt;/span&gt; error &lt;span class="nt"&gt;-i&lt;/span&gt; clean.mp4 &lt;span class="nt"&gt;-map&lt;/span&gt; 0 &lt;span class="nt"&gt;-c&lt;/span&gt; copy &lt;span class="nt"&gt;-f&lt;/span&gt; streamhash &lt;span class="nt"&gt;-hash&lt;/span&gt; sha256 -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the two &lt;code&gt;streamhash&lt;/code&gt; outputs match, the picture and sound are exactly what you exported.&lt;/p&gt;

&lt;p&gt;Then repost: delete the labelled post (copy the caption and note the sound first), upload &lt;code&gt;clean.mp4&lt;/code&gt;, and leave the AI-generated content switch off.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you export from CapCut every day
&lt;/h2&gt;

&lt;p&gt;Doing this per clip gets old fast. I built &lt;a href="https://metacleanai.com/remove-ai-generated-label-tiktok/" rel="noopener noreferrer"&gt;MetaClean&lt;/a&gt; for that: a Mac and Windows app that shows every piece of metadata in a video (or photo) in plain words, removes the AI markers, or location and device details too, and saves a verified &lt;code&gt;clean_&lt;/code&gt; copy next to the original, using the same stream-copy approach as above. Its &lt;strong&gt;Watch Folders&lt;/strong&gt; mode sits on your CapCut export folder (subfolders included) and only pops up when a new export actually carries AI metadata: one click and the clean copy is ready to post. Everything runs locally; nothing is uploaded. 3-day free trial, then $5 once.&lt;/p&gt;

&lt;p&gt;Disclosure: I'm the developer of MetaClean.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;TikTok's automatic "AI-generated" label is read from the file's metadata, including C2PA Content Credentials.&lt;/li&gt;
&lt;li&gt;See it: &lt;code&gt;c2patool clip.mp4&lt;/code&gt; and &lt;code&gt;exiftool -a -G1 -s clip.mp4&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Remove it without touching quality: &lt;code&gt;ffmpeg -i clip.mp4 -map 0 -c copy -map_metadata -1 clean.mp4&lt;/code&gt;, then verify with &lt;code&gt;c2patool&lt;/code&gt; and &lt;code&gt;streamhash&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Full TikTok walkthrough: &lt;a href="https://metacleanai.com/remove-ai-generated-label-tiktok/" rel="noopener noreferrer"&gt;How to remove the AI-generated label on TikTok&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>privacy</category>
      <category>video</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Why Instagram labels your real photo "AI info" (and how to see the metadata behind it)</title>
      <dc:creator>Sebastian Balog</dc:creator>
      <pubDate>Sat, 26 Sep 2026 20:46:48 +0000</pubDate>
      <link>https://dev.to/sebastian_balog_c88dc2913/why-instagram-labels-your-real-photo-ai-info-and-how-to-see-the-metadata-behind-it-4j0f</link>
      <guid>https://dev.to/sebastian_balog_c88dc2913/why-instagram-labels-your-real-photo-ai-info-and-how-to-see-the-metadata-behind-it-4j0f</guid>
      <description>&lt;p&gt;You take a real photo, remove a stray object with a generative fill tool, post it, and Instagram adds &lt;strong&gt;"AI info"&lt;/strong&gt; under your name. The picture is 99% camera, but the label says otherwise.&lt;/p&gt;

&lt;p&gt;The label usually isn't about the pixels. It's about &lt;strong&gt;metadata&lt;/strong&gt; the editing tool wrote into the file. Once you know where it lives, you can see it in seconds, and remove it without touching the image.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the platforms read
&lt;/h2&gt;

&lt;p&gt;Meta has said it labels images using industry-standard signals in the file. Two of them do most of the work:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. C2PA Content Credentials.&lt;/strong&gt; A signed manifest embedded in the file (in a JPEG it sits in &lt;code&gt;APP11&lt;/code&gt; segments as JUMBF boxes). It records which app made or edited the image and what it did: &lt;code&gt;c2pa.opened&lt;/code&gt;, &lt;code&gt;c2pa.edited&lt;/code&gt;, and, for AI tools, a &lt;code&gt;digitalSourceType&lt;/code&gt; saying generative AI was involved. Photoshop, Firefly, ChatGPT's image generation and a growing list of phones and cameras write it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The IPTC digital source type.&lt;/strong&gt; A single XMP field, &lt;code&gt;Iptc4xmpExt:DigitalSourceType&lt;/code&gt;, whose value is a URL from the IPTC vocabulary. The two that matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;trainedAlgorithmicMedia&lt;/code&gt;: made with generative AI&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;compositeWithTrainedAlgorithmicMedia&lt;/code&gt;: edited with generative AI (your generative-fill case)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Either one is enough to earn the label.&lt;/p&gt;

&lt;h2&gt;
  
  
  See it in your own files
&lt;/h2&gt;

&lt;p&gt;With &lt;a href="https://exiftool.org" rel="noopener noreferrer"&gt;ExifTool&lt;/a&gt; installed:&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;# The IPTC AI tag&lt;/span&gt;
exiftool &lt;span class="nt"&gt;-XMP-iptcExt&lt;/span&gt;:DigitalSourceType photo.jpg
&lt;span class="c"&gt;# Digital Source Type : http://cv.iptc.org/newscodes/digitalsourcetype/compositeWithTrainedAlgorithmicMedia&lt;/span&gt;

&lt;span class="c"&gt;# Is there a C2PA manifest? (JUMBF boxes labelled c2pa)&lt;/span&gt;
exiftool &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-JUMDLabel&lt;/span&gt; photo.jpg
&lt;span class="c"&gt;# JUMD Label : c2pa&lt;/span&gt;
&lt;span class="c"&gt;# JUMD Label : urn:c2pa:060ce687-...&lt;/span&gt;
&lt;span class="c"&gt;# JUMD Label : c2pa.assertions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the full, human-readable manifest (signer, actions, validation state), use the official &lt;a href="https://github.com/contentauth/c2pa-rs" rel="noopener noreferrer"&gt;c2patool&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;c2patool photo.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While you're in there, check what else the file carries. Most phones add GPS once the camera has location access:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;exiftool &lt;span class="nt"&gt;-GPSPosition&lt;/span&gt; &lt;span class="nt"&gt;-Model&lt;/span&gt; &lt;span class="nt"&gt;-SerialNumber&lt;/span&gt; photo.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No command line handy? I built a free &lt;a href="https://metacleanai.com/exif-viewer/" rel="noopener noreferrer"&gt;in-browser EXIF and C2PA viewer&lt;/a&gt; that reads all of this, including the prompts Stable Diffusion and ComfyUI hide in PNGs. The file is read locally and never uploaded; switch off your Wi-Fi after the page loads and it still works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Removing it (and the gotcha that bites everyone)
&lt;/h2&gt;

&lt;p&gt;The classic one-liner does remove the C2PA manifest, the IPTC tag and your GPS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;exiftool &lt;span class="nt"&gt;-all&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; photo.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But run it on a photo from a phone and look closely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Warning: ICC_Profile deleted. Image colors may be affected - photo.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-all=&lt;/code&gt; also deletes the &lt;strong&gt;colour profile&lt;/strong&gt; and the &lt;strong&gt;orientation&lt;/strong&gt; flag. iPhone photos are usually Display P3, so they come out duller, and portrait shots can come out sideways. The fix is to copy those two back from the original in the same command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;exiftool &lt;span class="nt"&gt;-all&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;-tagsfromfile&lt;/span&gt; @ &lt;span class="nt"&gt;-icc_profile&lt;/span&gt; &lt;span class="nt"&gt;-orientation&lt;/span&gt; photo.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I tested both on a C2PA-signed, Display P3, rotated JPEG: the second command removed the manifest (&lt;code&gt;c2patool&lt;/code&gt; reports &lt;code&gt;No claim found&lt;/code&gt;), the IPTC tag and the GPS, kept the profile and rotation, and left the decoded pixels identical.&lt;/p&gt;

&lt;p&gt;Then check your result, because a clean-looking command isn't proof:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;exiftool &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-JUMDLabel&lt;/span&gt; &lt;span class="nt"&gt;-XMP-iptcExt&lt;/span&gt;:DigitalSourceType &lt;span class="nt"&gt;-GPSPosition&lt;/span&gt; photo.jpg   &lt;span class="c"&gt;# should print nothing&lt;/span&gt;
c2patool photo.jpg                                                             &lt;span class="c"&gt;# should say No claim found&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the label is already on a post, removing the metadata from your file isn't enough on its own: Instagram keeps the label on what it already published. I wrote up the full repost routine for feed posts, Reels, Stories and Facebook (including saving your caption first) in &lt;a href="https://metacleanai.com/remove-ai-info-instagram/" rel="noopener noreferrer"&gt;How to remove AI info from Instagram posts&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Doing this for a whole camera roll
&lt;/h2&gt;

&lt;p&gt;For one JPEG, the ExifTool commands above are all you need. For folders full of photos &lt;em&gt;and&lt;/em&gt; videos (where metadata lives in QuickTime atoms and its own C2PA box), I made &lt;a href="https://metacleanai.com/" rel="noopener noreferrer"&gt;MetaClean&lt;/a&gt;, a Mac and Windows app that does the whole thing offline. It bundles pinned versions of ExifTool, c2patool and FFmpeg, never re-encodes (video is remuxed with stream copy), keeps colour profiles and orientation, and re-inspects every output before saving it as &lt;code&gt;clean_&amp;lt;name&amp;gt;&lt;/code&gt;, leaving the original untouched. There's a 3-day free trial, then it's $5 once.&lt;/p&gt;

&lt;p&gt;Disclosure: I'm the developer of MetaClean and the viewer linked above.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;"AI info" on a real photo usually comes from &lt;strong&gt;C2PA Content Credentials&lt;/strong&gt; or the &lt;strong&gt;IPTC DigitalSourceType&lt;/strong&gt; tag, not from the pixels.&lt;/li&gt;
&lt;li&gt;See them: &lt;code&gt;exiftool -XMP-iptcExt:DigitalSourceType -a -JUMDLabel photo.jpg&lt;/code&gt;, or &lt;code&gt;c2patool photo.jpg&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Remove them without breaking the photo: &lt;code&gt;exiftool -all= -tagsfromfile @ -icc_profile -orientation photo.jpg&lt;/code&gt;, then verify.&lt;/li&gt;
&lt;li&gt;Already labelled? See &lt;a href="https://metacleanai.com/remove-ai-info-instagram/" rel="noopener noreferrer"&gt;how to remove AI info from Instagram&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>privacy</category>
      <category>photography</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
