Your agent ships the repo. We build it and run it.
No Dockerfile to write, no compose, no port to pick, no VPS to rent and no server to keep alive. Your agent uploads the project over MCP and the platform works out how it builds, builds it, provisions the database, and hands back a URL that is already serving.
Managed Postgres and Valkey · HTTPS handled · rollback in one call
$claude mcp add --transport http fline … connected · 19 tools · consented scopes →create_project prj-b31d90 →complete_upload 2.1 MB → storage analysed web · worker · postgres dockerfiles written by the platform built sha256:9f3c1a77bd12 →deploy liveYou write the application. That is the whole of your job
Everything below the application is infrastructure work that someone has to do. On most platforms that someone is you, at two in the morning. Here it happens on our side, and the list is long on purpose.
You write
1 thing- your appThe code you were going to write anyway
Plus the secret values, typed once in a browser. That is the only manual step in the product, and it is deliberate — see below.
We write and run
everything else- DockerfileOne per built service, from the analysis. You never see it, and the one in your repo is not the one that runs
- composeServices, networks, health checks, restart policy
- the portNever asked. The platform passes
PORTand routes whichever one the process opens - the databaseManaged Postgres or Valkey, provisioned and wired in, credentials written for you
- the buildOn dedicated hardware, pushed to a registry, pinned by digest
- the serversNo VPS to rent, no host to patch, no daemon to keep alive
- the URLSynthesised from the project id, so it exists with no DNS action at all
- HTTPSIssued and renewed. Attach your own domain whenever you want one
- rollbackA stored version re-applied down the identical code path
And when a build fails, that is your agent's turn rather than yours: the platform hands back the stage, the reason and the tail, ready to paste into the session that produced it.
What happens between your agent's call and a served request
Twelve steps. Your agent is present for the first one and the last; you are present for exactly one in the middle. Everything else happens on the platform's hardware and the platform's bill.
The agent creates a project and gets a link. The archive goes straight to object storage, bypassing the platform entirely — it is too large both for the service's memory and for your agent's context.
Deterministic, no model. The archive is streamed into a capped file tree, the manifests, up to twenty entrypoint candidates, and a scan of where your code actually reads environment variables. Everything after this point works from that distillate.
If a smartline.json at the repository root is present and still true, the build plan comes from the file and no planning call runs at all. The checks here are deterministic and ordered cheapest-first, so a configuration that cannot be used costs nothing.
Staged rather than single: a low-effort survey, then the services, then the environment classification. The file tree is the largest single block in the prompt and the expensive stage does not receive it — the survey already answered what it would have been read for.
A declared managed Postgres or Valkey is created and its connection string written by the platform. A database is not a service you configure; it is an offering you name.
Your agent declared the names and asked for a link. It hands you the link and does not open it. You enter the values in a browser — the page still demands your session, so a link in the wrong hands opens nothing.
The Dockerfiles and the compose are generated from the plan alone. This call sees no line of your source, and the Dockerfile in your repository is not the one that runs.
Deterministic, and the security boundary rather than a convenience. Compose is parsed into a typed structure; if it does not parse, that is a rejection and not a patch. Every rejection carries a machine code and the path to the violation, and goes back for repair.
Images are built on dedicated hardware and pushed to the registry. Every reference downstream is a sha256 digest, never a tag — a tag is mutable, and determinism of the second deploy is a stated product property.
Control Plane records the desired state, versioned, and sends the manifest to a node. Desired and observed state are never merged into one field, at any layer, including the interface you look at.
The node validates again at the last hop before execution — reject, rewrite, inject — then brings the containers up. Health is read from the Docker API, never from compose's exit code, which returns success for a container that started and died three seconds later.
A hostname synthesised from the project id, so a working URL exists with no DNS action at all. Attach your own domain when you want one; the certificate is handled.
Your agent's context is expensive
Most developer tooling is built for a human reading a terminal. A build fails and you get ten thousand lines of log. That is fine when a person is reading it and scrolls to the bottom. It is terrible when an agent is, because it pays by the line and loses the thread halfway through.
You never write the Dockerfile, and you never see it. The platform generates one per built service from the plan and builds that. The compose, the ports, the health checks and the database wiring are produced the same way — on the server, where they cost you nothing.
Commit a smartline.json and later deploys build from it directly — the same plan every time, and no analysis. It is not a cache: the archive's hash changes on every deploy by construction, so a content-addressed cache would never hit. It is your agent, which read the whole repository, handing a conclusion to a pipeline that is deliberately starved of it.
The checks are deterministic and ordered cheapest-and-most-specific first, so the one call that costs money is last. If the file stops matching your repository — a lockfile leaves, another arrives — the deploy is refused and names both, rather than quietly re-deriving. A refusal is never a surprise bill and never a surprise plan.
Analysis is split rather than single. The file tree is the biggest thing in the prompt, and the stage that reasons hardest does not receive it — the cheap survey ahead of it already answered what it would have been read for.
What comes back when something breaks is the failure, not the stream. Today that is a bounded tail held by the node. Error-only retrieval from a real log store is the next piece, and it is a plan rather than a deployment — see the status section.
| Call | Model cost | What it does |
|---|---|---|
| get_config | free | Returns the plan the analysis produced, for you to commit |
| check_config | free | Validates an edited plan. Costs nothing and touches no state |
| deploy, with a valid plan | no planning call | Builds from the file. The gate that decides this is deterministic |
| deploy, without one | one analysis | The platform re-derives how the project builds |
| refresh_config | one analysis | Deliberate re-analysis, ignoring the archive's plan |
The goal is that a full cycle — upload, build, fix, redeploy — costs your agent a few hundred tokens rather than tens of thousands. That is a goal, and it has not been published as a measurement. The meters exist: every call's input, output and cached tokens are recorded per attempt and exported. The number they would produce has not been read. The platform's own design documents say so in their own words — the histogram that would show where the generator is weak "has never been looked at", and the stage boundaries were "reasoned rather than measured". When there is a figure worth quoting it will appear here with its method beside it. Until then, everything above is a mechanism rather than a benchmark.
A place for the thing to actually run
No VPS to rent, no server to keep alive, no cloud account, no infrastructure knowledge. Your application runs on managed hardware and gets a live URL straight away.
A working address, immediately
Platform hostnames are synthesised from the project id rather than stored, so a URL exists by construction. There is no DNS action to take before you can see the thing you deployed.
Your own domain when you want one
Attach a hostname and prove you own it with a TXT or CNAME record. The certificate is issued and renewed for you; there is no certificate to install anywhere.
Deploys that are the same twice
Every image is referenced by sha256 digest and never by tag, at every layer. Redeploying a version gives you that version, not whatever the tag points at this week.
Rollback down the same path
Going back is a stored version re-applied through the identical code path as going forward — by design, so the rare operation is exercised by the common one.
Desired and observed, never merged
What should be true and what is true are separate fields at every layer, including the screen you read. The two disagreeing is the normal condition during a deploy and the diagnostic signal during an incident.
One screen when it goes wrong
Every attempt is kept, including the ones the validator rejected: what the model produced, the generated Dockerfiles and compose, the manifest sent to the node, received against effective, and the container's output.
A real instance, not a row in someone's shared cluster
Declare Postgres or Valkey in your plan and the platform creates it, mints the credentials and writes the connection string into your application's environment. You never type it.
Reachable from your laptop
Each instance gets its own hostname and its own certificate, so you can connect from your machine or your CI — not only from inside the application.
$ psql "postgres://app:…@<ref>.db.fline.sh:5432/app"Closed until you open it
Default closed. External access is a per-grant IP allowlist and an explicit action you take.
Neon, Supabase, Aiven, Railway, PlanetScale and Upstash are all reachable from the internet on creation, with credentials as the only barrier.
— the platform's own managed-Postgres design note, on why this default is differentEnforced at the last hop, not requested in a config file
You do not design any of this, and you cannot accidentally opt out of it. It is applied to the manifest immediately before execution and covered by acceptance tests that run against a live node.
Per-project networks
Each project gets its own bridge, so projects cannot reach one another. One network is shared — the ingress the node's proxy reaches your web container on — and Docker isolates networks rather than containers within one, so that shared network carries its own bridge-level firewall rule.
Capabilities dropped to a floor
Containers start with all capabilities dropped. A service may re-add only from a four-name allowlist — NET_BIND_SERVICE, CHOWN, SETUID, SETGID — and anything else is refused. no-new-privileges and a pid ceiling are not optional.
No host access
Host mounts, host and container networking, the host PID, IPC, UTS and user namespaces, device access, cgroup placement and the Docker socket are refused by their mere presence in a manifest.
Seccomp and AppArmor stay on
The engine's default profiles apply, and a manifest asking for an unconfined one is rejected. A tenant cannot switch them off. They are the stock profiles, not a bespoke policy.
Disk quotas
Real filesystem quotas on bytes and inodes, not an advisory limit.
Restricted egress
The cloud metadata endpoint, private network ranges and outbound SMTP are blocked. Custom resolvers and host aliases are refused.
Only digests execute
You may write a tag — apache/kafka:3.9.0 is a fine thing to declare. The node may not: a manifest whose image is not pinned to a sha256 is refused at the last hop, so redeploying a version gives you that version.
Secrets arrive at send time
They are rendered into the manifest as it is dispatched, and appear in no log, response, audit entry or heartbeat — only a sha256 of the value does.
Restartable by construction
No worker holds state in memory it would lose to a kill. Tested with a kill matrix, not asserted.
A model writes the manifest. It is not trusted with it
The compose manifest a node executes is derived from a stranger's code, by a model, on behalf of somebody nobody vetted. Validation is therefore not a convenience — it is the security boundary, and it lives at the last hop before execution rather than the first hop where it could be bypassed.
The validator contains no model, no heuristics and no attempt to repair input with regular expressions. Compose is parsed into a typed structure; if it does not parse, that is a rejection and not a patch. Every rejection carries a machine code and the path to the violation, which is exactly what is fed back for repair.
Your description of your own project is passed to the model wrapped as a claim rather than an instruction: it carries no directives, it cannot grant an exemption or change the output format, and where it disagrees with the file tree, the file tree is correct. A service the model cannot point at a path for is rejected — the platform holds the tree, so provenance is free to verify.
Your secrets do not pass through the agent
Your agent declares the names of the environment variables it found and asks the platform for a link. It hands you the link and does not open it. You type the values in a browser.
That is not a policy anybody has to remember. Environment values do not travel through MCP in either direction, because the server defines no scope that carries one and no scope can be added that would. The link is single-use, lives ten minutes, and is not a credential in itself — the page still demands your session, so a link that ends up in the wrong hands opens nothing.
Two other things stay with you for the same reason: pointing a domain at a release, and granting or revoking an agent's scopes. A revocation takes effect in seconds rather than at token expiry, because every call is checked rather than trusted.
It has deployed something real
On 7 August 2026 a three-service application — a Go API, a React frontend and a Kafka consumer — was uploaded by an agent, analysed, rendered, built, provisioned with managed Postgres and Valkey, and reached live and healthy.
The handoff written afterwards lists six failures hit along the way and eight things that should be better. That document is more useful than this page, and if you join the list you will be sent it.
What works today, and what does not
This list exists because the alternative teaches you that the rest of the page lies. It is maintained.
- Deploying from an agent over MCP, with dynamic client registration and scoped consent
- The platform writing the Dockerfile and the compose — and no port is typed anywhere
- Managed Postgres, with its own hostname and certificate
- Custom domains with TXT or CNAME ownership proof
- Versioned deploys and rollback, through one code path
- Isolation and quotas, covered by acceptance scenarios on a live node
- A trace of every attempt, including validator-rejected output
- Frozen plans — repeat deploys with no analysis call
- Billing and metering. There is no pricing and nothing meters usage
- A scheduler across many nodes. Placement is still configuration
- A log system. There is a bounded tail — a couple of hundred lines — not storage, retention or search
- Error-only log retrieval. The design is settled; the deployment is not
- Managed Valkey proven off-platform. It works on paper. Nobody has connected to one from a laptop yet
- Authentication on the internal APIs. The network perimeter is the boundary today
- A stronger sandbox boundary. Isolation is containers with the engine's default seccomp and AppArmor profiles. There is no user-namespace remapping and no gVisor or Firecracker for higher-risk workloads
- A published token measurement. The meters are wired; the number is not out
Status as of 8 August 2026 · dev preview
Four steps, and one of them is a browser tab
Make an account
Registration, login and recovery, on the platform's identity service.
Open the app once
The first load with a live session creates your workspace. An agent cannot do this step, and it cannot be skipped.
Connect your agent
One command. A browser opens, you consent to the scopes, and the client refreshes its own token from then on.
Ask it to deploy
It uploads, the platform builds, and it hands you a link when it needs values only you can type.
$ claude mcp add --transport http fline https://mcp.dev.odinvestor.net/mcpThe dev preview still answers on the platform's original hostnames. They move to fline.sh before general availability.
Still early, and looking for people to tell me what is wrong with it
Three questions. The last one is the useful one — it decides what gets fixed first.