opensandbox-cli 0.1.0__py3-none-any.whl
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.
- opensandbox_cli/__init__.py +20 -0
- opensandbox_cli/__main__.py +20 -0
- opensandbox_cli/client.py +127 -0
- opensandbox_cli/commands/__init__.py +13 -0
- opensandbox_cli/commands/command.py +359 -0
- opensandbox_cli/commands/config_cmd.py +183 -0
- opensandbox_cli/commands/devops.py +123 -0
- opensandbox_cli/commands/egress.py +98 -0
- opensandbox_cli/commands/file.py +442 -0
- opensandbox_cli/commands/sandbox.py +580 -0
- opensandbox_cli/commands/skills.py +775 -0
- opensandbox_cli/config.py +160 -0
- opensandbox_cli/main.py +138 -0
- opensandbox_cli/output.py +363 -0
- opensandbox_cli/py.typed +1 -0
- opensandbox_cli/skill_registry.py +184 -0
- opensandbox_cli/skills/opensandbox-command-execution.md +215 -0
- opensandbox_cli/skills/opensandbox-file-operations.md +244 -0
- opensandbox_cli/skills/opensandbox-network-egress.md +179 -0
- opensandbox_cli/skills/opensandbox-sandbox-lifecycle.md +305 -0
- opensandbox_cli/skills/opensandbox-sandbox-troubleshooting.md +177 -0
- opensandbox_cli/utils.py +212 -0
- opensandbox_cli-0.1.0.dist-info/METADATA +597 -0
- opensandbox_cli-0.1.0.dist-info/RECORD +27 -0
- opensandbox_cli-0.1.0.dist-info/WHEEL +4 -0
- opensandbox_cli-0.1.0.dist-info/entry_points.txt +3 -0
- opensandbox_cli-0.1.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"""Built-in OpenSandbox skill metadata and rendering helpers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import importlib.resources
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True)
|
|
11
|
+
class SkillSpec:
|
|
12
|
+
"""A bundled skill shipped with the CLI."""
|
|
13
|
+
|
|
14
|
+
slug: str
|
|
15
|
+
package_file: str
|
|
16
|
+
title: str
|
|
17
|
+
summary: str
|
|
18
|
+
trigger_hint: str
|
|
19
|
+
marker_id: str
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
BUILTIN_SKILLS: dict[str, SkillSpec] = {
|
|
23
|
+
"sandbox-troubleshooting": SkillSpec(
|
|
24
|
+
slug="sandbox-troubleshooting",
|
|
25
|
+
package_file="opensandbox-sandbox-troubleshooting.md",
|
|
26
|
+
title="OpenSandbox Sandbox Troubleshooting",
|
|
27
|
+
summary=(
|
|
28
|
+
"Triage failed or unhealthy sandboxes with state, health, summary, "
|
|
29
|
+
"inspect, events, logs, and concrete remediation steps."
|
|
30
|
+
),
|
|
31
|
+
trigger_hint=(
|
|
32
|
+
"Use when the user reports sandbox startup failures, crashes, OOM, "
|
|
33
|
+
"image pull problems, pending sandboxes, or unreachable services."
|
|
34
|
+
),
|
|
35
|
+
marker_id="opensandbox-sandbox-troubleshooting",
|
|
36
|
+
),
|
|
37
|
+
"sandbox-lifecycle": SkillSpec(
|
|
38
|
+
slug="sandbox-lifecycle",
|
|
39
|
+
package_file="opensandbox-sandbox-lifecycle.md",
|
|
40
|
+
title="OpenSandbox Sandbox Lifecycle",
|
|
41
|
+
summary=(
|
|
42
|
+
"Create, inspect, renew, pause, resume, and terminate sandboxes "
|
|
43
|
+
"with the right defaults and follow-up checks."
|
|
44
|
+
),
|
|
45
|
+
trigger_hint=(
|
|
46
|
+
"Use when the user wants to create or manage a sandbox and needs "
|
|
47
|
+
"the exact OpenSandbox CLI/API flow."
|
|
48
|
+
),
|
|
49
|
+
marker_id="opensandbox-sandbox-lifecycle",
|
|
50
|
+
),
|
|
51
|
+
"command-execution": SkillSpec(
|
|
52
|
+
slug="command-execution",
|
|
53
|
+
package_file="opensandbox-command-execution.md",
|
|
54
|
+
title="OpenSandbox Command Execution",
|
|
55
|
+
summary=(
|
|
56
|
+
"Run foreground and background commands, inspect status/logs, and "
|
|
57
|
+
"use persistent sessions inside a sandbox."
|
|
58
|
+
),
|
|
59
|
+
trigger_hint=(
|
|
60
|
+
"Use when the user wants to execute commands in a sandbox, collect "
|
|
61
|
+
"logs, interrupt work, or reuse a persistent shell session."
|
|
62
|
+
),
|
|
63
|
+
marker_id="opensandbox-command-execution",
|
|
64
|
+
),
|
|
65
|
+
"file-operations": SkillSpec(
|
|
66
|
+
slug="file-operations",
|
|
67
|
+
package_file="opensandbox-file-operations.md",
|
|
68
|
+
title="OpenSandbox File Operations",
|
|
69
|
+
summary=(
|
|
70
|
+
"Read, write, upload, download, search, replace, and manage files "
|
|
71
|
+
"inside a sandbox without hand-wavy shell advice."
|
|
72
|
+
),
|
|
73
|
+
trigger_hint=(
|
|
74
|
+
"Use when the user needs file or directory manipulation inside an "
|
|
75
|
+
"OpenSandbox sandbox."
|
|
76
|
+
),
|
|
77
|
+
marker_id="opensandbox-file-operations",
|
|
78
|
+
),
|
|
79
|
+
"network-egress": SkillSpec(
|
|
80
|
+
slug="network-egress",
|
|
81
|
+
package_file="opensandbox-network-egress.md",
|
|
82
|
+
title="OpenSandbox Network Egress",
|
|
83
|
+
summary=(
|
|
84
|
+
"Inspect and patch sandbox runtime egress rules when the user "
|
|
85
|
+
"needs to allow or deny outbound domains."
|
|
86
|
+
),
|
|
87
|
+
trigger_hint=(
|
|
88
|
+
"Use when the user needs to view or modify outbound network access "
|
|
89
|
+
"for a sandbox, or debug domain allow and deny behavior."
|
|
90
|
+
),
|
|
91
|
+
marker_id="opensandbox-network-egress",
|
|
92
|
+
),
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
DEFAULT_SKILL = "sandbox-troubleshooting"
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def list_builtin_skills() -> list[SkillSpec]:
|
|
99
|
+
"""Return bundled skills in stable declaration order."""
|
|
100
|
+
return list(BUILTIN_SKILLS.values())
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def get_builtin_skill(slug: str) -> SkillSpec:
|
|
104
|
+
"""Return a bundled skill definition."""
|
|
105
|
+
return BUILTIN_SKILLS[slug]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_builtin_skill_source(skill: SkillSpec) -> Path:
|
|
109
|
+
"""Locate the bundled skill file shipped with the CLI package."""
|
|
110
|
+
pkg = importlib.resources.files("opensandbox_cli") / "skills" / skill.package_file
|
|
111
|
+
if hasattr(pkg, "__fspath__"):
|
|
112
|
+
return Path(str(pkg))
|
|
113
|
+
with importlib.resources.as_file(pkg) as resolved:
|
|
114
|
+
return Path(resolved)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def read_skill_markdown(skill: SkillSpec) -> str:
|
|
118
|
+
"""Load bundled skill markdown."""
|
|
119
|
+
return get_builtin_skill_source(skill).read_text(encoding="utf-8")
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def split_frontmatter(markdown: str) -> tuple[str | None, str]:
|
|
123
|
+
"""Split markdown into YAML frontmatter and body."""
|
|
124
|
+
if not markdown.startswith("---\n"):
|
|
125
|
+
return None, markdown
|
|
126
|
+
|
|
127
|
+
closing = markdown.find("\n---\n", 4)
|
|
128
|
+
if closing == -1:
|
|
129
|
+
return None, markdown
|
|
130
|
+
|
|
131
|
+
frontmatter = markdown[4:closing]
|
|
132
|
+
body = markdown[closing + 5 :]
|
|
133
|
+
return frontmatter, body
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def extract_section(body: str, heading: str) -> str | None:
|
|
137
|
+
"""Extract a markdown section by exact heading text."""
|
|
138
|
+
lines = body.splitlines()
|
|
139
|
+
capture = False
|
|
140
|
+
capture_level = 0
|
|
141
|
+
captured: list[str] = []
|
|
142
|
+
|
|
143
|
+
for line in lines:
|
|
144
|
+
if line.startswith("## ") or line.startswith("### "):
|
|
145
|
+
if capture:
|
|
146
|
+
if capture_level == 2 and line.startswith("## "):
|
|
147
|
+
break
|
|
148
|
+
if capture_level == 3 and (line.startswith("## ") or line.startswith("### ")):
|
|
149
|
+
break
|
|
150
|
+
if line == f"## {heading}":
|
|
151
|
+
capture = True
|
|
152
|
+
capture_level = 2
|
|
153
|
+
continue
|
|
154
|
+
if line == f"### {heading}":
|
|
155
|
+
capture = True
|
|
156
|
+
capture_level = 3
|
|
157
|
+
continue
|
|
158
|
+
if capture:
|
|
159
|
+
captured.append(line)
|
|
160
|
+
|
|
161
|
+
if not captured:
|
|
162
|
+
return None
|
|
163
|
+
|
|
164
|
+
return "\n".join(captured).strip() or None
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def render_skill_for_target(
|
|
168
|
+
skill: SkillSpec,
|
|
169
|
+
markdown: str,
|
|
170
|
+
*,
|
|
171
|
+
preserve_frontmatter: bool,
|
|
172
|
+
) -> str:
|
|
173
|
+
"""Render skill content for the target tool."""
|
|
174
|
+
frontmatter, body = split_frontmatter(markdown)
|
|
175
|
+
body = body.strip()
|
|
176
|
+
|
|
177
|
+
if preserve_frontmatter or not frontmatter:
|
|
178
|
+
return markdown.strip() + "\n"
|
|
179
|
+
|
|
180
|
+
return (
|
|
181
|
+
f"# {skill.title}\n\n"
|
|
182
|
+
f"{skill.summary}\n\n"
|
|
183
|
+
f"{body}\n"
|
|
184
|
+
)
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: command-execution
|
|
3
|
+
description: Use OpenSandbox command execution commands to run foreground or background processes, inspect tracked execution status and logs, interrupt work, and manage persistent shell sessions inside a sandbox. Trigger when users want to execute commands in a sandbox and need exact OpenSandbox CLI flows.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# OpenSandbox Command Execution
|
|
7
|
+
|
|
8
|
+
Run commands with `osb command`. Use foreground streaming by default, and add `--background` when you need tracked execution.
|
|
9
|
+
|
|
10
|
+
## When To Use
|
|
11
|
+
|
|
12
|
+
- the user wants to run a one-off command in a sandbox
|
|
13
|
+
- the user needs a tracked background command with later status/log inspection
|
|
14
|
+
- the user wants to stop a running command
|
|
15
|
+
- the user wants a persistent shell session that keeps working directory or environment state across runs
|
|
16
|
+
|
|
17
|
+
## Config Gate
|
|
18
|
+
|
|
19
|
+
Run this first:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
osb config show -o json
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If `domain` is missing, stop and set it before command execution:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
osb config set connection.domain <host:port> -o json
|
|
29
|
+
osb config show -o json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
If auth is required and `api_key` is missing, stop and set it before command execution:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
osb config set connection.api_key <api-key> -o json
|
|
36
|
+
osb config show -o json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Separator Rule
|
|
40
|
+
|
|
41
|
+
Use `--` before the sandbox command payload. This is required when the payload contains flags like `-l`, `-c`, or `-m`.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
osb command run <sandbox-id> -o raw -- sh -lc 'echo ready'
|
|
45
|
+
osb command run <sandbox-id> -o raw -- python -m http.server
|
|
46
|
+
osb command session run <sandbox-id> <session-id> -o raw -- sh -lc 'pwd'
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Execution Modes
|
|
50
|
+
|
|
51
|
+
Treat these as three distinct execution paths:
|
|
52
|
+
|
|
53
|
+
- `osb command run` without `--background`
|
|
54
|
+
Use for foreground one-shot commands when the result should stream directly to the terminal
|
|
55
|
+
- `osb command run --background`
|
|
56
|
+
Use when the user needs an execution ID, later status checks, or log retrieval
|
|
57
|
+
- `osb command session ...`
|
|
58
|
+
Use when shell state must persist across commands, such as exported variables or a working directory
|
|
59
|
+
|
|
60
|
+
## Golden Paths
|
|
61
|
+
|
|
62
|
+
Foreground one-shot command:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
osb command run <sandbox-id> -o raw -- python -c "print(1 + 1)"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Tracked background command:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
osb command run <sandbox-id> --background -o json -- sh -c "sleep 10; echo done"
|
|
72
|
+
osb command status <sandbox-id> <execution-id> -o json
|
|
73
|
+
osb command logs <sandbox-id> <execution-id> -o json
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Persistent session:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
osb command session create <sandbox-id> --workdir /workspace -o json
|
|
80
|
+
osb command session run <sandbox-id> <session-id> -o raw -- pwd
|
|
81
|
+
osb command session run <sandbox-id> <session-id> -o raw -- export FOO=bar
|
|
82
|
+
osb command session run <sandbox-id> <session-id> -o raw -- sh -c 'echo $FOO'
|
|
83
|
+
osb command session delete <sandbox-id> <session-id> -o json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Foreground Commands
|
|
87
|
+
|
|
88
|
+
For simple one-off execution, use:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
osb command run <sandbox-id> -o raw -- <command>
|
|
92
|
+
osb command run <sandbox-id> --workdir /workspace -o raw -- <command>
|
|
93
|
+
osb command run <sandbox-id> --timeout 30s -o raw -- <command>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Use foreground mode when the user wants immediate output and does not need a tracked execution ID.
|
|
97
|
+
|
|
98
|
+
## Background Commands
|
|
99
|
+
|
|
100
|
+
Use background mode when the user will need follow-up inspection:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
osb command run <sandbox-id> --background -o json -- <command>
|
|
104
|
+
osb command run <sandbox-id> --background --workdir /workspace -o json -- <command>
|
|
105
|
+
osb command run <sandbox-id> --background --timeout 5m -o json -- <command>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Then inspect the tracked execution:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
osb command status <sandbox-id> <execution-id> -o json
|
|
112
|
+
osb command logs <sandbox-id> <execution-id> -o json
|
|
113
|
+
osb command logs <sandbox-id> <execution-id> --cursor 0 -o json
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Use `status` for lifecycle state and exit information. Use `logs` for tracked background output. Do not suggest `command logs` for foreground commands that already streamed to the terminal.
|
|
117
|
+
|
|
118
|
+
## Persistent Sessions
|
|
119
|
+
|
|
120
|
+
Use sessions when commands must share shell state:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
osb command session create <sandbox-id> --workdir /workspace -o json
|
|
124
|
+
osb command session run <sandbox-id> <session-id> -o raw -- pwd
|
|
125
|
+
osb command session run <sandbox-id> <session-id> -o raw -- export FOO=bar
|
|
126
|
+
osb command session run <sandbox-id> <session-id> -o raw -- sh -c 'echo $FOO'
|
|
127
|
+
osb command session run <sandbox-id> <session-id> --workdir /var -o raw -- pwd
|
|
128
|
+
osb command session delete <sandbox-id> <session-id> -o json
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Rules:
|
|
132
|
+
|
|
133
|
+
- `session create --workdir` sets the initial working directory for the session
|
|
134
|
+
- `session run --workdir` overrides the working directory for that single run only
|
|
135
|
+
- exported variables and shell state persist across `session run` calls in the same session
|
|
136
|
+
- delete the session when the user is done; do not leave idle sessions around
|
|
137
|
+
|
|
138
|
+
## Interrupting Work
|
|
139
|
+
|
|
140
|
+
Interrupt only tracked executions:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
osb command interrupt <sandbox-id> <execution-id> -o json
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Only suggest interruption when the user explicitly wants to stop work or the process is clearly stuck.
|
|
147
|
+
|
|
148
|
+
## Failure Semantics
|
|
149
|
+
|
|
150
|
+
- foreground `osb command run` streams output directly and requires `-o raw`
|
|
151
|
+
- background `osb command run --background` returns tracked execution metadata and supports structured output
|
|
152
|
+
- `session run` also exits non-zero on execution error
|
|
153
|
+
- tracked background commands should be checked with `status` and `logs`
|
|
154
|
+
- if the command failure is caused by an unhealthy sandbox rather than the command itself, switch to `sandbox-troubleshooting`
|
|
155
|
+
|
|
156
|
+
## Response Pattern
|
|
157
|
+
|
|
158
|
+
Structure the answer as:
|
|
159
|
+
|
|
160
|
+
1. exact command to run
|
|
161
|
+
2. which execution mode it uses
|
|
162
|
+
3. the next inspection or cleanup command if the workflow continues
|
|
163
|
+
|
|
164
|
+
Keep command examples concrete and ready to paste.
|
|
165
|
+
|
|
166
|
+
## Minimal Closed Loops
|
|
167
|
+
|
|
168
|
+
Foreground command with timeout:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
osb command run <sandbox-id> --timeout 30s -o raw -- python -c "print(1 + 1)"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Tracked background execution:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
osb command run <sandbox-id> --background -o json -- sh -c "sleep 10; echo done"
|
|
178
|
+
osb command status <sandbox-id> <execution-id> -o json
|
|
179
|
+
osb command logs <sandbox-id> <execution-id> -o json
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Background execution with interrupt:
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
osb command run <sandbox-id> --background -o json -- sh -c "sleep 300"
|
|
186
|
+
osb command interrupt <sandbox-id> <execution-id> -o json
|
|
187
|
+
osb command status <sandbox-id> <execution-id> -o json
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Persistent session with shared shell state:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
osb command session create <sandbox-id> --workdir /workspace -o json
|
|
194
|
+
osb command session run <sandbox-id> <session-id> -o raw -- export FOO=bar
|
|
195
|
+
osb command session run <sandbox-id> <session-id> -o raw -- sh -c 'echo $FOO'
|
|
196
|
+
osb command session delete <sandbox-id> <session-id> -o json
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Per-run working directory override inside a session:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
osb command session create <sandbox-id> --workdir /tmp -o json
|
|
203
|
+
osb command session run <sandbox-id> <session-id> -o raw -- pwd
|
|
204
|
+
osb command session run <sandbox-id> <session-id> --workdir /var -o raw -- pwd
|
|
205
|
+
osb command session delete <sandbox-id> <session-id> -o json
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Best Practices
|
|
209
|
+
|
|
210
|
+
- use `osb command run -o raw -- ...` for quick foreground commands
|
|
211
|
+
- use `--background` when the user will need execution tracking
|
|
212
|
+
- use sessions only when state persistence is actually needed
|
|
213
|
+
- use `--workdir` explicitly when directory context matters
|
|
214
|
+
- use `--timeout` when the command should not run indefinitely
|
|
215
|
+
- prefer `status` before guessing whether a background command is still running or already failed
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: file-operations
|
|
3
|
+
description: Use OpenSandbox file commands to read, write, upload, download, search, replace, move, delete, and inspect files or directories inside a sandbox. Trigger when users want exact sandbox file manipulation commands instead of generic shell guidance.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# OpenSandbox File Operations
|
|
7
|
+
|
|
8
|
+
Manipulate sandbox files with `osb file` commands. Choose the operation mode first, then use the matching verification step. Do not mix sandbox-internal edits with host-to-sandbox transfer commands casually.
|
|
9
|
+
|
|
10
|
+
## When To Use
|
|
11
|
+
|
|
12
|
+
- the user wants to read or write a file inside a sandbox
|
|
13
|
+
- the user needs to upload a local file into a sandbox or download a sandbox file back to the host
|
|
14
|
+
- the user wants to search, replace, move, chmod, or inspect paths
|
|
15
|
+
- the user needs directory creation or cleanup
|
|
16
|
+
|
|
17
|
+
## Config Gate
|
|
18
|
+
|
|
19
|
+
Run this first:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
osb config show -o json
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If `domain` is missing, stop and set it before file commands:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
osb config set connection.domain <host:port> -o json
|
|
29
|
+
osb config show -o json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
If auth is required and `api_key` is missing, stop and set it before file commands:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
osb config set connection.api_key <api-key> -o json
|
|
36
|
+
osb config show -o json
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Operation Modes
|
|
40
|
+
|
|
41
|
+
Treat these as distinct categories:
|
|
42
|
+
|
|
43
|
+
- sandbox-only content operations
|
|
44
|
+
`cat`, `write`, `replace`, `mv`, `mkdir`, `rm`, `rmdir`, `info`, `chmod`
|
|
45
|
+
- host-to-sandbox transfer
|
|
46
|
+
`upload`
|
|
47
|
+
- sandbox-to-host transfer
|
|
48
|
+
`download`
|
|
49
|
+
- discovery before modification
|
|
50
|
+
`search`, then `info`
|
|
51
|
+
|
|
52
|
+
If the path is uncertain, search first. If the file boundary crosses between host and sandbox, use `upload` or `download` instead of `write` or `cat`.
|
|
53
|
+
|
|
54
|
+
## Golden Paths
|
|
55
|
+
|
|
56
|
+
Write and verify inside the sandbox:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
osb file write <sandbox-id> /workspace/app.txt -c "hello" -o json
|
|
60
|
+
osb file cat <sandbox-id> /workspace/app.txt -o raw
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Upload from host and verify in the sandbox:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
osb file upload <sandbox-id> ./local.txt /workspace/local.txt -o json
|
|
67
|
+
osb file cat <sandbox-id> /workspace/local.txt -o raw
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Search before editing:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
osb file search <sandbox-id> /workspace --pattern "*.py" -o json
|
|
74
|
+
osb file info <sandbox-id> /workspace/main.py -o json
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Sandbox-Only File Edits
|
|
78
|
+
|
|
79
|
+
Read and write:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
osb file cat <sandbox-id> /path/to/file -o raw
|
|
83
|
+
osb file write <sandbox-id> /path/to/file -c "hello" -o json
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Use `write` with `-c/--content` when the new content is known directly. If the content should come from stdin, omit `-c` and pipe or paste the content into the command.
|
|
87
|
+
|
|
88
|
+
Edit existing content:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
osb file replace <sandbox-id> /path/to/file --old old --new new -o json
|
|
92
|
+
osb file mv <sandbox-id> /old/path /new/path -o json
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Prefer `replace` for small text substitutions and `mv` for rename/path changes. Do not rewrite a full file when a targeted replace is enough.
|
|
96
|
+
|
|
97
|
+
Create directories:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
osb file mkdir <sandbox-id> /workspace/output -o json
|
|
101
|
+
osb file mkdir <sandbox-id> /workspace/a /workspace/b --mode 755 -o json
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Host <-> Sandbox Transfer
|
|
105
|
+
|
|
106
|
+
Host to sandbox:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
osb file upload <sandbox-id> ./local.txt /remote/path/local.txt -o json
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Sandbox to host:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
osb file download <sandbox-id> /remote/path/result.json ./result.json -o json
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Rules:
|
|
119
|
+
|
|
120
|
+
- use `upload` when the source file is on the host
|
|
121
|
+
- use `download` when the destination should be written to the host filesystem
|
|
122
|
+
- use `write` and `cat` only when the operation stays entirely inside the sandbox
|
|
123
|
+
|
|
124
|
+
## Metadata and Permissions
|
|
125
|
+
|
|
126
|
+
Inspect metadata:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
osb file info <sandbox-id> /path/to/file -o json
|
|
130
|
+
osb file info <sandbox-id> /path/one /path/two -o json
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Search by pattern:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
osb file search <sandbox-id> /workspace --pattern "*.py" -o json
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Set permissions:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
osb file chmod <sandbox-id> /path/to/script --mode 755 -o json
|
|
143
|
+
osb file chmod <sandbox-id> /path/to/file --mode 644 --owner root --group root -o json
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Use `info` after `chmod` when the user needs to confirm mode, ownership, or timestamps changed as expected.
|
|
147
|
+
|
|
148
|
+
## Destructive Operations
|
|
149
|
+
|
|
150
|
+
Delete files or directories only after verifying the target path:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
osb file info <sandbox-id> /workspace/tmp.txt -o json
|
|
154
|
+
osb file rm <sandbox-id> /workspace/tmp.txt -o json
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
osb file search <sandbox-id> /workspace --pattern "old-*" -o json
|
|
159
|
+
osb file rmdir <sandbox-id> /workspace/old-dir -o json
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Rules:
|
|
163
|
+
|
|
164
|
+
- prefer `info` when the exact path is known
|
|
165
|
+
- prefer `search` when the path is uncertain
|
|
166
|
+
- do not suggest `rm` or `rmdir` until the target has been verified
|
|
167
|
+
- after `mv`, `rm`, or `rmdir`, verify the new state with `info` or `search`
|
|
168
|
+
|
|
169
|
+
## Failure Semantics
|
|
170
|
+
|
|
171
|
+
- `upload` and `download` have host filesystem side effects; treat them as cross-boundary operations
|
|
172
|
+
- `download` writes to the local path immediately, so be explicit about the destination
|
|
173
|
+
- permission or ownership failures are usually path/runtime permission issues, not a reason to switch away from `osb file`
|
|
174
|
+
- if multiple file commands fail unexpectedly, check sandbox health before assuming a file-command bug
|
|
175
|
+
|
|
176
|
+
## Response Pattern
|
|
177
|
+
|
|
178
|
+
Structure the answer as:
|
|
179
|
+
|
|
180
|
+
1. exact `osb file` command
|
|
181
|
+
2. which operation mode it uses
|
|
182
|
+
3. the next verification command if the workflow continues
|
|
183
|
+
|
|
184
|
+
Keep command examples concrete and ready to paste.
|
|
185
|
+
|
|
186
|
+
## Minimal Closed Loops
|
|
187
|
+
|
|
188
|
+
Write and verify:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
osb file write <sandbox-id> /workspace/app.txt -c "hello" -o json
|
|
192
|
+
osb file cat <sandbox-id> /workspace/app.txt -o raw
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Upload and verify:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
osb file upload <sandbox-id> ./local.txt /workspace/local.txt -o json
|
|
199
|
+
osb file cat <sandbox-id> /workspace/local.txt -o raw
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Replace and verify:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
osb file replace <sandbox-id> /workspace/app.txt --old hello --new world -o json
|
|
206
|
+
osb file cat <sandbox-id> /workspace/app.txt -o raw
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Change permissions and inspect:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
osb file chmod <sandbox-id> /workspace/script.sh --mode 755 -o json
|
|
213
|
+
osb file info <sandbox-id> /workspace/script.sh -o json
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Create a directory and inspect it:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
osb file mkdir <sandbox-id> /workspace/output -o json
|
|
220
|
+
osb file info <sandbox-id> /workspace/output -o json
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Move a file and verify the new path:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
osb file mv <sandbox-id> /workspace/app.txt /workspace/archive/app.txt -o json
|
|
227
|
+
osb file info <sandbox-id> /workspace/archive/app.txt -o json
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Delete and verify removal:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
osb file info <sandbox-id> /workspace/tmp.txt -o json
|
|
234
|
+
osb file rm <sandbox-id> /workspace/tmp.txt -o json
|
|
235
|
+
osb file search <sandbox-id> /workspace --pattern "tmp.txt" -o json
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Best Practices
|
|
239
|
+
|
|
240
|
+
- prefer `search` before modification when the path is not certain
|
|
241
|
+
- prefer `info` before destructive actions
|
|
242
|
+
- prefer `replace` over full rewrites for small text changes
|
|
243
|
+
- prefer `upload` and `download` only for host boundary crossings
|
|
244
|
+
- prefer explicit verification after `mv`, `chmod`, `rm`, and `rmdir`
|