You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Aug 16, 2026. It is now read-only.
Whatever someone types into a conversation goes straight to the coding agent exactly as written — the text, any pasted image, any attached file. There is nothing in between. If a prompt carries an API key, a credential pasted out of a config file, a customer's data, or a screenshot with a token still visible in it, it leaves the machine unchanged, reaches the model provider unchanged, and is written into the conversation's permanent record in the same form. Deleting it afterwards is not possible, because by then it has already been sent.
Some of the agents the app can run already have a way to run code at moments like this — their own hook mechanism. That helps only in part, and unevenly:
The agents that have no such mechanism get no checks at all, so whether a prompt is inspected before it is sent depends entirely on which agent the conversation happens to be running.
Setting those hooks up means editing each agent's own configuration by hand on the host machine, in a different format for each one — something a person using this app through a browser cannot do at all.
When one of those hooks does run, and especially when it blocks or rewrites something, the app shows nothing. From the browser it looks like the agent simply behaved oddly.
So there is no way to state a rule like "never let anything matching this pattern reach a model" and have it actually hold across the app.
Goal
One hook system, configured in one place inside the app, that lets the operator run their own code before a prompt reaches the agent — using the agent's own hook mechanism where it has one, and running the check in the app itself where it does not, so the behaviour is the same either way. Configurable once for every agent, and separately per agent where they need to differ.
Scope
Hooks are configured from inside the app's settings, next to the existing per-agent configuration, without editing any file on the host.
Two levels: a global set that applies to every agent, and a per-agent set that adds to or overrides it. It is always clear which hooks apply to a given agent.
On an agent that has its own hook mechanism, the app registers the configured hooks with it, alongside — never instead of — hooks the user has already set up for that agent themselves.
On an agent that has none, the app runs the same hook itself, on the way out, before the prompt is handed over. Same configuration, same outcome.
A pre-send hook receives the entire prompt: the typed text and every attachment, images and files included — not the text alone.
A hook can let the prompt through unchanged, hand back a rewritten version of any part of it, or refuse to send it and give a reason.
What the agent receives is what the app records. A rewritten prompt is what appears in the conversation, in its stored history and in any export, so content a hook removed is never left behind somewhere else.
Nothing happens silently: when a hook changes a prompt or blocks it, the conversation says so.
A hook that hangs or fails cannot freeze the conversation. There is a time limit, and the behaviour on failure — send anyway, or refuse — is a deliberate configuration choice rather than an accident.
Messages that were queued while the agent was busy are treated exactly like ones sent immediately.
When an agent's own hooks run and change or block something, that becomes visible in the conversation too, instead of being invisible as it is today.
Documentation covering how to write a hook, what it is given, what it may hand back, and what happens when it fails.
Non-goals
Shipping a classifier or a redaction engine. The app runs whatever is configured; recognising sensitive data is the hook's job, not the app's.
Replacing the existing tool-approval prompts. Those already exist and stay as they are.
Hooks for plain terminal sessions, where the user drives the agent directly and its own configuration already governs it.
Inspecting or rewriting what comes back from the agent — this is about what leaves.
Per-conversation hook configuration, or letting an individual conversation turn a configured hook off.
A catalogue or marketplace of ready-made hooks.
Security / Safety Considerations
A hook is code that runs on the host with the app's own access. Being able to add one is a powerful capability, and today every signed-in user shares one configuration and there is no notion of an administrator — so who may add or change a hook is a decision this feature has to make explicitly rather than inherit.
For the case that motivates this feature, failing open means sending the very data the hook existed to remove. The choice between failing open and failing closed must be explicit, and the safe option must be available.
Removal has to reach everything the app keeps — the conversation history, exports, and any uploaded file still stored on the server — not only the copy handed to the agent.
Hooks see everything typed, so anything a hook writes down (its own logs or diagnostics) must not quietly become a second copy of the data it was meant to strip.
The hooks a user has already configured for an agent must keep working; the app must not silence them by installing its own.
Acceptance Criteria
I can add, edit and remove hooks from the app's settings without touching a file on the host.
A hook added globally runs for every agent; a hook added for one agent runs only there; and the settings show which hooks apply to a given agent.
With a hook configured to strip a known pattern, a prompt containing that pattern in its typed text reaches the agent with it removed — verified on every agent the app can run, including the ones with no hook mechanism of their own.
The same holds when the pattern is inside an attached file and when it is inside a pasted image.
The conversation's stored history and an export of it contain the stripped version, and the original cannot be recovered from anything the app kept.
A hook that refuses a prompt stops it being sent and shows its reason in the conversation.
When a hook changes a prompt, the conversation makes that visible rather than showing the change as if the user had typed it.
A hook that never returns does not hang the conversation, and what happens then follows the configured failure behaviour.
On an agent with its own hook mechanism, hooks configured in the app take effect and hooks the user had already configured for that agent still run.
When an agent's own hook blocks or alters something, that is visible in the conversation.
A message queued while the agent was busy is checked in the same way as one sent immediately.
Documentation describes writing a hook, what it receives, what it may return, and the failure behaviour.
Suggested Phasing
Hooks run by the app before a prompt is sent, one global list, working identically on every agent, covering text and attachments.
Per-agent configuration layered on top of the global set, with the settings surface that goes with it.
Delegation to the agent's own hook mechanism where one exists, plus making that agent's hook activity visible in the conversation.
Additional moments beyond "before the prompt is sent", if they prove useful, and documentation.
Open Questions
On a multi-user installation, should every signed-in user be able to configure hooks, or should this be restricted — given that there is no administrator role today?
When a hook removes something, should the person who typed it still see their original text in their own view of the conversation, or should the stripped version be the only one that exists anywhere?
Should a hook be allowed to add to a prompt as well as remove from it — project context, a standing instruction — or is rewriting-to-remove the whole of it?
Should a hook be told which project folder and which agent the prompt belongs to, so one hook can behave differently by context instead of needing several?
Problem / Motivation
Whatever someone types into a conversation goes straight to the coding agent exactly as written — the text, any pasted image, any attached file. There is nothing in between. If a prompt carries an API key, a credential pasted out of a config file, a customer's data, or a screenshot with a token still visible in it, it leaves the machine unchanged, reaches the model provider unchanged, and is written into the conversation's permanent record in the same form. Deleting it afterwards is not possible, because by then it has already been sent.
Some of the agents the app can run already have a way to run code at moments like this — their own hook mechanism. That helps only in part, and unevenly:
So there is no way to state a rule like "never let anything matching this pattern reach a model" and have it actually hold across the app.
Goal
One hook system, configured in one place inside the app, that lets the operator run their own code before a prompt reaches the agent — using the agent's own hook mechanism where it has one, and running the check in the app itself where it does not, so the behaviour is the same either way. Configurable once for every agent, and separately per agent where they need to differ.
Scope
Non-goals
Security / Safety Considerations
Acceptance Criteria
Suggested Phasing
Open Questions