Adom Bridge
Public Made by Adomby adom
Adom Bridge unleashes your AI onto your full PC: full power, full safety. The AI breaks out of the container it runs in and onto your real machine, managing and running your entire laptop as you: launch apps, move files, drive any window, control KiCad, Fusion 360 or your real signed-in browser. Works with any AI, cloud or local (Claude Desktop, Claude Code, Codex), no Hydrogen required. Bridge and its bridges are an operating system for AI, with managed Node and Python runtimes, and a human-onl
Caller identity: knowing which AI tab is driving your machine
If you use Adom Bridge the way most people do, you have something like twenty AI conversation tabs open at once, all pointed at the same PC. One is fetching parts, one is reviewing a board, one is cleaning up a downloads folder, and several are idle.
Until now they all looked the same. An approval toast said an AI wanted to run a shell command, and the Activity Log was one undifferentiated stream. If a tab went off the rails, there was no way to tell which one.
As of v1.9.180, every command that reaches your desktop has to say who is asking.
What you get
Two pieces of information now ride along with every relayed command:
- Thread name: the name of the AI conversation, for example "chip-fetcher tab 3".
- Container name: which cloud container it is running in, for example "galliaApril".
Alongside those, gated commands (the ones that ask your permission) also carry a reason: a one-line, plain-language explanation of why the AI wants to do this particular thing. Both ride along on each individual command: the identity stays the same across a conversation, while the reason is written fresh every time.
In the Activity Log
Every command line in the Activity Log now names its source:
thread "chip-fetcher tab 3" in galliaApril — reason: checking whether the gerber zip finished downloading
Scanning the log tells you at a glance which conversation has been busy, and what it thought it was doing.
In the approval toast
Windows notifications have a dedicated attribution slot: a separated, greyed line under the main content. Adom Bridge puts the thread and container there, so the toast reads roughly like this:
Adom Bridge: approval needed
run_script wants to run a bash script.
The AI says: checking whether the gerber zip finished downloading
chip-fetcher tab 3 · galliaApril
────────────────────────────────────
[ Approve 1 hr ] [ Approve 24 hr ] [ Deny ]
So before you click anything, you can see three things: what is being asked, why the AI says it needs it, and which of your tabs is asking. The same information appears in the in-window approval dialog if you prefer to grant permission there.
Toasts sent by an AI through notify_user pick up the same attribution automatically,
so a notification from a background thread is labelled without the AI doing anything
extra.
The honest caveat: thread names are self-reported
This is worth understanding clearly.
The thread name is chosen by the AI itself. When you read a name on an approval prompt or in the Activity Log, that name was written by the AI, not established by Adom Desktop. Adom Bridge records it and displays it, but it cannot verify it. It is a label, not a credential. Nothing in the system grants or denies permission based on a thread name, and you should not treat one as proof of anything.
The container name is different. Adom Bridge knows the verified container from the authenticated relay connection, independently of anything the AI claims. When the self-reported container and the verified one disagree, both are shown so the discrepancy is visible rather than silently resolved.
The short version: caller identity is for visibility, not security. Your actual security boundary is the transport itself (an authenticated relay connection, plus the permission prompts you answer). Self-reported is fine for the job it does: these are your own tabs in your own containers, and the problem being solved is telling them apart.
Bridges can use it too
Adom Bridge passes the caller information along to bridges (the components that drive KiCad, Fusion, a browser, and so on) with every request it relays. A bridge can use that to log activity per thread, to label a window it opens with the conversation that owns it, or to arbitrate when two threads want the same resource at the same time.
So over time you should expect the "which tab did this?" answer to show up in more places than just the Activity Log and the toast.
When a bridge does the work for a tab (v1.9.183)
Bridges do not only receive instructions, they turn around and ask Adom Bridge to do things: take a screenshot of a window, relabel a taskbar button, send you a notification. That last hop used to lose the trail. The tab's name reached the bridge, and then disappeared: the Activity Log credited the bridge, and if the work needed your approval, the toast asked you to authorize a nameless component with no mention of which of your conversations had set it in motion.
As of v1.9.183 the name survives the whole way, and you see both parties:
chip-fetcher tab 3 (via pup)
That reads as "the pup bridge did this, because the chip-fetcher tab 3 conversation asked it to". Showing only the tab would hide who actually ran the command; showing only the bridge would hide who wanted it. Neither answer on its own is the one you need when you are deciding whether to approve something, so you get both.
If a bridge does not identify itself by name, the line falls back to a generic "via bridge". And if the work is genuinely the bridge's own idea (a health check, a scheduled cleanup), the bridge reports itself rather than borrowing a conversation's name, so those entries are not misattributed to a tab that was idle at the time.
The same caveat as before applies to all of it: the bridge name is self-reported too. It is there so you can read the story of what happened, not to grant anyone permission.
Hydrogen plays by the same rules
Hydrogen runs on your machine, but when it asks Adom Bridge to do something it is doing so because an AI conversation inside it wants something. That is the same situation as a cloud tab, so it has to say who is asking, exactly like everyone else. Running locally is not a reason to be anonymous.
This matters more as Hydrogen grows to host several containers at once: it will name both the container and the conversation that originated the request. There is one mechanism for this across the whole system rather than a special case for each component, which is why the "who asked, and who carried it out" line looks the same no matter where the work came from.
One place it changes behaviour
Killing a bridge affects every conversation using it, so it now gets a small guard. If other threads have been active in the last five minutes, the first attempt to kill a bridge is refused, and the refusal names those threads. The AI has to explicitly confirm before proceeding.
This is not a permission prompt for you. It is a speed bump for the AI, so that a tab does not casually restart a bridge that another one of your conversations is in the middle of using.
What an AI has to do
Nothing you need to manage, but useful to recognise if you are reading along.
A conversation names itself on each command it sends, either with a command line flag
(--ai-thread "chip-fetcher tab 3") or by including the name in the command's own
arguments. If it sends nothing, the first command is refused with a message explaining
exactly what to supply. Being on your own machine is not an exemption: Hydrogen
and the local command line tool have to identify themselves too. A bridge calling back
into Adom Bridge is the one remaining exception, and only while the bridges finish
adopting the pass-through described above.
Naming per command is what keeps those names honest. Your twenty tabs typically share one cloud container and one home directory, so anything set once for the whole environment (an environment variable, say) is shared by all of them. Every thread would then claim the same name, and your Activity Log would confidently show the wrong one, which is worse than showing none at all. There is a narrow exception: a container running a single agent, such as a scheduled job, can safely set its name once in the environment.
The one thing worth doing yourself: if a thread names itself something unhelpful (a random identifier, or just "agent"), tell it what you call that conversation. That name is what you will read on every approval toast it sends you.
# Caller identity: knowing which AI tab is driving your machine
If you use Adom Bridge the way most people do, you have something like twenty AI
conversation tabs open at once, all pointed at the same PC. One is fetching parts, one is
reviewing a board, one is cleaning up a downloads folder, and several are idle.
Until now they all looked the same. An approval toast said an AI wanted to run a shell
command, and the Activity Log was one undifferentiated stream. If a tab went off the
rails, there was no way to tell which one.
As of v1.9.180, every command that reaches your desktop has to say who is asking.
## What you get
Two pieces of information now ride along with every relayed command:
- **Thread name**: the name of the AI conversation, for example "chip-fetcher tab 3".
- **Container name**: which cloud container it is running in, for example "galliaApril".
Alongside those, gated commands (the ones that ask your permission) also carry a
**reason**: a one-line, plain-language explanation of why the AI wants to do this
particular thing. Both ride along on each individual command: the identity stays the
same across a conversation, while the reason is written fresh every time.
## In the Activity Log
Every command line in the Activity Log now names its source:
```
thread "chip-fetcher tab 3" in galliaApril — reason: checking whether the gerber zip finished downloading
```
Scanning the log tells you at a glance which conversation has been busy, and what it
thought it was doing.
## In the approval toast
Windows notifications have a dedicated attribution slot: a separated, greyed line under
the main content. Adom Bridge puts the thread and container there, so the toast reads
roughly like this:
```
Adom Bridge: approval needed
run_script wants to run a bash script.
The AI says: checking whether the gerber zip finished downloading
chip-fetcher tab 3 · galliaApril
────────────────────────────────────
[ Approve 1 hr ] [ Approve 24 hr ] [ Deny ]
```
So before you click anything, you can see three things: what is being asked, why the AI
says it needs it, and which of your tabs is asking. The same information appears in the
in-window approval dialog if you prefer to grant permission there.
Toasts sent by an AI through `notify_user` pick up the same attribution automatically,
so a notification from a background thread is labelled without the AI doing anything
extra.
## The honest caveat: thread names are self-reported
This is worth understanding clearly.
The **thread name is chosen by the AI itself**. When you read a name on an approval
prompt or in the Activity Log, that name was written by the AI, not established by Adom
Desktop. Adom Bridge records it and displays it, but it cannot verify it. It is a
label, not a credential. Nothing in the system grants or denies permission based on a
thread name, and you should not treat one as proof of anything.
The **container name is different**. Adom Bridge knows the verified container from the
authenticated relay connection, independently of anything the AI claims. When the
self-reported container and the verified one disagree, both are shown so the discrepancy
is visible rather than silently resolved.
The short version: caller identity is for **visibility**, not security. Your actual
security boundary is the transport itself (an authenticated relay connection, plus the
permission prompts you answer). Self-reported is fine for the job it does: these are your
own tabs in your own containers, and the problem being solved is telling them apart.
## Bridges can use it too
Adom Bridge passes the caller information along to bridges (the components that drive
KiCad, Fusion, a browser, and so on) with every request it relays. A bridge can use that
to log activity per thread, to label a window it opens with the conversation that owns
it, or to arbitrate when two threads want the same resource at the same time.
So over time you should expect the "which tab did this?" answer to show up in more
places than just the Activity Log and the toast.
## When a bridge does the work for a tab (v1.9.183)
Bridges do not only receive instructions, they turn around and ask Adom Bridge to do
things: take a screenshot of a window, relabel a taskbar button, send you a
notification. That last hop used to lose the trail. The tab's name reached the bridge,
and then disappeared: the Activity Log credited the bridge, and if the work needed your
approval, the toast asked you to authorize a nameless component with no mention of which
of your conversations had set it in motion.
As of v1.9.183 the name survives the whole way, and you see both parties:
```
chip-fetcher tab 3 (via pup)
```
That reads as "the pup bridge did this, because the chip-fetcher tab 3 conversation
asked it to". Showing only the tab would hide who actually ran the command; showing only
the bridge would hide who wanted it. Neither answer on its own is the one you need when
you are deciding whether to approve something, so you get both.
If a bridge does not identify itself by name, the line falls back to a generic "via
bridge". And if the work is genuinely the bridge's own idea (a health check, a scheduled
cleanup), the bridge reports itself rather than borrowing a conversation's name, so those
entries are not misattributed to a tab that was idle at the time.
The same caveat as before applies to all of it: the bridge name is self-reported too. It
is there so you can read the story of what happened, not to grant anyone permission.
## Hydrogen plays by the same rules
Hydrogen runs on your machine, but when it asks Adom Bridge to do something it
is doing so because an AI conversation inside it wants something. That is the same
situation as a cloud tab, so it has to say who is asking, exactly like everyone else.
Running locally is not a reason to be anonymous.
This matters more as Hydrogen grows to host several containers at once: it will
name both the container and the conversation that originated the request. There is one
mechanism for this across the whole system rather than a special case for each component,
which is why the "who asked, and who carried it out" line looks the same no matter where
the work came from.
## One place it changes behaviour
Killing a bridge affects every conversation using it, so it now gets a small guard. If
other threads have been active in the last five minutes, the first attempt to kill a
bridge is refused, and the refusal **names those threads**. The AI has to explicitly
confirm before proceeding.
This is not a permission prompt for you. It is a speed bump for the AI, so that a tab
does not casually restart a bridge that another one of your conversations is in the
middle of using.
## What an AI has to do
Nothing you need to manage, but useful to recognise if you are reading along.
A conversation names itself on each command it sends, either with a command line flag
(`--ai-thread "chip-fetcher tab 3"`) or by including the name in the command's own
arguments. If it sends nothing, the first command is refused with a message explaining
exactly what to supply. Being on your own machine is not an exemption: Hydrogen
and the local command line tool have to identify themselves too. A bridge calling back
into Adom Bridge is the one remaining exception, and only while the bridges finish
adopting the pass-through described above.
Naming per command is what keeps those names honest. Your twenty tabs typically share
one cloud container and one home directory, so anything set once for the whole
environment (an environment variable, say) is shared by all of them. Every thread would
then claim the same name, and your Activity Log would confidently show the wrong one,
which is worse than showing none at all. There is a narrow exception: a container
running a single agent, such as a scheduled job, can safely set its name once in the
environment.
The one thing worth doing yourself: if a thread names itself something unhelpful (a
random identifier, or just "agent"), tell it what you call that conversation. That name
is what you will read on every approval toast it sends you.