Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fea0ff8
feat(core): add remote host identity metadata
ian-pascoe Jun 22, 2026
369395b
feat(core): add pending remote login store
ian-pascoe Jun 22, 2026
bbc9c01
feat(core): expose pending remote login routes
ian-pascoe Jun 22, 2026
8f9a88a
feat(core): add pending login operator commands
ian-pascoe Jun 22, 2026
10406ec
feat(core): add pending remote login client flow
ian-pascoe Jun 22, 2026
8e8a2a6
feat(core): refine pending remote login client states
ian-pascoe Jun 22, 2026
afe1cf7
feat(core): emit pending login terminal events
ian-pascoe Jun 22, 2026
30b3b75
feat(core): cancel pending remote login on abort
ian-pascoe Jun 22, 2026
5f008cc
feat(core): distinguish revoked remote credentials
ian-pascoe Jun 22, 2026
52c8bd8
feat(core): align cloud remote profile lifecycle
ian-pascoe Jun 22, 2026
6f17f80
docs: update remote attach pending login flow
ian-pascoe Jun 22, 2026
fe4e57a
chore: add pending remote login changeset
ian-pascoe Jun 22, 2026
1d3f07d
fix(core): bound pending remote login state
ian-pascoe Jun 22, 2026
1af9921
fix(core): close legacy remote login bootstrap
ian-pascoe Jun 22, 2026
d49e1b9
fix(core): replay pending login responses
ian-pascoe Jun 22, 2026
d0a0766
docs: add pending remote login plan context
ian-pascoe Jun 22, 2026
155d4f3
fix(core): address remote login review feedback
ian-pascoe Jun 22, 2026
7d93be4
fix(core): anchor pending login source hints
ian-pascoe Jun 22, 2026
3d33596
fix(core): harden pending remote login review paths
ian-pascoe Jun 23, 2026
4523244
fix(core): address pending login review follow-ups
ian-pascoe Jun 23, 2026
b44c304
feat(core): accept positional attach URL
ian-pascoe Jun 23, 2026
a0cba21
docs: capture pending remote login pattern
ian-pascoe Jun 23, 2026
cfa0035
docs: mark remote attach plan superseded
ian-pascoe Jun 23, 2026
7c577dd
fix(core): harden pending remote login lifecycle
ian-pascoe Jun 23, 2026
5cc789f
fix(daemon): resolve emulated Windows paths on host
ian-pascoe Jun 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/attach-positional-url.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@caplets/core": patch
"caplets": patch
---

Make `caplets attach <url>` the primary remote attach command while keeping `--remote-url <url>` as a hidden compatibility alias.
6 changes: 6 additions & 0 deletions .changeset/remote-pairing-ergonomics.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@caplets/core": patch
"caplets": patch
---

Label hidden CLI prompts without echoing entered secrets, and document the pending self-hosted Remote Login requirements and implementation plan.
6 changes: 6 additions & 0 deletions .changeset/self-hosted-pending-remote-login.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@caplets/core": patch
"caplets": patch
---

Replace self-hosted Remote Login's operator-minted Pairing Code bootstrap with a client-started pending login flow. The client now starts `caplets remote login <url>`, displays a short operator code, waits for server-local approval, rotates pre-login material while pending, and stores final Remote Profile credentials only after approval. Remote attach recovery now reports revoked self-hosted credentials and Cloud workspace ambiguity with stable recovery guidance, and public docs/examples show the pending-login approval sequence without remote secrets in agent configuration.
12 changes: 9 additions & 3 deletions CONCEPTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,13 +84,19 @@ Remote Attach uses Remote Profiles for trust and credentials. Long-lived attach

The provider-neutral flow that trusts a local Caplets client to a Caplets host, whether the host is self-hosted or Caplets Cloud.

Remote Login stores host credentials in Caplets-owned credential storage so agent configs can launch `caplets attach --remote-url ...` without carrying remote secrets.
Remote Login stores host credentials in Caplets-owned credential storage so agent configs can launch Remote Attach using stable host selectors without carrying remote secrets.

### Pending Remote Login

The self-hosted Remote Login state between client initiation and server-local operator approval or rejection.

A Pending Remote Login separates the operator-visible Pairing Code from client-held pending material. Approval alone does not create reusable attach credentials; the initiating client must still complete the flow with its possession proof before a Remote Profile can be stored.

### Pairing Code

A short-lived, one-time code minted by a self-hosted Caplets host and exchanged by a client during Remote Login.
A short-lived, operator-visible approval code for a pending self-hosted Remote Login flow.

Pairing Codes are bootstrap material only. They are not reusable client credentials.
Pairing Codes prove that a server-local operator approved a specific pending login. They are not reusable client credentials, attach bearer credentials, or the flow's longer-lived pre-login refresh material.

### Remote Profile

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,15 @@ For a remote or Cloud-backed MCP server, point the client at `caplets attach` in
```toml
[mcp_servers.caplets]
command = "caplets"
args = ["attach"]
args = ["attach", "https://caplets.example.com/caplets"]
```

```json
{
"mcpServers": {
"caplets": {
"command": "caplets",
"args": ["attach"]
"args": ["attach", "https://caplets.example.com/caplets"]
}
}
}
Expand All @@ -150,7 +150,7 @@ host once, then launch attach or a native integration with only non-secret selec

```sh
caplets remote login https://caplets.example.com/caplets
caplets attach --remote-url https://caplets.example.com/caplets
caplets attach https://caplets.example.com/caplets

caplets remote login https://cloud.caplets.dev
CAPLETS_MODE=cloud CAPLETS_REMOTE_URL=https://cloud.caplets.dev opencode
Expand Down
31 changes: 19 additions & 12 deletions apps/docs/src/content/docs/remote-attach.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Codex:
```toml
[mcp_servers.caplets]
command = "caplets"
args = ["attach", "--remote-url", "https://caplets.example.com/caplets"]
args = ["attach", "https://caplets.example.com/caplets"]
```

Generic MCP JSON:
Expand All @@ -34,32 +34,39 @@ Generic MCP JSON:
"mcpServers": {
"caplets": {
"command": "caplets",
"args": ["attach", "--remote-url", "https://caplets.example.com/caplets"]
"args": ["attach", "https://caplets.example.com/caplets"]
}
}
}
```

## Remote Login

For a self-hosted remote, first create a short-lived Pairing Code on the server:
For a self-hosted remote, start Remote Login from the client:

```sh
caplets remote host pair --host-url https://caplets.example.com/caplets
caplets remote login https://caplets.example.com/caplets
```

If the server uses a non-default credential state directory, pass the same directory with
`--state-path` that the server uses for `caplets serve --remote-state-path`.

Then log in once on the client and configure the agent to launch attach:
The command prints a short operator code and waits. On the host, a server-local
operator reviews the pending login metadata and approves the code from the same
server environment that owns the remote credential state:

```sh
caplets remote login https://caplets.example.com/caplets
caplets attach --remote-url https://caplets.example.com/caplets
caplets remote host logins
caplets remote host approve <code> --yes
```

Enter the Pairing Code at the hidden prompt from `caplets remote login`. Use
`--code-stdin` for automation instead of putting Pairing Codes in shell history.
If the server uses a non-default credential state directory, pass the same directory
with `--state-path` that the server uses for `caplets serve --remote-state-path`.
The visible approval code is not an attach credential, but do not put Caplets access
or refresh credentials in shell history, agent configs, or environment variables.

After approval, configure the agent to launch attach:

```sh
caplets attach https://caplets.example.com/caplets
```

For Caplets Cloud native integrations, log in once and then set the Cloud URL selector:

Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/content/docs/troubleshooting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ Confirm the remote environment:
```sh
caplets remote login https://caplets.example.com/caplets
caplets doctor
caplets attach --remote-url https://caplets.example.com/caplets
caplets attach https://caplets.example.com/caplets
```

If the URL belongs to Caplets Cloud, log in through Remote Login and keep the Cloud URL
Expand Down
6 changes: 3 additions & 3 deletions apps/landing/src/data/landing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ export const whyCapletsProblems = [

export const remoteCommands = {
server: `caplets daemon install --start
caplets remote host pair --host-url <url>`,
client: `caplets remote login <url> --code <pairing-code>
caplets attach --remote-url <url>`,
caplets remote host approve <code> --yes`,
client: `caplets remote login <url>
caplets attach <url>`,
} as const;

export const remoteEndpoints = [
Expand Down
Loading