Session sync
Your session on two computers
- scrypt plus AES-256-GCM
- Encryption
- your folder, not ours
- Storage
- 1 / 2 / 5 / 20 by plan
- Device seats
- 3 minutes, renewed while open
- Profile lock
The second computer is where accounts get lost
Profile settings travel through your account: name, scenario, fingerprint template, proxy, group, tags. Cookies, logins and site storage do not. They sit in the profile directory on the machine that made them, and nowhere else.
So an honest move to a second computer meant signing in to thirty accounts again. That is exactly the work you bought the product to avoid. The shortcuts are worse. Copying a profile folder by hand gives you a broken database. Opening the same account in a normal browser next to it gives a site one account live from two places, behind two different machines, at the same time. That pattern is what gets an account reviewed and closed.
ARMANOS answers it in two halves. A session travels as one encrypted file through a folder you already own. A profile opens on one machine at a time, and the app refuses to touch a profile that is open. The rest of this page is those two halves, in the order the code runs them.

The folder is yours, and so is the cloud under it
You point ARMANOS at a folder. Anything your own cloud already syncs works: Dropbox, iCloud Drive, Google Drive, a work network share, a folder on a NAS. The app does not know which one it is and does not ask.
That is a deliberate choice, not a gap. We run no storage for your sessions, so there is nothing of yours for us to hold, lose or hand over. It also meant the feature could ship at once, instead of waiting for object storage to exist.
The folder is tested by writing a small probe file, not by reading permission bits. A network share and a cloud folder can both look available and refuse the first real write. Changing the folder clears every sync mark, because those marks describe the old folder and would carry a recorded conflict into the new one.
One line does reach our server, and only after the work is done: which machine, which direction, whether it worked, and a short error name. No file names, no contents. Without it your dashboard would show nothing at all about sessions, and a sync that broke last Tuesday would stay invisible.
- 1
Choose the folder
Any folder your cloud syncs. The app writes a probe file to check it can really write there.
- 2
Set a password
At least 8 characters, and the same on both machines. The other computer cannot open the file without it.
- 3
Name this computer
Office, laptop, home. That name is what the other machine shows you when a session arrives from here.
- 4
Turn sync on
Without a folder and a password the switch refuses, instead of saying on and doing nothing.
What is packed, and what is dropped on purpose
Two files per profile land in the folder. The archive is <id>.armanos, encrypted. Beside it sits <id>.json, a small plain label the other machine reads first.
The archive holds the session directories of both engines, each under its own name, so the built-in Chromium and the ARMANOS Browser 153.0.7978.0 travel in one file without a nested archive. Alongside them goes profile.json: the profile id, name, scenario, group, tags, notes, start page, fingerprint template and generation, fingerprint edits, proxy, 2FA secret, saved login, and which extensions are on. The id travels because the fingerprint is derived from it. On the other machine the profile stays the same machine, rather than familiar cookies arriving under a new one.
The cache is dropped deliberately. Caches, GPU and shader caches, Service Worker storage, blob storage and crash dumps are hundreds of megabytes that sites refill by themselves. Lock files such as SingletonLock are skipped too. An archive over 400 MB is refused outright rather than written half way.
The label beside the archive carries no profile name. It holds the time, the size in bytes, and the name you gave this computer. A shared cloud folder is exactly where someone else's access arrives first, and a label reading "Instagram work" would tell them which accounts you run.
| What | Does it travel? |
|---|---|
| Cookies, logins, local and IndexedDB storage | Yes, inside the encrypted archive |
| Profile id, name, scenario, group, tags, notes, start page | Yes, as profile.json inside the archive |
| Fingerprint template, generation and manual edits | Yes, and the id with them, so the fingerprint stays the same |
| Proxy, country, 2FA secret, saved login | Yes, and only inside the encrypted file |
| Which extensions are switched on | Yes, the choice; the extension files themselves are not packed |
| Caches, Service Worker, blob storage, crash dumps | No, sites refill them and they would make the file unliftable |
| Lock files, DevToolsActivePort, socket files | No |
| The profile's name, outside the encrypted file | No, the label holds only time, size and your computer's name |
One password, and it stays on this machine
The file format is the one the manual profile transfer already uses, so a file written by one route opens by the other. A header, a random 16 byte salt, a 12 byte nonce, scrypt with N 32768 to a 256 bit key, then AES-256-GCM. The tag is checked on open, so a wrong password gives an honest refusal rather than garbage.
The password is kept on this machine, and the app says so on screen. Asking for it every time a profile closes would mean no automatic upload at all, which is the same as not building the feature. Where the system offers a keychain, the password is sealed with it; where it cannot, it is written to a file readable only by you. It never goes into the sync folder, and it is never handed back out to the interface.
Changing the password clears every sync mark, so each profile is sent again under the new one, and the app tells you how many. Without that the folder quietly fills with a mixture of two passwords: the second machine refuses honestly, the first says nothing, and you believe you simply changed a password.
Owner-only file permissions are a macOS and Linux fact
When the exchange actually happens
Before a profile opens, the app takes a newer session from the folder. It has to be before the window exists: replacing files under a running Chromium leaves a broken profile, and the browser would already have read the old databases.
Four seconds after a profile closes, the session is sent. Chromium keeps writing its databases for a second or two after the window disappears, and the app checks again that you have not reopened the profile. If you close the app inside those seconds, the send is caught up at the next start, one profile at a time with a pause between them, because building thirty sessions at once would freeze the machine right after launch.
While the app is open it watches the folder once a minute. It reads one timestamp on the folder itself, and only reads the per-profile labels when that changed, so two hundred profiles do not mean two hundred cloud reads every minute. It never pulls silently. Bringing someone else's session into a profile you are working in would swap the ground under you, so the app only tells you something new arrived.
Everything else is a button, because the automatic moments are few and a profile you keep open all day never reaches them.
Send mine to the folder
Per profile, with a confirmation that says plainly it replaces what is there.
Take the one from the folder
Per profile, replacing the session this computer holds for it.
Send all and Take all
One after another, never all at once: thirty simultaneous writes into a cloud folder invite duplicate copies. Open profiles are skipped and counted.
Find profiles in the folder
Reads the folder whole and lists profiles that exist there but not here. Settings come from inside the archive, so this works with no account at all.
When both sides changed, nothing is overwritten
One small function makes the decision, and it compares marks rather than clocks. "Changed here" is the newest session file time on this machine against the same number remembered at the last sync. "Changed there" is the label in the folder against the label the app last read or wrote. Two clocks on two machines never enter the comparison.
If both changed since the last sync, two people worked in parallel, and either write would throw away real logins. So nothing is written in either direction. You get a notification naming the other computer, a mark on the row in the profile list, and two buttons in the profile card. The decision is yours because only you know which side matters.
"Send mine" settles the argument for this machine, and the confirmation says so. What it replaces is copied aside first, under a name the exchange ignores, and the last three such copies per profile are kept. A click made without thinking now costs a minute rather than a day of the other machine's work.
A recorded conflict is a cache, not a verdict. It is recomputed before every exchange, because the file may have been deleted, renamed by the cloud, or the folder changed. Otherwise one conflict would disable automatic sending for that profile forever, and only a successful send could clear a flag that itself forbids sending.
| State since the last sync | What the app does |
|---|---|
| Nothing in the folder for this profile | Sends as soon as there is a real session to send |
| Only this machine changed | Sends |
| Only the folder changed | Takes it, before the profile opens |
| Neither changed | Nothing is written |
| Both changed | Nothing is touched; you are told and you choose |
| Label is newer than the file beside it | Nothing this round; the app comes back when the file arrives |
Clouds do things behind your back, and the app expects them
A cloud copies files one at a time, and the small label beats the big archive. So the app checks the size on disk against the size the label promises. If they disagree, the pair is marked not ready and nothing happens that round. Throwing the label away instead would look like an empty folder, and the next send would overwrite fresh work from the other machine.
A missing archive is not an empty folder either. iCloud Optimize Storage, OneDrive Files On-Demand, which is on by default on Windows, and Dropbox Smart Sync take file contents off the disk and leave a stub. A heavy session archive is the first candidate, while the tiny label stays. The rule is simple: a label means a session exists. We cannot take it right now, and we have no right to overwrite it.
Writing goes through a neighbour file and a rename, because half an archive on top of a working session cannot be decrypted. An interrupted write leaves that neighbour behind, and the neighbour is a full copy of a session in a folder whose space you pay for. Once an hour the app sweeps leftovers older than an hour that match its own naming exactly. Somebody else's half-written file is never touched.
The archive also carries its own build time, and it must equal the label beside it. If they differ, the file is the previous one and the label is the new one, so nothing is unpacked and nothing is recorded.
| What the cloud did | What you get |
|---|---|
| Copied the label first, the archive later | Nothing this round, then a normal take once the file lands |
| Evicted the archive to save disk space | Nothing is taken and nothing is overwritten |
| Kept two copies after a near-simultaneous write | The second copy is recognised by name and reported to you once |
| Left a half-written neighbour file behind | Swept after an hour, and only if the name is ours exactly |
An open profile is never touched, and it opens on one machine
A running profile is skipped in both directions. Its databases are being written by a live browser, and a copy taken mid-write is a broken profile on the other computer. The refusal sits in three separate places: building the archive, sending, and taking. The batch buttons skip open profiles too, and tell you how many they skipped.
When you are signed in, starting a profile also claims a lock on the server. It is held for three minutes and renewed every minute while the window is open, so a machine that loses power releases the profile by itself instead of holding it forever.
A second machine gets a plain refusal that names the holder and how long it has held it. You can take over on purpose. The previous holder finds out at its next renewal that the lock is no longer its own, and closes its windows. Both the first claim and the takeover are conditional writes, so two simultaneous starts cannot both succeed.
"Mine" means the same machine, not the same person. A request that does not name its machine cannot prove a lock is its own, and does not get it. Without an account there is no lock and none is needed: the profiles live only on this computer, and there is nobody to share them with.
- Lock held for
- 3 minutes
- Renewed
- every 60 seconds while the profile is open
- Second machine
- refused, and told who holds it and since when
- Profile closed
- the lock is released at once
- Machine unplugged
- the lock expires on its own
Numbers are from apps/server/src/profiles/profiles.service.ts and the desktop lock renewal timer.
A machine takes a seat, and you can take it back
Each installation names itself with a random identifier created once and kept in the app data. It used to be derived from hostname, platform and username, which made two fresh laptops the same machine. That cost a seat, and worse, it let the lock treat both as one and open the same profile twice at the same time.
Seats are a workspace pool counted against the owner, so a team shares one set. They follow the subscription that is live now, not a number stored once: a lapsed plan does not keep every machine it ever registered. When there are more machines than seats, the earliest registrations hold them in a stable order, and the rest get an honest refusal rather than a machine dropping out at random.
Unlinking a machine in the dashboard frees its seat immediately and is remembered. A revoked machine cannot open profiles or renew a lock, and it does not quietly register itself back on the next heartbeat, which is what used to happen. You can unlink your own machine; unlinking someone else's takes an admin. Signing out on the machine itself also hands the seat back, and that is not remembered as a revocation, because you were sitting at it.
| Plan | Device seats | Profiles |
|---|---|---|
| Free | 1 | 2 |
| Professional | 2 | 10 to 100 |
| Business | 5 | 200 to 1000 |
| Enterprise | 20 | 5000 and above |
What this does not do
- It does not host anything for you. No folder, or a cloud app that is not running, means no exchange. If your cloud has not finished copying, the app waits and does nothing that round.
- It does not merge two sessions. When both sides changed you pick one, the other is set aside as a copy, and putting the two together is manual work.
- It does not touch an open profile in either direction. A profile you keep open all day does not travel until you close it or press Send all.
- It is not live mirroring. Sessions move before a profile opens, a few seconds after it closes, at app start, and when you press a button.
- If you lose the password, the files already in the folder cannot be opened. There is no recovery path, by design: we hold no copy of it.
How to check
Every claim above has a file behind it, and most have a stand that runs the real code.
- The folder gets an encrypted file, and a full round trip restores the cookies
- apps/desktop/src/lib/sessionSync.js · apps/desktop/test/session-sync-folder.js
- Both sides changed: nothing is overwritten, and what you replace is kept aside
- apps/desktop/src/main/main.js · apps/desktop/test/conflict-keeps-copy.js
- An archive the cloud evicted or has not finished copying is not read as an empty folder
- apps/desktop/src/lib/sessionSync.js · apps/desktop/test/cloud-evicted-file.js
- One profile opens on one machine at a time, and takeover is deliberate
- apps/server/src/profiles/profiles.service.ts · apps/server/test/profile-lock.js
- Seats follow the live plan, and unlinking a machine is remembered
- apps/server/src/devices/devices.service.ts · apps/desktop/test/device-identity.js
Read next
Profiles
What a profile holds, and why the session lives on the machine.
Transfer and import
The same encrypted file, moved by hand instead of through a folder.
Team
Shared profiles, roles, and the seat pool the whole workspace draws on.
Security
Where secrets are kept, what leaves the machine, and what does not.
Set it up on both computers
Install ARMANOS on the second machine, point both at the same folder, and set the same password. The first session travels the next time you close a profile.