# Giving a secret its value

> Declaring `app.Secrets` names a secret; it does not give it a value, and an app cannot run until something does. `osy secret set` supplies the value on your own machine — it writes the project's gitignored `.secrets` file, which every compile re-applies, and applies it straight away to a running local app. `osy secret list` shows which of your declared secrets still have no value here.

<!-- id: local-giving-a-secret-its-value · area: local · stability: stable · html: https://osysharp.com/reference/local/giving-a-secret-its-value/ -->

## Summary        {#summary}

[declaring secrets (app.Secrets)](https://osysharp.com/reference/config/secrets/) declares that your app uses a secret. It does not supply the value — a secret's value never appears
in source. `osy secret set` is how you supply it on **your own machine**, and `osy secret list` shows which declared
secrets still have none.

```console
osy secret set Anthropic          # prompts for the value, so it stays out of your shell history
osy secret list                   # which secrets are declared, and which still have no value here
```

## Signature      {#signature}

```console
osy secret list [--path <dir>] [--json]
osy secret set <NAME> [VALUE] [--path <dir>] [--devname <name>]
```

`NAME` must be a name your app declares in `app.Secrets`. A name it does not declare is refused — with the closest
declared name, when there is one — because a value your app cannot read is a credential stored for nothing.

## Description    {#description}

### Where the value is kept   {#secrets-file}

`osy secret set` writes the value to a file called `.secrets`, beside your `app.osy`. The format is one
`NAME=value` per line, so you can also edit it by hand — the two are exactly equivalent.

```text
Anthropic=sk-ant-...
```

That file is the **durable** source on your machine. Your app's secret values live in the app's database, and resetting
the local platform wipes them; every compile re-applies `.secrets`, so a reset cannot lose the values you set. This is
also why setting a value does not require a running platform: if one is running, the value is applied immediately and
takes effect without recompiling; if not, the next compile applies it.

`.secrets` holds credentials in plain text, so `osy secret set` makes sure it is ignored by git before writing to it —
adding it to your project's `.gitignore` if nothing already covers it. If your project is not in a repository at all, it
says so, because then there is nothing keeping the file out of an archive you share.

### Which secrets still need a value   {#listing}

```console
osy secret list
```

lists every secret your app declares and whether it has a value here. It reads the declarations from your **source**, so
it answers in a project you have never compiled, with no platform running. If `.secrets` sets a name your app does not
declare, `list` reports it: a compile refuses while that is true, and applies nothing.

### Values that are not yours to set   {#deployed}

`osy secret` is the LOCAL surface — your machine, your project. A deployed app's secrets are supplied by whoever
operates the platform it runs on, out of band, and are never read from a file in your project.

A **user-scoped** secret (`new Secret("Name") { UserScoped = true }`, see [declaring secrets (app.Secrets)](https://osysharp.com/reference/config/secrets/)) belongs to each user of
your app rather than to the app, so each user supplies their own through the app — there is no single value to set here.

## Examples       {#examples}

Give a declared API key its value and see the result:

```console
$ osy secret set Anthropic sk-ant-...
✓ Secret 'Anthropic' written to .secrets.
  This file is the durable local source: `osy compile` re-applies it, so a `dev --reset` cannot lose it.
  Added `.secrets` to .gitignore — it holds credentials in plain text.
  Applied to the running local app.

$ osy secret list
╭───────────┬─────────╮
│ Name      │ Value   │
├───────────┼─────────┤
│ Anthropic │ ●  set  │
╰───────────┴─────────╯
```

Omit the value to be prompted for it, so it never reaches your shell history:

```console
$ osy secret set Anthropic
Value for Anthropic: ********
```

A name your app does not declare is refused, with the near miss:

```console
$ osy secret set Anthropi sk-ant-...
✗ 'Anthropi' is not declared in `app.Secrets` — did you mean 'Anthropic'?
  This app declares: Anthropic
```

## See also       {#see-also}

[declaring secrets (app.Secrets)](https://osysharp.com/reference/config/secrets/) — declaring the secrets your app uses, and referencing one by its `Secret.Name` handle.

[Compiling your app](https://osysharp.com/reference/local/compiling-your-app/) — the compile that re-applies `.secrets` to your local app.

[default LLM model (app.DefaultModel)](https://osysharp.com/reference/agent/default-model/) — `app.DefaultModel`, whose `ApiKey` is a declared secret.
