@north-light/cli 0.3.543 → 0.3.544

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/builtin-memory/northlight-apps/build-on-your-app.md +47 -0
  2. package/dist/builtin-memory/northlight-apps/cli.md +3 -3
  3. package/dist/builtin-memory/northlight-apps/coding-agents.md +16 -7
  4. package/dist/builtin-memory/northlight-apps/concepts/apps-and-sign-in.md +0 -4
  5. package/dist/builtin-memory/northlight-apps/concepts/connections.md +0 -4
  6. package/dist/builtin-memory/northlight-apps/concepts/providers.md +0 -4
  7. package/dist/builtin-memory/northlight-apps/concepts/runs.md +0 -4
  8. package/dist/builtin-memory/northlight-apps/concepts/scopes-and-grants.md +0 -4
  9. package/dist/builtin-memory/northlight-apps/concepts/testing-mode.md +0 -4
  10. package/dist/builtin-memory/northlight-apps/get-started.md +56 -0
  11. package/dist/builtin-memory/northlight-apps/guides/go-live.md +1 -1
  12. package/dist/builtin-memory/northlight-apps/guides/manage-your-app.md +4 -4
  13. package/dist/builtin-memory/northlight-apps/how-it-fits.md +1 -1
  14. package/dist/builtin-memory/northlight-apps/know-the-person.md +29 -0
  15. package/dist/builtin-memory/northlight-apps/let-their-ai-use-your-app.md +67 -0
  16. package/dist/builtin-memory/northlight-apps/providers/README.md +1 -1
  17. package/dist/builtin-memory/northlight-apps/providers/context.md +2 -2
  18. package/dist/builtin-memory/northlight-apps/providers/device.md +3 -3
  19. package/dist/builtin-memory/northlight-apps/providers/integrations.md +1 -1
  20. package/dist/builtin-memory/northlight-apps/providers/search.md +1 -1
  21. package/dist/builtin-memory/northlight-apps/providers/sms.md +3 -3
  22. package/dist/builtin-memory/northlight-apps/quickstart.md +3 -17
  23. package/dist/builtin-memory/northlight-apps/reach-people-by-text.md +50 -0
  24. package/dist/builtin-memory/northlight-apps/use-our-ai.md +55 -0
  25. package/dist/builtin-memory/northlight-apps/use-our-apps.md +46 -0
  26. package/dist/core/command-plugins/transport/http-plan.d.ts +2 -0
  27. package/dist/core/command-plugins/transport/http-plan.js +1 -1
  28. package/dist/core/providers/call.js +1 -1
  29. package/dist/daemon/api/app-listener.d.ts +1 -1
  30. package/dist/daemon/api/app-listener.js +13 -13
  31. package/dist/daemon/api/handlers/providers.d.ts +3 -1
  32. package/dist/shared/traceparent.d.ts +6 -0
  33. package/dist/shared/traceparent.js +1 -0
  34. package/docs/apps/build-on-your-app.md +44 -0
  35. package/docs/apps/cli.md +3 -3
  36. package/docs/apps/coding-agents.md +16 -7
  37. package/docs/apps/concepts/apps-and-sign-in.md +0 -4
  38. package/docs/apps/concepts/connections.md +0 -4
  39. package/docs/apps/concepts/providers.md +0 -4
  40. package/docs/apps/concepts/runs.md +0 -4
  41. package/docs/apps/concepts/scopes-and-grants.md +0 -4
  42. package/docs/apps/concepts/testing-mode.md +0 -4
  43. package/docs/apps/get-started.md +47 -0
  44. package/docs/apps/guides/go-live.md +1 -1
  45. package/docs/apps/guides/manage-your-app.md +4 -4
  46. package/docs/apps/how-it-fits.md +1 -1
  47. package/docs/apps/know-the-person.md +27 -0
  48. package/docs/apps/let-their-ai-use-your-app.md +63 -0
  49. package/docs/apps/providers/README.md +1 -1
  50. package/docs/apps/providers/context.md +2 -2
  51. package/docs/apps/providers/device.md +3 -3
  52. package/docs/apps/providers/integrations.md +1 -1
  53. package/docs/apps/providers/search.md +1 -1
  54. package/docs/apps/providers/sms.md +3 -3
  55. package/docs/apps/quickstart.md +3 -17
  56. package/docs/apps/reach-people-by-text.md +47 -0
  57. package/docs/apps/use-our-ai.md +27 -0
  58. package/docs/apps/use-our-apps.md +32 -0
  59. package/docs/cli/join-northlight.md +1 -1
  60. package/package.json +2 -2
  61. package/packages/crouter-identity/package.json +1 -1
  62. package/runtime.lock.json +12 -12
@@ -0,0 +1,47 @@
1
+ ---
2
+ kind: knowledge
3
+ when-and-why-to-read: When you need Let other apps build on yours, this
4
+ knowledge should be read because Offer your app as a service other Northlight
5
+ apps build on — as a provider their runs call, or as your own API — and list
6
+ it with a docs link so their coding agents find it.
7
+ ---
8
+
9
+ # Let other apps build on yours
10
+
11
+ Other developers' apps can build on yours the way they build on Northlight's: by calling your provider tools from a run, or by calling your own API. Set a docs link on your app and it is listed on [Services you can build on](https://sdk.docs.northlight.ai/docs/services), where their coding agents look.
12
+
13
+ Comms is built this way. Another app calls it with its own Northlight app key, and reads [comms.northlight.ai/llms.txt](https://comms.northlight.ai/llms.txt) to learn how:
14
+
15
+ ```ts
16
+ import {readFile} from 'node:fs/promises';
17
+ import {CommsClient} from '@north-light/comms';
18
+
19
+ const comms = new CommsClient({
20
+ baseUrl: 'https://comms.northlight.ai',
21
+ issuer: 'https://account.northlight.ai',
22
+ clientId: process.env.CROUTER_CLIENT_ID!, // the calling app's own client id and key
23
+ privateKeyJwk: JSON.parse(await readFile(process.env.CROUTER_KEY_FILE!, 'utf8')),
24
+ });
25
+ ```
26
+
27
+ ## Two ways to offer it
28
+
29
+ - **As a provider.** Your tools run on the person's runtime for any app the person has granted them, and you can charge per call. This is the same work as [[northlight-apps/let-their-ai-use-your-app]]; other apps ask for your groups as scopes named `<your client id>:<group>`.
30
+ - **As your own API.** Serve HTTP from your own host, as Comms does. A calling app identifies itself with its Northlight client id and key, so you know which app is asking.
31
+
32
+ ## Get listed
33
+
34
+ 1. In the console, open your app's **Profile** tab.
35
+ 2. Under **Marketplace**, set **Docs link** to the https URL of your guide for agents and developers, for example `https://yourapp.com/llms.txt`, and choose **Save docs link**.
36
+ 3. Write that guide for a coding agent: what your service does, how to install the client, one working snippet, the errors and their fixes. [comms.northlight.ai/llms.txt](https://comms.northlight.ai/llms.txt) is a working example.
37
+
38
+ [Services you can build on](https://sdk.docs.northlight.ai/docs/services) is rebuilt from the directory's public marketplace list each time this site is built, so a new docs link appears with no change to these docs.
39
+
40
+ ## Guides
41
+
42
+ | Page | What it covers |
43
+ |---|---|
44
+ | [[northlight-apps/let-their-ai-use-your-app]] | Define tools with `@north-light/plugin`, serve them, add the provider role, set a price |
45
+ | [Services you can build on](https://sdk.docs.northlight.ai/docs/services) | Every listed app with a docs link |
46
+ | [[northlight-apps/guides/manage-your-app]] | The console's **Profile** and **Provider** tabs |
47
+ | [[northlight-apps/guides/go-live]] | Verification and the marketplace listing |
@@ -7,7 +7,7 @@ when-and-why-to-read: When you need CLI reference, this knowledge should be read
7
7
 
8
8
  # CLI reference
9
9
 
10
- `npx @north-light/sdk <command>` runs the package's one command-line tool. Run it with no command, or with `--help`, to print the list below. `npx @north-light/sdk <command> --help` (or `-h`) prints that command's usage and exits 0. An unknown command, or a bad flag, prints the usage and exits 1.
10
+ `npx @north-light/sdk <command>` runs the command-line tool of [`@north-light/sdk`](https://www.npmjs.com/package/@north-light/sdk) on npm. (crouter's own CLI, `crtr`, is a different package: [`@north-light/cli`](https://www.npmjs.com/package/@north-light/cli). Tools you offer to agents are built with [`@north-light/plugin`](https://www.npmjs.com/package/@north-light/plugin).) Run it with no command, or with `--help`, to print the list below. `npx @north-light/sdk <command> --help` (or `-h`) prints that command's usage and exits 0. An unknown command, or a bad flag, prints the usage and exits 1.
11
11
 
12
12
  With no dependencies installed, `npx` downloads the newest published release of the SDK (the one tagged latest on npm), not the version your project pins. Run `npm i` in the project first if the pinned version must run; `init` pins the version of the CLI that ran it.
13
13
 
@@ -23,7 +23,7 @@ With no dependencies installed, `npx` downloads the newest published release of
23
23
  | `npx @north-light/sdk register [--name <text>] [--scope <scope>]... [--logo <url>] [--justification <text>] [--redirect-uri <uri>]... [--issuer <url>]` | Run in a project made by `init`, after `login`: registers the app with the public key from `local/app-key.json`, adds each `--scope` beyond `crtr:llm crtr:act`, and writes `CROUTER_CLIENT_ID` and `CROUTER_ISSUER` to `local/app.env`. | No |
24
24
  | `npx @north-light/sdk apps <leaf> [--app <client id>] [--issuer <url>] [leaf flags] [--json]` | Call one app-management leaf with the login and print its answer as JSON. Leaves: `mine`, `get`, `update`, `set-logo --file <path>`, `set-brand-color --color <#rrggbb|none>`, `set-redirect-uris`, `asks`, `set-scopes`, `set-requires`, `set-run-notice-url`, `keys list\|add\|retire\|delete\|set-jwks-uri\|remove-jwks-uri`, `testers list\|add\|remove`. `--app` defaults to `CROUTER_CLIENT_ID` in `local/app.env`; `keys add` takes `--key-file <path>` and sends only the public half. Deleting an app, its marketplace listing, monthly spend cap, sharing and provider role are console-only: those leaves exit 1 and name the console page, with no request. | No |
25
25
 
26
- `keygen` and `env` are the only commands that can call `crtr`, and only with `--app`. The documented path on this site never uses `--app`, so you do not need crtr. `login`, `logout`, `whoami`, `register` and `apps` call only the Northlight directory.
26
+ `keygen` and `env` are the only commands that can call `crtr`, and only with `--app`. The rest of this site never uses `--app`, so crtr is optional; to use it, see [[northlight-apps/get-started]]. `login`, `logout`, `whoami`, `register` and `apps` call only the Northlight directory.
27
27
 
28
28
  ## Details
29
29
 
@@ -65,7 +65,7 @@ Writes the `northlight` Agent Skill that ships in the package, replacing an olde
65
65
 
66
66
  ### `keygen`
67
67
 
68
- Writes a private signing key to `local/app-key.json` with mode `0600`, refuses to overwrite an existing file (pass `--out` for another path), and prints the public JWK on stdout. Register the JWK in the console with **Add key** on the app's **Sign-in** tab, or paste it under **Register an app**. With `--app <client id>`, it offers to add the key to your app through your own `crtr` (`crtr cloud apps keys add`); `--yes` skips the question. This needs a joined crtr, which this site does not otherwise require.
68
+ Writes a private signing key to `local/app-key.json` with mode `0600`, refuses to overwrite an existing file (pass `--out` for another path), and prints the public JWK on stdout. Register the JWK in the console with **Add key** on the app's **Sign-in** tab, or paste it under **Register an app**. With `--app <client id>`, it offers to add the key to your app through your own `crtr` (`crtr cloud apps keys add`); `--yes` skips the question. This needs a joined crtr.
69
69
 
70
70
  ### `env`
71
71
 
@@ -8,7 +8,7 @@ when-and-why-to-read: When you need Use your coding agent, this knowledge should
8
8
 
9
9
  # Use your coding agent
10
10
 
11
- The `northlight` skill teaches a coding agent the whole path in the [[northlight-apps/quickstart]]: the commands, the code patterns and the rules. With it, your agent signs you up, logs in, registers the app and runs it, and you choose **Allow** twice in your browser: once on the login page, once on the app's consent page. `npx @north-light/sdk init` installs it into your project. The skill needs no account and no crtr.
11
+ The `northlight` skill teaches a coding agent the whole path in the [[northlight-apps/quickstart]]: the commands, the code patterns and the rules. With it, your agent signs you up, logs in, registers the app and runs it, and you choose **Allow** twice in your browser: once on the login page, once on the app's consent page. `npx @north-light/sdk init` installs it into your project. The skill needs no account to install, and works whether or not crouter is on your machine.
12
12
 
13
13
  ## Install it
14
14
 
@@ -28,6 +28,17 @@ npx @north-light/sdk skill
28
28
 
29
29
  `skill` always replaces the `northlight` skill it finds. `--print` writes the skill to stdout instead of to files.
30
30
 
31
+ ## Install it once for every project (Claude Code)
32
+
33
+ If you build more than one app, install the Claude Code plugin instead of a copy in each project:
34
+
35
+ ```
36
+ /plugin marketplace add Northlight-Systems/plugins
37
+ /plugin install northlight
38
+ ```
39
+
40
+ It adds the `northlight` skill, one skill for each section of this site, and the commands `/northlight:new-app`, `/northlight:add-permission`, `/northlight:text-people`, `/northlight:become-a-provider` and `/northlight:go-live`. The plugin repository is generated from these docs and the skill at each release, so it matches the current SDK version.
41
+
31
42
  ## Where it goes
32
43
 
33
44
  | Agent | In the project (default) | With `--global` |
@@ -39,7 +50,7 @@ npx @north-light/sdk skill
39
50
 
40
51
  The project copy is the default so it is committed with the project, and teammates get it from git. It matches the SDK version your project pins.
41
52
 
42
- Checked on production: the files `init` writes, that `init` in a directory that already has a `package.json` pins the SDK and writes the key and skill but no app code, and that `skill` rewrites both skill files. In such a directory `init` creates a `.gitignore` with `local/`, or adds `local/` to the one you have, so the key stays out of git. Which agent loads which directory is from each agent's documentation and is not yet checked on production for every agent.
53
+ In a directory that already has a `package.json`, `init` creates a `.gitignore` with `local/`, or adds `local/` to the one you have, so the key stays out of git.
43
54
 
44
55
  ## Without a project: the hosted skill
45
56
 
@@ -53,7 +64,7 @@ If the agent's shell call times out or is interrupted while you approve, it runs
53
64
 
54
65
  The skill tells the agent to read the whole message `login` printed and its exit code before it tells you what happened.
55
66
 
56
- Checked on production with Claude Code (an interactive session, no crtr on `PATH`, an empty directory), given only the skill URL plus the quickstart request: a fresh session ran `init`, `login`, `npm i`, `register --scope sms:send` and `npm start` by itself. The person's part was choosing **Allow** on the login page and on the app's consent page, and pressing the button; the run replied `pong` and the text was sent (whether it reached the phone is not checked). When the first login code expired unapproved, that session said so and ran `login` again for a new code. In an earlier session on the same day, before this guidance, the agent misread a failed second `login` as a network timeout and fell back to the console steps. Name what you want built in the prompt.
67
+ Name what you want built in the prompt.
57
68
 
58
69
  ## What the login can do
59
70
 
@@ -68,13 +79,11 @@ Checked on production with Claude Code (an interactive session, no crtr on `PATH
68
79
  | Change signing keys, redirect URIs and the run notice URL on an app in testing | Change those on a verified app: do it in the console |
69
80
  | | Approve another login |
70
81
 
71
- Deleting an app, its listing, spend cap and sharing stay in the console on purpose. The CLI refuses them without sending a request, and the directory refuses them (403 `provider_refused`) if a call is made by hand. Checked on production for delete, the marketplace listing and the spend cap.
82
+ Deleting an app, its listing, spend cap and sharing stay in the console on purpose. The CLI refuses them without sending a request, and the directory refuses them (403 `provider_refused`) if a call is made by hand.
72
83
 
73
84
  The login lives in `~/.config/northlight/credentials.json` (`$XDG_CONFIG_HOME/northlight/credentials.json` when set), mode `0600`, outside your project. The CLI refuses a file that other users can read. It lasts 30 days, or until it has gone 14 days unused, and then you run `login` again. An account holds at most 10 logins; an eleventh replaces the oldest. The Developer access page shows the date the login goes unused, "Expires Oct 31" for a login approved on Oct 17, not the 30-day date the CLI prints.
74
85
 
75
- Revoke it on your account's Developer access page (`https://account.northlight.ai/account/developer`), or run `npx @north-light/sdk logout`, which revokes it on the server and removes it from the file. The file is not deleted: it is rewritten as `{"version":1,"issuers":{}}`, with no secret in it. A revoked login stops working at once: `whoami` and every other command fail with "This login was revoked" and ask for `login`, and a token minted before the revoke is refused with 401 `credential_revoked` even before it expires. Checked on production: the Developer access page, Revoke, `logout`, and what the next command prints.
76
-
77
- Not yet checked on production: the 10-login limit and the eleventh login replacing the oldest, and the 14-day and 30-day expiries.
86
+ Revoke it on your account's Developer access page (`https://account.northlight.ai/account/developer`), or run `npx @north-light/sdk logout`, which revokes it on the server and removes it from the file. The file is not deleted: it is rewritten as `{"version":1,"issuers":{}}`, with no secret in it. A revoked login stops working at once: `whoami` and every other command fail with "This login was revoked" and ask for `login`, and a token minted before the revoke is refused with 401 `credential_revoked` even before it expires.
78
87
 
79
88
  ## How it stays current
80
89
 
@@ -103,7 +103,3 @@ LoggerModule.forRoot({
103
103
  ```
104
104
 
105
105
  Test it: send a callback with a recognizable fake code and assert that the code, the state and the cookie never appear in the log output.
106
-
107
- ## Checked and not checked
108
-
109
- Checked on production: the discovery document lists `S256` and `private_key_jwt`, and the login route of the quickstart server redirects to `https://account.northlight.ai/authorize` with the PKCE challenge and nonce. The rest is from the SDK and directory source. A full sign-in as the account that owns the app, through the consent page and the callback, was run on production with the quickstart server. A sign-in by a second person, token refresh and the refusals are not yet checked on production.
@@ -120,7 +120,3 @@ It needs the app registered with the `app_token_for_user` operation, and an acti
120
120
  ## Signing in a visitor
121
121
 
122
122
  A person who only needs to be recognized, not connected, signs in with identity only: request `openid`, optionally with `email` and `profile`, and no runtime scope. Finish with `exchangeIdentity`, not `exchangeCode`. An `Identity` is not a connection: no runtime URL, grant or refresh token (if the directory answers with one anyway, `exchangeIdentity` revokes the refresh token), nothing goes in the store, and you keep your own session. To act for that person later, send them through `authorizeUrl` again with the runtime scopes you need.
123
-
124
- ## Checked and not checked
125
-
126
- From the SDK source and tests. The refresh and refusal paths against `account.northlight.ai` are not yet checked on production.
@@ -71,7 +71,3 @@ if (context?.state !== 'ready') {
71
71
  | `unavailable` | The provider does not offer this to the person's account. `message` says so; there is nothing for them to do. |
72
72
 
73
73
  `message` is the provider's own sentence, present for `pending`, `failed` and `unavailable`. `step` is present when the provider reports where things stand (for example `researching`); its values may grow, so ignore one you do not know. `next` is the absolute URL of the setup page for this provider and your app; `setupLink(dependency, {returnTo})` from `@north-light/sdk` adds a `return_to` with your app's registered origin so the person returns to you, and keeps the query `next` already carries. A key can contain a dot (`context.deep`). An entry is missing when the runtime has not synced the grant since the app began requiring the provider: treat that as `not_started`. The runtime does not block your calls for you, so refuse the dependent operation yourself. To act the moment a state turns `ready`, follow it with `oauth.watchGrants`; see [[northlight-apps/guides/grant-changes]].
74
-
75
- ## Checked and not checked
76
-
77
- From the SDK source (`providers.tools`, `providers.call`, `grant.get`) and the directory source. The sms limits come from the existing SDK guide. A real `providers.call` for `sms` on production returned a `message_id` for a text to the signed-in person. That the text arrived is not yet checked.
@@ -97,7 +97,3 @@ try {
97
97
  ## Learn when a background run ends
98
98
 
99
99
  A run you start and do not wait on ends while nobody holds a request. `oauth.watchRuns(...)` follows those runs for you and calls `onEnded` for each one that comes to rest. See [[northlight-apps/guides/background-runs]].
100
-
101
- ## Checked and not checked
102
-
103
- From the SDK source and its tests. On production, `runs.start` and `runs.wait` ran the quickstart's prompt and settled with status `idle`; the run's reply text and `activity` are not yet checked.
@@ -58,7 +58,3 @@ A run's list must stay inside the grant, and a child agent never regains a scope
58
58
  ## Your app's own space
59
59
 
60
60
  Your app has its own space on each person's runtime: documents and files owned by your app. Your server and runs started without a `scopes` list read and write it freely. A run started with a `scopes` list needs `crtr:memory:read:app:<your client id>` or `crtr:memory:rw:app:<your client id>` to touch it. Another app's space is reachable only where that app allows it.
61
-
62
- ## Checked and not checked
63
-
64
- From the SDK source, the directory console source and the existing SDK guide. `403 scope_missing` for a missing `crtr:act` and the consent page's behavior are not yet checked on production.
@@ -48,7 +48,3 @@ Email support@northlight.ai to have the app verified. Only Northlight staff can
48
48
  ## Test the refusal in code
49
49
 
50
50
  `@north-light/sdk/testing` has a fake directory that can refuse a sign-in as an app in testing, so you can test this path without a second account. See [[northlight-apps/guides/test-your-app]].
51
-
52
- ## Checked and not checked
53
-
54
- From the SDK source, the console source and the testing-mode specification. Adding a tester, a second person signing in, the `app_in_testing` redirect and removing a tester have not been run on production (not yet checked on production). Those steps need a second account.
@@ -0,0 +1,56 @@
1
+ ---
2
+ kind: knowledge
3
+ when-and-why-to-read: When you need Get started, this knowledge should be read
4
+ because What every Northlight app needs first — an account, a registered app,
5
+ sign-in with Northlight, a stored connection per person, scopes, and testing
6
+ mode — and where each is covered.
7
+ ---
8
+
9
+ # Get started
10
+
11
+ Every app on Northlight starts the same way: a person signs in with their Northlight account, your server stores a connection for them, and from then on it calls their runtime with `oauth.client(userId)`. The six sections of this site all build on that.
12
+
13
+ ```bash
14
+ npx @north-light/sdk@latest init my-app
15
+ ```
16
+
17
+ `init` writes a Node server, a signing key and an env file. [[northlight-apps/quickstart]] takes it from there to a running app in about ten minutes. Using a coding agent? Tell it: *Read https://sdk.docs.northlight.ai/SKILL.md and follow it.* See [[northlight-apps/coding-agents]].
18
+
19
+ Once a person has signed in, this is all it takes to use their runtime:
20
+
21
+ ```ts
22
+ const runtime = await oauth.client(userId); // a client on this person's runtime, from their stored connection
23
+ // The prompt is the instruction; the message stored with it joins the first turn, so `reply` can follow that turn.
24
+ const started = await runtime.runs.start({prompt: 'Reply with exactly the word: pong', message: 'ping', scopes: ['crtr:llm', 'crtr:act']});
25
+ const reply = await runtime.runs.reply(started.run_id, started.message!).collect(); // reply.text is what the agent said
26
+ const run = await runtime.runs.wait(started.run_id); // status is 'idle' once the reply is done
27
+ ```
28
+
29
+ ## What to read, in order
30
+
31
+ | Page | What it covers |
32
+ |---|---|
33
+ | [[northlight-apps/quickstart]] | From no account to an app that signs you in, starts a run and texts your phone |
34
+ | [[northlight-apps/coding-agents]] | The `northlight` skill that `init` installs for Claude Code, Codex, Cursor and Copilot |
35
+ | [[northlight-apps/how-it-fits]] | Your server, the directory at `account.northlight.ai`, and each person's runtime |
36
+ | [[northlight-apps/concepts/apps-and-sign-in]] | What registering creates, the key pair, and the sign-in flow `OAuth2Client` runs |
37
+ | [[northlight-apps/concepts/connections]] | What you store per person, token refresh, and refused connections |
38
+ | [[northlight-apps/concepts/scopes-and-grants]] | What your app may ask for, what a person allowed, and a run's own scopes |
39
+ | [[northlight-apps/concepts/testing-mode]] | You and up to 100 testers can sign in until the app is verified |
40
+ | [[northlight-apps/guides/test-your-app]] | Test your server against `@north-light/sdk/testing` without a network |
41
+ | [[northlight-apps/guides/manage-your-app]] | The console's tabs: sign-in, scopes, profile, sharing, testers and provider |
42
+ | [[northlight-apps/guides/go-live]] | Persistent storage, a real host, verification and the marketplace |
43
+
44
+ Then pick what your app does from the sections in the sidebar: [[northlight-apps/use-our-ai]], [[northlight-apps/use-our-apps]], [[northlight-apps/know-the-person]], [[northlight-apps/reach-people-by-text]], [[northlight-apps/let-their-ai-use-your-app]], or [[northlight-apps/build-on-your-app]].
45
+
46
+ ## Run `crtr cloud apps` yourself
47
+
48
+ Everything on this site works with the SDK's own commands and the web console. If you also run crouter, the agent runtime Northlight is built on, you can join your machine to your Northlight account and manage your apps with `crtr cloud apps`, or let your own crouter agents build and manage them.
49
+
50
+ ```bash
51
+ npm install -g @north-light/cli
52
+ crtr sys join --directory https://account.northlight.ai --token <token>
53
+ crtr cloud apps mine
54
+ ```
55
+
56
+ The token comes from **Create join token** at `https://account.northlight.ai/account/machines`. The full steps, and what joining changes on your machine, are in [Join a machine to your Northlight account](https://crouter.docs.northlight.ai/docs/cli/join-northlight). The CLI is [`@north-light/cli`](https://www.npmjs.com/package/@north-light/cli) on npm, and crouter's own docs are at [crouter.docs.northlight.ai](https://crouter.docs.northlight.ai).
@@ -32,7 +32,7 @@ Four variables configure an app built on the SDK:
32
32
 
33
33
  A new app is in testing: only you and up to 100 testers can sign in. To open it to everyone, ask Northlight to verify it by email to support@northlight.ai. Include your app's name and client ID, where it runs, and what it asks for and why. Until then, anyone else is refused with `app_in_testing`. See [[northlight-apps/concepts/testing-mode]].
34
34
 
35
- This site does not state how long verification takes or what Northlight checks beyond that email address (not yet checked on production).
35
+ This site does not state how long verification takes or what Northlight checks beyond that email address.
36
36
 
37
37
  ## Rotate the key later
38
38
 
@@ -7,7 +7,7 @@ when-and-why-to-read: When you need Manage your app, this knowledge should be
7
7
 
8
8
  # Manage your app
9
9
 
10
- You manage an app in the console at `https://account.northlight.ai/console`. Choose your app in the list to open its page. The tabs are Sign-in, What it asks for, Profile, Sharing, Testers and Provider. (Only the first-party apps use Provider.)
10
+ You manage an app in the console at `https://account.northlight.ai/console`. Choose your app in the list to open its page. The tabs are Sign-in, What it asks for, Profile, Sharing, Testers and Provider. **Provider** is where an app offers its own tools to people's agents and to other apps: see [[northlight-apps/let-their-ai-use-your-app]].
11
11
 
12
12
  Your **client ID** is shown on the app's page. `npx @north-light/sdk register` writes it to `local/app.env`; for an app registered in the browser, use `npx @north-light/sdk env --client-id <client id>`.
13
13
 
@@ -24,7 +24,7 @@ The login cannot do these, and the CLI refuses them without a request:
24
24
  - The provider role.
25
25
  - On a verified app: signing keys, the JWKS URL, redirect URIs and the run notice URL.
26
26
 
27
- Everything below names its `apps` command when there is one. (Not yet checked on production for any `apps` command.)
27
+ Everything below names its `apps` command when there is one.
28
28
 
29
29
  ## Sign-in
30
30
 
@@ -48,7 +48,7 @@ Until you retire the old key it is your rollback. After you retire it, a sign-in
48
48
  - **What your app asks for.** The scopes people are asked to approve. **Add permissions** searches the catalog; take scope strings from it and from `providers.tools`, and do not invent them. From the terminal: `apps asks` lists what the app can ask for, and `apps set-scopes --add <scope>` or `--remove <scope>` changes the list. `crtr:act` needs `crtr:llm`. See [[northlight-apps/concepts/scopes-and-grants]].
49
49
  - **What your app requires.** Providers the app cannot work without (`apps set-requires`). A person is taken through that provider's setup the first time they sign in. See [[northlight-apps/guides/grant-changes]].
50
50
  - **Monthly spend cap.** The most your app may spend of each person's AI subscription per month, in whole US dollars.
51
- - **Run notice URL.** Where Northlight posts a signed notice when one of your app's background runs ends. Type it in **Notice URL** and choose **Save**; empty it and save to turn notices off. From the terminal: `apps set-run-notice-url` (apps in testing). The URL must be `https`, at most 512 characters, with no `#fragment`. The directory refuses a plain `http` URL with `run_notice_url` as the field. The field's hint says `http://localhost` is accepted while developing, but the production directory refuses it (checked in the directory source, not yet checked on production), so test notices with a tunnel that gives you an `https` URL. What your app does with a notice is in [[northlight-apps/guides/background-runs]].
51
+ - **Run notice URL.** Where Northlight posts a signed notice when one of your app's background runs ends. Type it in **Notice URL** and choose **Save**; empty it and save to turn notices off. From the terminal: `apps set-run-notice-url` (apps in testing). The URL must be `https`, at most 512 characters, with no `#fragment`. The directory refuses a plain `http` URL with `run_notice_url` as the field. The field's hint says `http://localhost` is accepted while developing, but the production directory refuses it, so test notices with a tunnel that gives you an `https` URL. What your app does with a notice is in [[northlight-apps/guides/background-runs]].
52
52
 
53
53
  ## Profile
54
54
 
@@ -77,6 +77,6 @@ Once your app is live you can keep developing on your laptop against production
77
77
 
78
78
  On the **Profile** tab, the **Delete this app** card lists what goes: every person's connection to the app, yours included (each person's runtime deletes the app's runs, space and schedules), the app's sign-ins and keys, and its testers and marketplace listing. This cannot be undone, and the client ID is never reused.
79
79
 
80
- To delete, type the app's full name in **Type the app's name, *name*, to confirm**. **Delete app** stays disabled until what you typed matches the name (surrounding spaces are ignored), and the directory checks the name again when you submit. After it deletes, the console returns to your app list. Checked on production: the app is gone from the list, the console's API answers 404 `App not found` for it, and `/authorize` with its client ID shows "We couldn't start that sign-in" (HTTP 400). The app's next refresh for any person failing with `invalid_grant` is not yet checked on production.
80
+ To delete, type the app's full name in **Type the app's name, *name*, to confirm**. **Delete app** stays disabled until what you typed matches the name (surrounding spaces are ignored), and the directory checks the name again when you submit. After it deletes, the console returns to your app list. After that, `/authorize` with its client ID shows "We couldn't start that sign-in" (HTTP 400).
81
81
 
82
82
  The card is not shown for a provider or a first-party app, and the directory refuses to delete a provider (`app_is_provider`). If you only want a clean slate for tests, changing the app's redirect URIs and keys is often simpler.
@@ -46,4 +46,4 @@ The person's AI subscription pays for model calls, and what your app may do on t
46
46
 
47
47
  You operate your server, its sessions, its database and its `ConnectionStore`. You register the app in the console and keep its key pair. Northlight operates the directory and the runtimes; you do not run either, and there is no local Northlight to start. If you run crouter yourself and want a runtime of your own, that is a different path: see [crouter.docs.northlight.ai](https://crouter.docs.northlight.ai).
48
48
 
49
- The directory's discovery document at `https://account.northlight.ai/.well-known/openid-configuration` lists the endpoints, the `S256` PKCE method and `private_key_jwt` as the only token authentication method (checked on production).
49
+ The directory's discovery document at `https://account.northlight.ai/.well-known/openid-configuration` lists the endpoints, the `S256` PKCE method and `private_key_jwt` as the only token authentication method.
@@ -0,0 +1,29 @@
1
+ ---
2
+ kind: knowledge
3
+ when-and-why-to-read: When you need Let your app know the person, this knowledge
4
+ should be read because Learn who the person is and what they care about from
5
+ their first sign-in, with the context provider and their public documents.
6
+ ---
7
+
8
+ # Let your app know the person
9
+
10
+ A person who signs in to your app already has a Northlight agent that knows them. Your app can ask it about them from the first sign-in, so onboarding needs fewer questions and the product fits them sooner.
11
+
12
+ ```ts
13
+ const runtime = await oauth.client(userId);
14
+ const advice = await runtime.providers.call({
15
+ provider: 'context',
16
+ tool: 'ask informed', // pass the name exactly as providers.tools('context') lists it
17
+ arguments: {request: 'Suggest the first three topics for this person\'s reading list.'},
18
+ });
19
+ ```
20
+
21
+ `ask informed` (scope `context:ask_informed`) answers from everything their agent knows, private memories included, without handing you private details. `ask public` (scope `context:ask_public`) answers from their public memories only.
22
+
23
+ ## Guides
24
+
25
+ | Page | What it covers |
26
+ |---|---|
27
+ | [[northlight-apps/providers/context]] | The context provider's scopes, setup and tools, including public profile lookups |
28
+ | [[northlight-apps/guides/files-and-documents]] | Read the documents the person made public with `memory.list` and `memory.get`, with no scope |
29
+ | [[northlight-apps/concepts/providers]] | Require `context` so the person sets it up at first sign-in |
@@ -0,0 +1,67 @@
1
+ ---
2
+ kind: knowledge
3
+ when-and-why-to-read: When you need Let the person's AI use your app, this
4
+ knowledge should be read because Make your app a provider so its tools show up
5
+ in the person's chat and terminal agents. Define commands with
6
+ @north-light/plugin, serve them over HTTP, and add the provider role in the
7
+ console.
8
+ ---
9
+
10
+ # Let the person's AI use your app
11
+
12
+ Your app can be a provider: it offers tools, and once a person connects it, every agent they run (in Northlight chat, in their terminal, and in other apps that ask for it) can call them. You define the tools once with [`@north-light/plugin`](https://www.npmjs.com/package/@north-light/plugin) and serve them from your own server.
13
+
14
+ ```ts
15
+ import {createFetchHandler, defineLeaf, definePlugin, field, param} from '@north-light/plugin';
16
+
17
+ export const plugin = definePlugin({
18
+ name: 'acme',
19
+ provider: true,
20
+ version: 1,
21
+ description: 'Manage Acme orders.',
22
+ whenToUse: 'you need to look up an Acme order.',
23
+ summary: 'Acme orders',
24
+ rootEntry: {concept: 'an Acme order', description: 'Look up orders.', whenToUse: 'the task is about an Acme order.'},
25
+ groups: {read: {consentLine: 'Read your Acme orders.'}},
26
+ commands: {
27
+ order: defineLeaf({
28
+ group: 'read',
29
+ description: 'Show one order.',
30
+ whenToUse: 'you have an order id.',
31
+ summary: 'show an order',
32
+ params: {id: param.positional('The order id.', {required: true})},
33
+ output: {status: field.string('The order status.')},
34
+ effects: ['Reads one order.'],
35
+ handler: (input, ctx) => ({status: 'shipped'}), // ctx.caller.sub is the person who connected
36
+ }),
37
+ },
38
+ });
39
+
40
+ export default createFetchHandler(plugin, {
41
+ auth: {issuer: 'https://account.northlight.ai', audience: 'https://acme.example.com/crtr', providerId: process.env.CROUTER_CLIENT_ID!},
42
+ });
43
+ ```
44
+
45
+ Each group in `groups` is a scope named `<your client id>:<group>`, and its `consentLine` is what the consent page shows. Every request carries a token the directory minted for one person; the handler checks it and the group's scope before your code runs.
46
+
47
+ ## The steps
48
+
49
+ 1. **Define the tools** with `definePlugin({provider: true, version, groups, commands})`. Every leaf names its `group`.
50
+ 2. **Serve them** at an HTTPS URL. `createFetchHandler` is a standard Fetch handler; `createNodeHandler` serves the same plugin from Node's `http` server.
51
+ 3. **Add the provider role.** In the console, open your app's **Provider** tab, fill in **Offer tools to other apps** with your **Endpoint URL** (and an optional **Manage URL**, where people manage their connection), and choose **Add provider role**. The directory fetches your manifest and saves the groups it declares. After a change, choose **Refresh manifest**.
52
+ 4. **Set a price**, if you charge, on the same tab: free, a price per unit, or the cost your provider reports, plus a free monthly allowance per person.
53
+
54
+ ## Who may use a group
55
+
56
+ A group's `who` says who may be granted it: `own` (only your own app), `user` (the default), `allowlist` (the apps listed in `allowlist`), `any`, or `team:<id>`. The directory applies `own` and `team:<id>`; `user`, `allowlist` and `any` are stored but not yet enforced at consent.
57
+
58
+ ## Guides
59
+
60
+ These live on the crouter docs site, because the same package also adds commands to a self-run crouter:
61
+
62
+ | Page | What it covers |
63
+ |---|---|
64
+ | [Plugin docs](https://crouter.docs.northlight.ai/docs/plugin) | What `@north-light/plugin` does and how a plugin is installed |
65
+ | [Commands](https://crouter.docs.northlight.ai/docs/plugin/commands) | Branches, leaves, parameters, outputs, groups and `who` |
66
+ | [Deploying](https://crouter.docs.northlight.ai/docs/plugin/deploying) | `auth: {issuer, audience, providerId}`, `ctx.caller`, versions and breaking changes |
67
+ | [[northlight-apps/guides/manage-your-app]] | The console's **Provider** tab beside the others |
@@ -38,4 +38,4 @@ export async function textMe(runtime: ConnectedCrouter, body: string) {
38
38
  }
39
39
  ```
40
40
 
41
- Each provider page below shows the tools of a provider as captured on **2026-10-16**. The capture is not an app's view: it came from the runtime of a person's own Northlight account (`GET /v1/providers/<id>/tools` on `crtr` 0.3.462, joined to production), which shows the groups that person's own grant holds. What `providers.tools` answers for your app depends on the scopes your app was granted. Tools can change between releases, so treat a table as a starting point and list the tools at run time.
41
+ Each provider page below shows the tools of a provider as listed on **2026-10-16** by a person's own Northlight runtime, so it shows the groups that person's own grant holds, not an app's view. What `providers.tools` answers for your app depends on the scopes your app was granted. Tools can change between releases, so treat a table as a starting point and list the tools at run time.
@@ -11,13 +11,13 @@ The `context` provider answers questions about the person from what their agent
11
11
 
12
12
  ## Scopes and setup
13
13
 
14
- Scopes are `context:<group>`. The console's **Add permissions** list shows `context:ask_informed` and `context:ask_public` on 2026-10-16; the tool list also shows a `research` group (`context:research`) that was not in that console list when we checked (not yet checked on production).
14
+ Scopes are `context:<group>`. The console's **Add permissions** list shows `context:ask_informed` and `context:ask_public` on 2026-10-16; the tool list also shows a `research` group (`context:research`). It was not in that console list on that date, so check that **Add permissions** offers it before your app depends on it.
15
15
 
16
16
  Context needs setup before it works: the person gives a profile URL on the provider's setup page, and its state stays `pending` for a few minutes afterwards. If your app depends on it, add `context` under **What your app requires** and follow the state with `grant.get().dependencies['context']`. See [[northlight-apps/guides/grant-changes]].
17
17
 
18
18
  ## Tools
19
19
 
20
- Captured 2026-10-16 from `GET /v1/providers/context/tools` on a joined runtime (provider major version 1). `*` marks a required parameter. Tool names with a space are written as the provider lists them; check how to pass a multi-word `tool` to `providers.call` against your own `providers.tools` output before relying on it (not yet checked on production).
20
+ Tools as listed on 2026-10-16 (provider major version 1). `*` marks a required parameter. Tool names with a space are written as the provider lists them; pass a multi-word `tool` to `providers.call` exactly as your own `providers.tools` output lists it.
21
21
 
22
22
  | Tool | Group | Parameters | What it does |
23
23
  |---|---|---|---|
@@ -7,7 +7,7 @@ when-and-why-to-read: "When you need Device, this knowledge should be read
7
7
 
8
8
  # Device
9
9
 
10
- The `device` provider reaches the person's own Mac. Its tools run on the person's machine (the provider's transport is `machine`), and each group is its own scope, so ask only for the groups your app needs. What happens when the Mac is asleep or offline is not yet checked on production. When the person has more than one registered Mac, a call must name the one to use with `machine` (`providers.call({provider: 'device', tool, arguments, machine})`); without it the runtime refuses with `machine_required` (except `browser libs`, which uses the most recently seen Mac).
10
+ The `device` provider reaches the person's own Mac. Its tools run on the person's machine (the provider's transport is `machine`), and each group is its own scope, so ask only for the groups your app needs. When the person has more than one registered Mac, a call must name the one to use with `machine` (`providers.call({provider: 'device', tool, arguments, machine})`); without it the runtime refuses with `machine_required` (except `browser libs`, which uses the most recently seen Mac).
11
11
 
12
12
  ## Scopes
13
13
 
@@ -15,7 +15,7 @@ The `device` provider reaches the person's own Mac. Its tools run on the person'
15
15
 
16
16
  ## Tools
17
17
 
18
- Captured 2026-10-16 from `GET /v1/providers/device/tools` on a joined runtime (provider major version 2, transport `machine`). `*` marks a required parameter.
18
+ Tools as listed on 2026-10-16 (provider major version 2, transport `machine`). `*` marks a required parameter.
19
19
 
20
20
  | Group (scope) | Tools |
21
21
  |---|---|
@@ -25,4 +25,4 @@ Captured 2026-10-16 from `GET /v1/providers/device/tools` on a joined runtime (p
25
25
  | `messages_send` | `messages send` (`recipient`\*, `text`\*, `file`, `service`) |
26
26
  | `shell` | `shell run` (`command`\*, `cwd`, `timeout`, `stdin`) |
27
27
 
28
- Tool names with spaces are written as the provider lists them; check how to pass them to `providers.call` against your own `providers.tools` output (not yet checked on production). The capture is of a person's own grant, not an app's. Run `runtime.providers.tools('device')` for the list your app can use.
28
+ Tool names with spaces are written as the provider lists them; pass them to `providers.call` exactly as your own `providers.tools` output lists them. The table shows a person's own grant, not an app's. Run `runtime.providers.tools('device')` for the list your app can use.
@@ -18,7 +18,7 @@ Scope strings come from **What it asks for → Add permissions** (provider `inte
18
18
 
19
19
  ## Find the tool you need
20
20
 
21
- The provider has thousands of tools: on 2026-10-16 the runtime we captured from listed 3,061 tools across 3,060 groups, one `_read` group and one `_write` group per service, plus `discover` and `link`. This page does not table them. List them from your app:
21
+ The provider has thousands of tools: on 2026-10-16 one runtime listed 3,061 tools across 3,060 groups, one `_read` group and one `_write` group per service, plus `discover` and `link`. This page does not table them. List them from your app:
22
22
 
23
23
  ```ts
24
24
  const integrations = await runtime.providers.tools('integrations');
@@ -15,7 +15,7 @@ Each scope is `search:<group>`: `search:search`, `search:answer`, `search:conten
15
15
 
16
16
  ## Tools
17
17
 
18
- Captured 2026-10-16 from `GET /v1/providers/search/tools` on a joined runtime (provider major version 1). `*` marks a required parameter.
18
+ Tools as listed on 2026-10-16 (provider major version 1). `*` marks a required parameter.
19
19
 
20
20
  | Tool | Group (scope) | Parameters | What it does |
21
21
  |---|---|---|---|
@@ -16,7 +16,7 @@ The `sms` provider sends a text from Northlight's number to the verified phone o
16
16
  | Scope | Consent sentence | Gates |
17
17
  |---|---|---|
18
18
  | `sms:send` | Send you text messages from Northlight's number | `send`, `react` |
19
- | `sms:status` | Not captured | `status` |
19
+ | `sms:status` | Not listed | `status` |
20
20
 
21
21
  Add them under **What it asks for → Add permissions** (provider `sms`). Without `sms:send` the consent page does not offer it and `providers.call` for `sms` is refused with `scope_missing`.
22
22
 
@@ -26,11 +26,11 @@ Add them under **What it asks for → Add permissions** (provider `sms`). Withou
26
26
  await runtime.providers.call({provider: 'sms', tool: 'send', arguments: {body: 'Your summary is ready.'}});
27
27
  ```
28
28
 
29
- `body` is required. The text goes from Northlight's number to the person's verified phone, and each person can receive at most 50 texts from your app per UTC day. These limits are the provider's documented behavior (the 50-per-day limit is not yet checked on production).
29
+ `body` is required. The text goes from Northlight's number to the person's verified phone, and each person can receive at most 50 texts from your app per UTC day.
30
30
 
31
31
  ## Tools
32
32
 
33
- Captured 2026-10-16 from `GET /v1/providers/sms/tools` on a joined runtime (provider major version 1). `*` marks a required parameter.
33
+ Tools as listed on 2026-10-16 (provider major version 1). `*` marks a required parameter.
34
34
 
35
35
  | Tool | Group (scope) | Parameters | What it does |
36
36
  |---|---|---|---|
@@ -11,19 +11,19 @@ when-and-why-to-read: When you need Quick setup, this knowledge should be read
11
11
  npx @north-light/sdk@latest init my-app
12
12
  ```
13
13
 
14
- This command creates a small Node server, a signing key and an env file. About ten minutes later you have an app on your laptop that signs you in with Northlight, starts an agent run on your own Northlight runtime, and texts your phone. The app runs on your machine and talks to Northlight's production directory at `https://account.northlight.ai`. There is no local Northlight stack to run, and you do not need crouter.
14
+ This command creates a small Node server, a signing key and an env file. About ten minutes later you have an app on your laptop that signs you in with Northlight, starts an agent run on your own Northlight runtime, and texts your phone. The app runs on your machine and talks to Northlight's production directory at `https://account.northlight.ai`. There is no local Northlight stack to run. To run crouter on your own machine as well, see [[northlight-apps/get-started]].
15
15
 
16
16
  You need Node.js 20.6 or later (the start command uses `--env-file`) and a phone that can receive iMessage. The server was run on Node 20.6, 20.20, 22.14, 22.22 and 26.12.
17
17
 
18
18
  Using a coding agent? Tell it: *Read https://sdk.docs.northlight.ai/SKILL.md and follow it.* It runs every command below; you sign up, then choose **Allow** twice in your browser. See [[northlight-apps/coding-agents]].
19
19
 
20
- Each step below ends with what you should see when it worked. A step marked "(not yet checked on production)" is written from the source code and has not been run end to end against `account.northlight.ai`.
20
+ Each step below ends with what you should see when it worked.
21
21
 
22
22
  ## 1. Create an account
23
23
 
24
24
  Open `https://account.northlight.ai/signup` and create your account. Signup texts a confirmation code to your phone, and that text is sent over iMessage. A number that cannot receive iMessage gets "We couldn't send the text", and retrying does not help. One phone number belongs to one account.
25
25
 
26
- You should see: your account's page after you enter the code. Opening `https://account.northlight.ai/console` while signed in shows the console, where your apps are listed. Checked on production: `/signup` redirects to the phone step at `/signup/phone`, which asks for a name and a phone number and offers **Text me a confirmation**; `/console` while signed out redirects to sign-in; and the signed-in console lists your apps and has **Register an app**. Completing signup, the confirmation code and the "We couldn't send the text" refusal are not yet checked on production (the walk used an existing account).
26
+ You should see: your account's page after you enter the code. Opening `https://account.northlight.ai/console` while signed in shows the console, where your apps are listed.
27
27
 
28
28
  ## 2. Scaffold the app
29
29
 
@@ -51,8 +51,6 @@ You should see, on the terminal: `Created a Northlight app in my-app:` with the
51
51
 
52
52
  Only the browser registration below uses that line: `register` reads the public half from `local/app-key.json` itself. If a file already exists, `init` refuses, names it and exits non-zero without writing anything.
53
53
 
54
- Checked on production: `npx @north-light/sdk@latest init my-app` (npm `latest` 0.3.476) in an empty directory with no crtr on `PATH` printed this output and wrote these files, the private key has mode `0600`, and `server.ts` is the one listed at the end of this page. Running it again names the skill file and writes nothing.
55
-
56
54
  ## 3. Log in
57
55
 
58
56
  ```bash
@@ -91,8 +89,6 @@ and "Done. Go back to your terminal." in the browser. The name, id and dates are
91
89
 
92
90
  The login is saved outside your project, in `~/.config/northlight/credentials.json` (mode `0600`). Never commit, paste or print it.
93
91
 
94
- Checked on production: this whole step, including the confirm page and its wording. The confirm page reads "Let a coding agent manage your Northlight apps?", shows the code, the computer's name and platform and the address it asked from ("The computer named itself; Northlight did not check it"), and lists what the login can and can't do. After **Allow** the page reads "Done / Go back to your terminal." and the terminal prints the output above.
95
-
96
92
  If you run `login` again, it does not start over. While a code is pending it prints "Still waiting for the login started at HH:MM." with the same link and code. Once you are logged in it prints "Already logged in as …" and exits 0. If the code expired unapproved it exits 1 and says so: run it again for a new code. See [[northlight-apps/cli]].
97
93
 
98
94
  If `login` cannot reach `account.northlight.ai`, or you would rather use the browser, skip to [Register in the browser instead](#register-in-the-browser-instead).
@@ -120,8 +116,6 @@ Next: npm i && npm start, then open http://localhost:3000/auth/login
120
116
 
121
117
  `local/app.env` now has all four settings. The name, client ID and key ID are examples. Change the defaults with `--name`, `--logo`, `--justification` and `--redirect-uri`; the default logo is a placeholder, `https://sdk.docs.northlight.ai/app-logo.png`. `register` refuses when `CROUTER_CLIENT_ID` is already set. A login can register at most 10 apps a day.
122
118
 
123
- Checked on production: this step, including that the directory accepts the default logo.
124
-
125
119
  ## 5. Run it
126
120
 
127
121
  ```bash
@@ -133,8 +127,6 @@ node --env-file=local/app.env --import tsx server.ts
133
127
 
134
128
  Open `http://localhost:3000/auth/login`. Your browser goes to `account.northlight.ai`. Sign in if asked, read the consent page, and choose Allow. You land back on `http://localhost:3000/` with "Signed in" and your Northlight user id. Press **Start a run and send me a text**. The page answers "Done", shows the run's status `idle`, the run's reply (`pong`) and the text's `message_id`, and your phone receives "Hello from my first Northlight app." from Northlight's number.
135
129
 
136
- Checked on production, as the account that owns the app: the server starts (with `npm start` too), `/` shows the sign-in link, and `/auth/login` answers `303` to `https://account.northlight.ai/authorize?client_id=…&scope=openid+profile+crtr%3Allm+crtr%3Aact+sms%3Asend…&code_challenge_method=S256…`. The consent page listed the four permissions and the monthly cap, **Allow** returned to `http://localhost:3000/` with "Signed in" and the user id, and the button page answered "Done" with status `idle` and a `message_id` for the text. In the console the key then read "Last used just now". Not yet checked on production: that the text reached the phone (the `message_id` is the provider's answer, not a delivery receipt), and the `426` case. The `pong` reply is read through `runs.reply` and has not been run on production since this example changed. Signing in as a second person needs a second account and is not covered here.
137
-
138
130
  If `/` shows "One step left", `CROUTER_CLIENT_ID` is empty: run `npx @north-light/sdk register` (or, for an app you registered in the browser, `env --client-id`) and restart. If a call fails with `426 runtime_version_unsupported`, your SDK is newer than the Northlight runtimes. Install the previous version with `npm i --save-exact @north-light/sdk@<version>` and tell support@northlight.ai.
139
131
 
140
132
  ## 6. What next
@@ -165,16 +157,12 @@ Choose **Register app**.
165
157
 
166
158
  You should see: a page titled "*your app's name* is registered" with a **Client ID** and, under it, the key ID of the key you pasted. Copy the client ID, then choose **Continue to *your app's name***. If it says "Next: add your app's public key on the Sign-in tab", the key was left out: open the app's **Sign-in** tab and choose **Add key**. The app starts asking for `crtr:llm` and `crtr:act`.
167
159
 
168
- Checked on production: these field labels, registering with a pasted key, and the app page opening in testing with that key active and `crtr:llm` and `crtr:act` listed. The "Next: add your app's public key" message, which shows when the key is left out, is not yet checked on production.
169
-
170
160
  ### Add the permission to text
171
161
 
172
162
  On the app's page, open the **What it asks for** tab and choose **Add permissions**. Choose **Texting**, tick `sms:send` ("Send you text messages from Northlight's number"), and choose **Done**. Then choose **Save** under the list: **Done** only closes the dialog, and the change is not stored until you save.
173
163
 
174
164
  You should see: `sms:send` under what your app asks for after **Save** says "Saved", next to `crtr:llm` and `crtr:act`. The server in this guide asks for all three, so without `sms:send` the consent page does not offer it and the text in step 5 is refused. Take scope strings from this list. Do not invent them. See [[northlight-apps/concepts/scopes-and-grants]].
175
165
 
176
- Checked on production: after **Save** and a reload, the tab lists `crtr:llm` and `crtr:act` under Agents and `sms:send` under Texting, and the consent page in step 5 offered the text permission.
177
-
178
166
  ### Write the client ID into the env file
179
167
 
180
168
  ```bash
@@ -193,8 +181,6 @@ Key file: local/app-key.json (set CROUTER_KEY_FILE to change it).
193
181
 
194
182
  `local/app.env` now has all four settings. The command makes no network call and keeps every other line in the file. Add `--origin <url>` if your app does not run on `http://localhost:3000`.
195
183
 
196
- Checked on production: this output, and that the command works in a directory with no `local/` yet. `--origin` is not yet checked on production.
197
-
198
184
  ## The server `init` writes
199
185
 
200
186
  This is `examples/apps/quickstart-server.ts`. The SDK reads no environment: the server passes the values in.