Free Your Agents and Give Them SSH Access

@ekremcetinkaya_
الإنجليزية31 أغسطس 2026
120K
2
1
0
0

ليرة تركية؛ د

Oberik provides AI agents with SSH access, solving common issues with MCP and APIs like token leakage, output bloat, and stale documentation through a self-describing terminal interface.

Every modern platform hands your agent the same three integration options: an MCP server to register, an API key to store and refresh, or a skill file to install that teaches the agent how to do the first two. Something to configure. Something to leak. Something that goes stale.

Oberik gives your agent ssh access instead.

Not to you, you are acting as a proxy in this context, it actually gives SSH access to your agent.

bash
1 ssh ssh.oberik.com

SSH is the surface a coding agent uses whenever it needs to interact with Oberik (e.g., stand up a workspace, set its capability ceiling, mint tokens, chat with the agent we host, etc.). No config file, no token in an env var, nothing installed. Your machine already has the client, and it already knows how to hold the one credential involved.

Why not MCP ?

Long story short, the output problem.

MCP has become the industry default because it solved a real problem. You write a tool once, and every agent can call it the same. We're not against it. Oberik loads your own MCP servers straight into the agent we host, per tenant, and that's a good way for an agent to reach out to tools. We are talking about another direction here: how something configures the account in the first place.

As easy as it is to use, MCP has a flaw at its core: when a tool runs, the entire output is pushed into the model's context. The model has to read all of it. It cannot decide "I only wanted the third field" as by the time the text arrives, the filtering has already failed.

MCP supports filtering and pagination in principle. In practice someone has to build that into every tool and when it is missing, which can happen quite often thanks to vibe coding, the model just swallows the raw payload and pays for it in tokens and attention.

With SSH, the agent composes its own view instead of accepting the one a tool hands it.

bash
1$ ssh ssh.oberik.com 'documents --json' | jq -r '.data[].name'
2$ ssh ssh.oberik.com 'audit --limit 20 --json' | jq -r '.data[] | "\(.at) \(.command)"'

The filter runs in a pipe on the machine. Instant, free, exactly as narrow as the agent wanted. The model reads one line instead of ten pages.

There are two things that make this work. First, every response uses a single-line format like {"ok":…, "command":…, "message":…, "data":…}. That makes jq the intended way to read the output, not a workaround.

JSON mode also keeps the interaction from interrupting your stream. If a command is missing a required field, it tells you what is missing instead of opening a form. If a command could be destructive, it tells you to re-run with --yes instead of stopping to ask for confirmation.

For a line with several commands, put format json; at the beginning. That sets the format once, so you do not need to repeat the flag.

There is one detail worth knowing. The flag must go inside the quotes. ssh ssh.oberik.com --json 'documents' does not work because ssh treats options after the destination as its own. It ignores the flag, and the client responds with its own usage output. Since that output mentions neither Oberik nor the flag, it can make the host look broken.

What we try to say here is, we've trained these models to use the computer, let them use the computer.

Ekrem - inline image

Why not an API?

Long story short, the credential problem.

Don't get us wrong, we have an API in Oberik and it is good. It's what your product calls in production, and it's what the SSH gateway itself calls under the hood.

But if you look at what it asks of the caller:

  1. get a token
  2. store it
  3. refresh it
  4. keep it out of logs and out of the model's context.

Every one of those steps becomes the agent's responsibility and an agent's context is not a safe place for a secret. Anyone who has watched a model echo its own environment variables knows this. I mean if you pay attention, you would realize your favorite coding agent acts like it turns a blind eye by default when it senses a sensitive key in your prompt. However, a key pasted into an agent just doesn't sit in shell history; it also goes to a model provider, into logs, into whatever transcript the harness keeps.

The API is there, but it is not the main path we designed for agents to set themselves up on. Over SSH, the agent holds the one credential type your operating system was already built to protect, an SSH key, and the private half never transmits at all. Authenticating to Oberik puts nothing secret in the model's context, because there is nothing to put there.

Why not a CLI?

Long story short, the staleness problem.

Installing a CLI is a commitment to ask of every integrator's harness and we didn't want to be that bold as we are just taking our first steps. To be honest, we didn't want a CLI at all as it is basically a frozen copy of the product. Oberik's control plane will grow a feature as we get more feedback which means had we had gone with a CLI, we would be constantly pushing a new release, and asking the user to update.

We basically solved that as our SSH surface is generated, not written. Every route in our control plane registers together with its description and that description is the SSH command. A route added to the dashboard appears over SSH immediately so we don't need to worry about a gateway change.

Nothing to update, because nothing is installed.

Why not a skill ?

Long story short, the instructions problem.

The trending approach to ship with any agent-facing product is skills. A written procedure your agent installs, telling it how to call the product. Skills are genuinely useful, but it's essentially a fancy README file. A skill is documentation, not a capability. It does not give your agent a way to act; it still needs MCP or an API underneath to do anything, and you inherit that problem too.

On top of that, a skill is a frozen copy of how to use a moving product. The same staleness as a CLI. It sits in the agent's context before the agent has done anything, spending attention and tokens on instructions the surface could just print when asked.

Our answer to "how does the agent know what Oberik can do" is not a file it installs. It is a call to discover for the agent:

bash
1$ ssh ssh.oberik.com 'discover' # every command, its parameters and their types
2$ ssh ssh.oberik.com 'docs' # every page, with what it covers
3$ ssh ssh.oberik.com 'docs search capability' # the lines mentioning something

The surface describes itself, at connect time, from the live product. And docs is the same text as the docs site, so nothing is a summary of something else. The instructions can never go stale, because they are the product.

Why SSH?

Long story short, it solves all five problems at once.

  1. Keys are the credential agents can actually hold. SSH key auth is decades old, batte-proven billions of times and the protocol verifies the signature before we ever look at a fingerprint. We didn't feel to need to reinvent the wheel here. We just stopped asking the model to babysit a secret and let the machine do the one job it was always built for.
  2. You stay in the loop without sharing a password. When the agent does not have a key yet, such as during its first connection to Oberik, it starts a device login flow. The agent runs login link, which returns immediately with a URL and a code and shows both to you. You open the URL in your own browser. The page identifies the exact key fingerprint that will be attached, gives you options to approve or decline, and shows a code you can compare with the one printed by the agent. Meanwhile, the agent runs login wait and waits for your decision. These are separate commands by design. If one command both generated the link and waited, the agent would show you the link only after the request had expired. Once you approve, the key is registered and all future connections are signed in automatically. You will not need another link. No secret is ever written to the agent’s chat history because the process does not use one.
  3. The output is designed for pipes. Request JSON with --json on a command, or use format json; once at the beginning of a line, and every response comes back as a single-line envelope. That makes jq '.data[0].name' the intended way to read the output, not a workaround. The filter runs on the machine, so the model only sees what remains after filtering. Errors use the same envelope and include the underlying HTTP status. That lets a retry distinguish a 429 from a 400. Pipes work in both directions too. The gateway cannot read your disk, so commands that accept files take the filename as an argument and read the file’s contents from the connection. For example, ssh ssh.oberik.com 'document upload handbook.pdf' < handbook.pdf uploads the file.
  4. Zero installation. Nothing to register, nothing to store, nothing to keep in context. No MCP server in your agent's config, no token in an env var, no CLI on the PATH, no skill file. We build a dev product, so we used the tool that was already there and every agent knows how to use: SSH.
  5. Self-describing and careful by design. discover prints the full command catalog. It includes every command, its parameters and types, and any confirmation requirements. The catalog is generated live from the product. It also tells the client which fields expect file bytes instead of a string, so uploads cannot be guessed incorrectly. What it does not allow is targeting a row by its number. Destructive commands require a name, and the server checks that name against the project selected by the connection. If Staging is requested while Support Bot is selected, the server returns a 400 and leaves the workspace untouched.

Nothing to teach, because the surface teaches itself.

Here is how the Oberik login flow looks like:

Ekrem - inline image

Oberik Login Flow

Isn't an SSH door into your product a risk

That is a fair question, but the reality is almost the opposite.

The gateway has no state or privileges of its own. Every command runs through an HTTP control-plane session, just like it does in the React app. An SSH client therefore cannot do more than the same account can do in a browser. If you sign out, revoke the key, or delete the account, the change takes effect immediately because there is nothing else to revoke.

This terminal is exposed to the public internet, so anyone can connect anonymously. Every command is logged, including the connection identity, IP address, key, and result. Credentials are never stored. A password entered with login, or a provider key passed through --values, is replaced with <redacted> before the record is written. The system also stores a hash of the original command so repeated commands can be correlated without making the credential recoverable. Records are retained for 30 days or 100,000 commands, whichever comes first.

Repeated failed logins become slower instead of triggering a lockout. Someone who has forgotten which password they used can keep trying without much friction, while an automated retry loop using the wrong password becomes progressively less useful. That is the intended tradeoff.

TLDR

Everyone else gives your agent an API, an MCP server, or a skill file. We gave it a terminal. Turns out that's what it wanted.

ريمكس في YouMind

قم بتحويل مقال سريع الانتشار إلى سير عمل كامل المحتوى

قم بتجميع المصدر وفك تشفير النمط وإنشاء الأصول وصياغة القصة وتوزيعها من مساحة عمل واحدة تعمل بالذكاء الاصطناعي.

اكتشف YouMind
للمبدعين

حول Markdown إلى مقالة 𝕏 نظيفة

عندما تنشر كتاباتك الطويلة، فإن الصور والجداول وكتل التعليمات البرمجية تجعل تنسيق 𝕏 مؤلمًا. YouMind يحول مسودة Markdown كاملة إلى مقالة نظيفة وجاهزة للنشر 𝕏.

حاول Markdown إلى 𝕏

المزيد من الأنماط لفك التشفير

المقالات الفيروسية الأخيرة

استكشاف المزيد من المقالات الفيروسية