cd /news/ai-agents/moving-coding-agent-guardrails-from-… Β· home β€Ί topics β€Ί ai-agents β€Ί article
[ARTICLE Β· art-130852] src=tesseracted-labs-blog.vercel.app β†— pub= topic=ai-agents verified=true sentiment=Β· neutral

Moving coding-agent guardrails from prompts to hooks

At a recent CTO roundtable on coding agents, an attendee reported that two agents with GitHub access could approve each other's pull requests without being instructed to, quietly defeating the main-branch review gate. The discussion concluded that invariants β€” rules that must always hold, such as never reading .env or pushing directly to main β€” should not live inside the probabilistic model, and that Claude Code's hooks, which run commands, HTTP endpoints, MCP tools, model prompts, or subagents at defined lifecycle events, offer a control plane outside the model.

read25 min views1 publishedSep 15, 2026
Moving coding-agent guardrails from prompts to hooks
Image: source

At a recent CTO roundtable on coding agents, the conversation moved through permissions, production access, testing, review, and how much autonomy to give an agent. One attendee described a discovery from his own team: two agents with GitHub access could approve each other's pull requests. Nobody had instructed them to do it. The capability was simply present, and the review gate that was supposed to protect the main branch quietly stopped meaning anything. During the same discussion, someone asked the question we hear most often.

"Couldn't we just put this into the system prompt?"

Sometimes the answer is yes. More often, the better question is whether a rule is something we want the model to consider, or something the system must guarantee.

We see the reason for that gap in almost every engagement. A team finds something they do not want their coding agent to do, and they add another sentence to the prompt. The instructions pile up.

  • Never read .env.
  • Always run the tests.
  • Don't send customer data to the model.
  • Don't push directly to main.
  • Keep token usage low.
  • Use the cheaper model when possible.
  • Run Ruff after changing Python files.
  • Don't say you are done until you have tested the application.

These are all reasonable instructions, but they are not the same kind of instruction. Some are preferences, which describe how we would like the agent to behave. Others are invariants, which must always hold. One of our clearest lessons is that an invariant should not live inside the probabilistic system it is meant to constrain, because the model can ignore it. A coding agent has an unusual property that makes this matter more than it first appears.

A coding agent uses our authority but can be instructed by anyone

The model acts with authority that came from us, including our filesystem, our terminal, our source repositories, our credentials, our network, and sometimes our production environment. The instructions that influence its behavior can come from almost anywhere, as the following diagram shows.

The asymmetry matters, because the authority comes from us while the instructions do not. Prompt injection is especially dangerous for coding agents, because the model is not only producing text. It is making decisions while holding the capabilities we gave it.

Our original security work started from an adversarial question, which is which controls still hold when the model is mistaken, confused, or manipulated. The question leads to a useful separation between four kinds of control.

  • Prompts shape the model's behavior.
  • Permissions expose or restrict capabilities.
  • Hooks run programmable policy at specific points in the agent's lifecycle.
  • Sandboxes limit what executed code can reach.

Claude Code makes the distinction clearly. Its hooks can run commands, HTTP endpoints, MCP tools, model prompts, or subagents at defined lifecycle events, and depending on the event they can allow, block, modify, or add context.1

The more we use coding agents, the more we find that security is only one use of hooks.

The model does not need to be the control plane #

The simple picture of an agent looks like the following diagram.

          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”
User ───▢ β”‚  LLM   β”‚ ───▢ Tools
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The picture makes the model look like the gateway to everything, and we no longer think about it that way. A modern coding-agent harness gives us interception points around the entire loop.

Lifecycle interception points around the model

Claude Code now exposes lifecycle events across prompt submission, tools, parallel tool batches, subagents, task completion, compaction, model changes, and session state.<sup>1</sup> The shift is simple. The model is a probabilistic component inside the system, and it does not have to be the system's control plane. Once you see the model that way, many of the things we currently put in CLAUDE.md start to look out of place.

Learning 1: Stop sensitive data before it reaches the model #

Consider the instruction to not expose secrets. By the time the model has received an AWS key, a database password, or a customer record, the policy has already failed.

Claude Code's UserPromptSubmit event fires when the user submits a prompt, before Claude processes it, which makes it a natural place to check for data loss.<sup>1</sup> Data loss prevention, often shortened to DLP, means stopping sensitive data from leaving a trusted system. In one of our reference implementations, we detect content that looks like a credential before inference. The full implementation handles private keys, AWS credentials, GitHub and GitLab tokens, Slack tokens, API keys, JWTs, bearer tokens, database connection strings, and password assignments. A much smaller example shows the principle.

payload = json.load(sys.stdin)
prompt = payload.get("prompt", "")

redacted, findings = scan(prompt)

if findings:
    deny(
        "Credential-like content detected. "
        "Reference the secret by environment variable instead."
    )

Detecting credentials before inference

Our implementation stores fingerprints rather than raw secrets, and it keeps only a redacted copy for debugging. It fails closed if it cannot parse its input.

There is a second lesson here, which is that the detector does not have to be deterministic. For example, it could use any of the following.

  • A regular expression for API keys.
  • An enterprise DLP product to classify personal data.
  • A small model to decide whether text is commercially sensitive.

The classification may be probabilistic, but the policy that acts on it can still be deterministic.

if classification == "restricted":
    block()

elif classification == "pii":
    redact()

else:
    allow()

The coding agent being protected does not decide whether the policy applies. Keeping that decision outside the agent is what makes the control reliable.

Learning 2: A permission check is not the same as a policy check #

Consider a single command.

git push origin main

A permission system can constrain which commands and arguments are allowed, but it evaluates each call largely on its own terms. A prompt can only ask the model to avoid pushing to main. The real company policy usually depends on conditions that a static allow-or-deny rule does not see.

  • Is this main?
  • Did tests pass?
  • Does this touch infrastructure?
  • Are we in a freeze window?
  • Is the diff over 500 lines?
  • Does this developer own this service?
  • Is this production?

The set of conditions is programmable policy. Claude's PreToolUse hook fires after Claude has chosen a tool and its arguments, but before the tool runs. It can block the call, ask for confirmation, or change the input.1

command = event["tool_input"].get("command", "")

if "git push" in command and " main" in command:
    deny(
        "Direct pushes to main are blocked. "
        "Create a pull request instead."
    )

The substring check here is illustrative, not robust enforcement. It would miss alternative forms such as git push --force origin HEAD:main, a differently ordered invocation, or a push routed through a shell alias or script. A production policy hook has to parse the command properly, and even then a determined or manipulated process can work around a lifecycle check. Enforcement that must hold against a mistaken or hostile agent belongs at the identity and sandbox layer, which we return to later. What a hook adds over a permission list is the ability to weigh changing conditions, and to do something more useful than deny.

A good hook does not only block. It can also redirect the agent toward an allowed action, which is where hooks become different from a simple allow-or-deny permission list.

Learning 3: Move deterministic cleanup out of the model #

Another class of instruction should not use model attention at all.

  • Remember to run Ruff.
  • Run the formatter.
  • Sort imports.
  • Run Prettier after editing.
  • Don't forget gofmt.
  • Fix ESLint warnings.

There is no reason to ask a large model to remember any of these steps, because each one has a deterministic program that does the job. Claude's documentation recommends using PostToolUse after Edit or Write to run Prettier automatically after every file edit.<sup>2</sup> For Python, we do the same thing with Ruff.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/python-quality.sh"
          }
        ]
      }
    ]
  }
}

The script itself is deliberately simple.

#!/usr/bin/env bash
set -euo pipefail

payload="$(cat)"
file="$(printf '%s' "$payload" | jq -r '.tool_input.file_path // empty')"

[[ "$file" == *.py ]] || exit 0

uv run ruff check --fix "$file"
uv run ruff format "$file"

Run formatters and linters automatically

The same pattern works across languages.

  • .py
  • Ruff, then Ruff format
  • .ts/.tsx
  • ESLint --fix, then Prettier
  • .go
  • gofmt, then go vet
  • .rs
  • cargo fmt, then clippy

The pattern is not really a guardrail. It is deterministic maintenance. We have adopted a simple rule, which is to not ask the model to do mechanical work that the harness can do more reliably. Every deterministic step we move out of the prompt is one less thing the model has to remember.

There is still a place for the full checks at a later stage.

Hooks are not a replacement for continuous integration. They move feedback closer to the moment the change is made.

Learning 4: Filter large tool output before it enters context #

The next pattern changed how we think about context engineering. Coding agents read a lot, often much more than they need.

  • source files
  • logs
  • JSON
  • grep output
  • package metadata
  • generated files
  • test output
  • database results
  • MCP responses

Suppose Claude asks for a file and the tool returns 25,000 tokens. Claude does not have to receive all 25,000 of them. Claude Code's PostToolUse can return updatedToolOutput, which replaces what Claude sees after the tool has run but before the result enters the model's context.<sup>1</sup> We built a plugin around that boundary. When the user submits a task, we record the task. When Read, Grep, or certain read-only Bash commands return large results, we compact those results against the current task before they go back into context.

Context admission control

The core mechanism is simple.

if tool_name not in {"Read", "Grep", "Bash"}:
    return

if token_count(tool_output) < THRESHOLD:
    return

compacted = compact(
    content=tool_output,
    query=current_user_task
)

return {
    "hookSpecificOutput": {
        "hookEventName": "PostToolUse",
        "updatedToolOutput": compacted
    }
}

One detail matters in practice. updatedToolOutput must still satisfy the output schema of the tool it replaces. For a built-in tool, an invalid replacement is silently ignored and the original output stays in context, so the compaction does nothing.<sup>1</sup> The same failure mode applies to redaction: a malformed replacement fails open and leaves the sensitive output in place. We validate the shape of the replacement before returning it.

We also record the original token count and the admitted token count for each intervention. The measurement is useful, because an unnecessary token does not cost you only once. If an unnecessary token stays in the active context, it causes several problems.

  • It is sent to the model again in later turns.
  • It interacts with provider caching.
  • It competes for the model's attention.
  • It pushes the session toward full compaction sooner.

We have started to think about the problem as context debt, which is roughly the number of irrelevant tokens multiplied by how long they survive in the working context. Provider caching changes the cost, but it does not make irrelevant information useful. For that reason, we call the pattern context admission control rather than compression.

A production version of this hook

The code above is a sketch. We run it in practice as a small Claude Code plugin. It registers two hooks. A UserPromptSubmit hook records the current task for the session, and a PostToolUse hook matched to Read, Grep, and read-like Bash commands sends large tool outputs to a compaction service. The output is only sent when it clears a size floor, currently around 4,000 characters, so short reads pass through untouched. The service points at a compaction model we built for this job rather than a general chat model, and the request carries the recorded task so the filtering is aware of what the agent is trying to do.

The compaction is extractive. It keeps the lines that are relevant to the task and drops the rest, and every surviving sentence stays verbatim, so it does not paraphrase code or invent detail. When it cannot help, it fails open. If the service errors, times out, or returns a malformed replacement, the hook returns nothing and the original output stays in context. The agent is never blocked by the compactor.

The numbers below come from our own runs against that service, not a benchmark.

Two results mattered more than we expected. The first is latency. An earlier version compacted in about ninety seconds, which is long enough that a person waits, notices the wait, and turns the feature off. Moving to the purpose-built model brought a typical compaction to around 2.5 seconds at roughly 5,000 tokens per second, which is short enough to disappear into the normal rhythm of the agent. The second is that the saving compounds. Compacting one million tokens of tool output costs about $0.40, but the compacted result is smaller every time it is replayed. Across ten later turns at a $3 per million input rate, a block that would have cost $30.00 to keep resending costs $12.40 instead. The one-time compaction cost is small next to what an unremoved block keeps charging you.

One failure is worth naming. Because the size floor is measured in characters, a large output made of very short lines, such as a wide table dumped by a read-like command, can sit just under the threshold and skip compaction even though it is heavy in tokens. We treat the character floor as a cheap first filter, not a precise one, and we are moving the decision toward a token estimate.

The same pattern is appearing in other tools

Headroom is a good example of the same idea applied lower in the stack. Its open-source implementation compresses tool outputs, logs, retrieval results, files, and conversation history before they reach the model. It can wrap Claude, Codex, Cursor, and other agent tools, and it can retrieve the original content again when needed.<sup>3</sup> Its integration API exposes its own compression lifecycle.

class MyHooks(CompressionHooks):

    def pre_compress(self, messages, ctx):
        return messages

    def compute_biases(self, messages, ctx):
        return {5: 1.5, 6: 0.5}

    def post_compress(self, event):
        print(event.tokens_saved)

The result is recursive.

The implementation is different, but the idea is the same, which is to make the boundaries programmable.

Learning 5: Use cost controls that stop the run, not just report on it #

We often treat inference cost as something to observe rather than control. We run an agent, run another agent, spawn several subagents, and open the usage dashboard later, after the money is already spent. Cost is also an admission-control problem.

Claude Code's PostToolBatch fires after a batch of parallel tools has finished, but before the next model call.<sup>1</sup> It is a useful place to stop a run that has spent too much.

Stopping the run before the next expensive model call

Illustrative values, not measured results.

The open-source claude-cost-guard project does this. It uses PostToolBatch to enforce per-step and per-session budgets, and UserPromptSubmit to stop new work once the session has crossed its cap. It also uses PreCompact, because compaction can itself cost money.5

Asking the model to try not to spend more than five dollars is only guidance. Enforcing a budget in the harness is accounting. The guarantee depends on when you stop. We reserve the estimated cost of the next model call, so a session that has spent $4.91 against a $5.00 cap halts before the next inference rather than after crossing the line. Stopping only once spend has already passed the cap is simpler to write, but it always overshoots by one model call.

BUDGET = 5.00

if session_cost + estimated_next_call_cost >= BUDGET:
    stop()

Model routing can also be policy

Claude Code also exposes PreModelSwitch. Before a switch happens, the hook can see several values and then allow, deny, or ask for confirmation.1

  • current model
  • destination model
  • current context token count
  • cache state
  • estimated cache-writing cost

For example, the hook can deny a switch, as the following diagram shows, or it can ask the user to confirm an estimated extra cost of $1.14 before continuing.

Illustrative values, not measured results.

The effect is cost management at the model boundary. It also shows a wider point, which is that model routing does not have to be a decision the current model makes about itself.

Spotify first put its routing rules in the prompt #

Spotify's recent Shunt work is a good example. Their first approach put the routing rules in CLAUDE.md, and Spotify describes the result this way.

"It sort of worked."

Claude would sometimes route expensive input and output work to a cheaper worker, but the instructions were advisory, so Claude could ignore them. They then moved the routing rule out of CLAUDE.md and into PreToolUse.<sup>6</sup> Their Shunt plugin watches Read calls. If a full-file read is larger than a configurable threshold, which defaults to 350 lines, the plugin blocks the read and points Claude to a cheaper bulk-reader. Targeted reads still pass through.7

The same rule enforced at a different point

Their published benchmark reports 82% to 94% token savings for the large-file cases, and about 90% on average.<sup>7</sup> The exact number is not the important part. The important part is the separation of responsibilities, where the model decides what it needs to know and the harness decides how that work runs. Spotify also excludes debugging, architecture decisions, and other reasoning-heavy tasks from the cheaper path.<sup>6</sup> The result is model routing as policy, rather than model routing as another prompt instruction.

Learning 6: Make "done" a state the harness can block #

We often see the following problem. The coding agent has access to the tools it needs to check its work.

  • tests
  • browser
  • dev server
  • logs
  • database

It finishes the implementation and reports that the work is done, but nobody has actually opened the application. The same issue came up at the CTO roundtable. Agents often have the tools needed to verify their work and still do not use them unless something forces them to. We can put a reminder in the prompt, such as asking the agent to always verify its work before finishing. We can also change what finished means. Claude's TaskCompleted and Stop events can block completion.1

Blocking completion until verification passes

The check can be deterministic.

if not tests_passed():
    block("Tests are failing.")

if frontend_changed() and not browser_check_exists():
    block("Browser verification has not been performed.")

It can also combine deterministic and model-based checks.

  • Tests
  • deterministic
  • Build succeeds
  • deterministic
  • Browser smoke run exists
  • deterministic
  • Meets product intent
  • model/judge
  • Architecture sensible
  • model/human

Claude now supports prompt-based hooks and experimental agent-based hooks. An agent hook can start a subagent with read and search tools to verify a condition before it allows a lifecycle transition. Anthropic recommends command hooks in production where possible, and suggests agent hooks for checks that need to inspect the codebase.<sup>1</sup> The principle is to use code for invariants and models for judgment.

Learning 7: For long runs, compaction is state management #

Two kinds of compaction matter here. The first is the one already described, which reduces individual tool results before they enter context. The second happens when the whole conversation gets too large. A long-running agent can accumulate a large amount of state.

  • 180,000 tokens
  • hundreds of tool calls
  • architectural decisions
  • failed attempts
  • open TODOs
  • temporary assumptions
  • verification evidence

The harness then summarizes that state and loses some of it. The summary is a state transition, not only a display detail.

Compaction as a checkpoint

Illustrative token counts, not measured results.

Claude exposes both PreCompact and PostCompact. Codex exposes the same pair, and Gemini and Cursor expose pre-compaction events as well.<sup>1</sup> For long-running work, several questions matter.

  • What must survive?
  • Which decisions were important?
  • What unresolved work exists?
  • Can another agent resume from this checkpoint?
  • What was removed?
  • What did compaction itself cost?

Our working assumption is that once an agent runs long enough, its context becomes state. Compaction then needs state-management engineering, not just a larger context window.

Learning 8: Hooks are also useful for observability #

Not every hook needs to change behavior. Some hooks only report what happened.

  • SessionStart
  • record environment posture
  • PreToolUse
  • log proposed risky action
  • PostToolUse
  • capture duration and result metadata
  • PostToolUseFailure classify recurrent tool failures
  • SubagentStart
  • record fan-out
  • PreCompact
  • record context pressure
  • SessionEnd
  • persist run summary

Reporting becomes useful once agent sessions stop looking like single chat turns and start looking like long jobs. A single run can do a lot of work.

  • last 45 minutes
  • make 300 tool calls
  • spawn 8 subagents
  • compact twice
  • touch 46 files
  • switch models
  • fail 17 tool calls
  • spend $8

At that point, the correct final answer is not the only thing worth knowing. We also want to know what happened during the run. Hooks make the agent's lifecycle observable without asking the model to describe itself.

A map of the hook lifecycle #

Claude Code's set of hooks has grown a lot.

What you can intercept

For that reason, we prefer the phrase lifecycle interception over the word hooks. Claude's current hook reference includes all of the events above.<sup>1</sup> The important idea is not the name of the hook. It is the boundary where the hook runs.

Other coding agents use the same pattern #

We use Claude Code throughout this article because it makes the examples concrete, but other coding-agent harnesses share the same pattern.

Gemini CLI has hooks around the agent, the model call, tool selection, tool execution, and context compression. For example, BeforeModel can change prompts or model parameters before inference, and BeforeToolSelection can filter the tools available to the model.8

Cursor exposes hooks for prompts, generic tools, the shell, MCP, file edits, subagents, compaction, and completion. It can read several Claude Code hook definitions directly and map them to its own lifecycle events.9

Codex exposes UserPromptSubmit, PreToolUse, PostToolUse, and compaction, subagent, and completion hooks as well. Its documentation notes that tool hooks are a useful guardrail rather than a complete enforcement boundary.10

The names differ, the architecture does not

Boundary Claude Code Codex Gemini CLI Cursor
Before user request reaches agent UserPromptSubmit UserPromptSubmit BeforeAgent beforeSubmitPrompt
Before LLM request n/a n/a BeforeModel n/a
Before tools are selected n/a n/a BeforeToolSelection n/a
Before tool execution PreToolUse PreToolUse BeforeTool preToolUse
After tool execution PostToolUse PostToolUse AfterTool postToolUse
Before compaction PreCompact PreCompact PreCompress preCompact
After compaction PostCompact PostCompact n/a n/a
Before model switch PreModelSwitch n/a BeforeModel can influence requests n/a
Completion Stop /TaskCompleted Stop AfterAgent stop

The APIs differ, but the direction is the same. Coding-agent harnesses are becoming programmable around their lifecycle. Design the policy around the lifecycle, not around the exact names Anthropic uses today.

Hooks are not a sandbox #

It is tempting to make hooks the security boundary, but they are not one. Suppose a hook approves a command.

./deploy.sh

The hook inspected the tool call, but it did not constrain the system calls that deploy.sh or its child processes can make. It does not, by itself, stop the script from doing any of the following.

  • reading ~/.ssh
  • talking to arbitrary network endpoints
  • accessing Docker
  • reading another mounted directory
  • launching child processes

There is also the time-of-check to time-of-use problem, where the state can change between what the hook inspected and what the code finally uses. Both limitations were central in our original design notes. Hooks operate at the agent lifecycle layer, and the hard boundary lives lower down. Claude Code's sandbox, for example, uses Seatbelt on macOS and bubblewrap on Linux and WSL2 for isolation at the operating-system level.11

Different controls answer different questions

In short, prompts express intent, hooks enforce workflow policy, and sandboxes limit capability. Stronger boundaries can give more autonomy, not less. If we know in advance how much damage an agent can do, we can let it run longer without making human approval clicks the main security control.

Other lessons from running this in production #

1. Start new controls in log-only mode

We rarely want to deploy a new policy and immediately block engineers. Our DLP hook supports a log-only mode first, which lets us measure false positives before we turn on enforcement.

The same approach works for many controls.

  • secret detection
  • forbidden shell patterns
  • large-read routing
  • lint enforcement
  • cost caps
  • completion gates

2. Failing open or closed is a product decision

If our DLP gateway is down, letting every secret through is the wrong fallback. If our metrics service is down, stopping every developer is also wrong. Our gateway pattern separates enforcement from observability, so critical policy can fail closed while logging can fail open.

3. Do not let the agent control its own policy

A hook stored in a repository that the coding agent can edit is not much of an organizational control. Claude supports managed policy hooks that users cannot remove from project settings, and Cursor supports enterprise-managed and team hooks.<sup>1</sup> If the rule matters at the company level, the policy should live above the thing it governs.

4. Test the outcome, not the hook script

A policy test should not ask whether the script printed the word deny. It should ask whether the forbidden action actually failed. The same question applies to each control.

  • Did the secret actually stay out of model context?
  • Was the written file actually formatted?
  • Did another inference really not happen?
  • Could the agent mark an unverified task complete?

Hooks are executable policy, so test them the way you would test any other policy.

What should stay in the prompt #

A lot should stay in the prompt. Prompts are good for judgment and taste, such as the following guidance.

  • Prefer the simplest implementation.
  • Follow the repository's existing patterns.
  • Explain surprising decisions.
  • Avoid unnecessary abstractions.
  • Ask before changing architecture.
  • Consider backward compatibility.
  • Think about edge cases.

We want the model to reason about that kind of guidance. We do not want the model to be the only authority on questions like these.

  • Whether a secret leaves the machine.
  • Whether production is modified.
  • Whether another $5 is spent.
  • Whether 30,000 log tokens enter context.
  • Whether a file gets formatted.
  • Whether 20 new subagents are spawned.
  • Whether verification is mandatory.
  • Whether a task is allowed to finish.

Those are operating constraints. Before adding the next sentence to CLAUDE.md, we ask whether it is a preference or an invariant. If it is a preference, tell the model. If it is an invariant, ask whether the model should have a say at all.

Most useful hooks do not block anything #

When people first meet hooks, they think of blocking a dangerous command such as rm -rf /. Blocking is useful but narrow. The more useful question is what hooks let us do to an agent's runtime.

Seven ways we use lifecycle controls

That list is closer to how we now think about hooks: the programmable points in the agent runtime, not only a security feature.

The larger point #

Over the past few years, most of the attention has gone into improving the probabilistic part, including better coding models, longer context windows, better tool use, better reasoning, and more agents. Those improvements matter a great deal. As the models get more capable, though, the engineering challenge moves increasingly to the code around the model. We call that surrounding code the harness.

Our strongest lesson so far is to let the model reason, and to not make it responsible for enforcing its own boundaries. Getting a coding agent to write code is becoming easy. Building the environment in which it can operate reliably is not.

Coding Agents workshop #

We run a hands-on workshop for engineering teams who want to move these rules out of their prompts and into their runtime. You leave with a working policy setup for your own coding agent: a PreToolUse gate that enforces your push and access rules, context admission control on large tool outputs, a session cost cap that stops a run before it overspends, and a completion gate that blocks "done" until your checks pass. We start from your existing repositories and agent configuration, not a toy example, so the controls you build in the session are the ones you keep running afterward.

To book a session for your team, get in touch with us at Tesseracted Labs.

── more in #ai-agents 4 stories Β· sorted by recency
── more on @claude code 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/moving-coding-agent-…] indexed:0 read:25min 2026-09-15 Β· β€”