# The inner loop

> The local develop-and-debug loop for an Osy# app — for the person in the editor and the coding agent at the CLI alike. Run your app on a local platform, see exactly what a run did when it misbehaves, and check it before you ship, all against the source on your disk.

<!-- id: local-the-inner-loop · area: local · stability: stable · html: https://osysharp.com/reference/local/the-inner-loop/ -->

## Summary        {#summary}

Everything you do to an Osy# app while building it happens in one short loop: change the source, run it on a local
platform, and — when it does the wrong thing — see exactly what it did and why. The same commands serve a person typing
in the editor and a coding agent working at the command line: both edit the same `.osy` files, run the same local
platform, and read the same explanations of what happened, so an agent debugging your app sees precisely what you would.

## Signature      {#signature}

```console
osyrin dev     # a local platform to run on
osy launch     # compile the current source and open it
osy inspect    # see what a run did — named, at its source line, with the values
osy lint       # is it production-ready?
```

## Description    {#description}

The loop has four moves. You rarely do all four every time — most turns are *edit → launch → look* — but this is the
whole of it.

### Run it            {#run}

A local platform hosts your app while you build. Start one with `osyrin dev` ([Running a local platform](https://osysharp.com/reference/local/running-a-local-platform/)); it runs
only on your machine and needs no account. `osy launch` ([Launching your app](https://osysharp.com/reference/local/launching-your-app/)) compiles the source on your disk
into the app and opens it in a browser — edit, launch, see the result. When the platform is already running, an open
page even updates itself as you recompile, so the tightest loop is just *save and look*.

Your app runs the **real** thing locally: its own login, its own access rules, the same compiler that runs in
production. What opens is what you wrote, not a stub.

An app is more than its code, so two commands put yours in a state worth looking at: `osy import`
([Importing data](https://osysharp.com/reference/local/importing-data/)) loads the rows it ships with, and `osy run` ([Running a function](https://osysharp.com/reference/local/running-a-function/)) runs one of its
own functions — to seed something, backfill a column, or kick off a job — as a real user or as nobody.

### See what it did   {#see}

When a run misbehaves, you do not add logging and run it again — you open the run you already have. `osy inspect`
([Seeing what happened when your code ran](https://osysharp.com/reference/local/seeing-what-happened/)) shows a finished run as one readable story:

- **Named, and pointed at your source.** Every step shows the function it ran, the file and line, and the statement —
  so a step lands where you would put your cursor.
- **Across the client↔server boundary, one story.** A page action that awaits a server function reads as a single
  sequence, showing the values that **crossed** the wire — the arguments handed over and the value handed back.
- **The failure, for free.** A run that threw is kept with the exact place it threw and the values in scope there,
  whether or not you were recording — so the moment you most need the state is never the moment it is discarded.
- **The steps that led there, on demand.** Turn on recording ([Recording a run](https://osysharp.com/reference/local/recording-a-run/)) to also get the path a run
  took; add `--full` to capture the locals at **every** step — for a wrong *result* rather than a crash.

When what you hold is not a run's id but the id of an *interaction* (from an error dialog or a log line), `osy inspect
--correlation-id <id>` opens the set of runs that one click caused.

### Check it before you ship   {#check}

`osy lint` ([Checking your app](https://osysharp.com/reference/local/checking-your-app/)) reads the app the way a reviewer would and reports what is not
production-ready — before it becomes a live problem. Run it as the last step of the loop, and in whatever runs your
changes automatically.

### What IS this app? `osy model`   {#understand}

Sometimes the question is not what a run *did* but what the app *is* — its entities, pages, functions and how they
connect. `osy model` ([Understanding your app](https://osysharp.com/reference/local/understanding-your-app/)) answers that: the shape of the whole app, in a form a person or
an agent can read.

### The same loop, for a coding agent   {#for-agents}

Every command above has a machine-readable form (`--json`), and that is deliberate: the loop is the SDLC for a coding
agent as much as for you. An agent editing your app runs the same local platform, inspects the same runs, and checks
the same rules — and because a trace speaks in the names, source lines and values of the code the agent is holding, an
explanation lands directly in the `.osy` it is editing, not in terms it would have to reverse-engineer.

## See also       {#see-also}

[Running a local platform](https://osysharp.com/reference/local/running-a-local-platform/) — start the local platform the loop runs on.

[Launching your app](https://osysharp.com/reference/local/launching-your-app/) — compile the current source and open it in a browser.

[Seeing what happened when your code ran](https://osysharp.com/reference/local/seeing-what-happened/) — open a finished run and read what it did.

[Recording a run](https://osysharp.com/reference/local/recording-a-run/) — also record the steps, and (with `--full`) the locals at each step.

[Checking your app](https://osysharp.com/reference/local/checking-your-app/) — what is not production-ready yet.

[Understanding your app](https://osysharp.com/reference/local/understanding-your-app/) — the shape of the app itself, as opposed to what it did.
