Skip to content
This repository was archived by the owner on Jul 16, 2025. It is now read-only.

Commit 5d46377

Browse files
authored
feat: preview and authentication, exec env, multi file upload (#332)
Signed-off-by: Ivan Dagelic <[email protected]>
1 parent 125d9f7 commit 5d46377

28 files changed

+850
-510
lines changed

public/llms-full.txt

Lines changed: 183 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Daytona Documentation v0.12.0
2-
# Generated on: 2025-04-13
2+
# Generated on: 2025-04-14
33

44

55
title: API Keys
@@ -137,6 +137,7 @@ Daytona SDK provides an option to list files and directories in a Sandbox using
137137
```python
138138
# List files in a directory
139139
files = sandbox.fs.list_files("/workspace")
140+
140141
for file in files:
141142
print(f"Name: {file.name}")
142143
print(f"Is directory: {file.is_dir}")
@@ -146,14 +147,14 @@ for file in files:
146147
```
147148
```typescript
148149
// List files in a directory
149-
const files = await sandbox.fs.listFiles("/workspace");
150+
const files = await sandbox.fs.listFiles("/workspace")
150151

151152
files.forEach(file => {
152-
console.log(`Name: ${file.name}`);
153-
console.log(`Is directory: ${file.isDir}`);
154-
console.log(`Size: ${file.size}`);
155-
console.log(`Modified: ${file.modTime}`);
156-
});
153+
console.log(`Name: ${file.name}`)
154+
console.log(`Is directory: ${file.isDir}`)
155+
console.log(`Size: ${file.size}`)
156+
console.log(`Modified: ${file.modTime}`)
157+
})
157158
```
158159

159160

@@ -172,49 +173,124 @@ sandbox.fs.create_folder("/workspace/new-dir", "755")
172173
```
173174
```typescript
174175
// Create a directory
175-
await sandbox.fs.createFolder("/workspace/new-dir");
176+
await sandbox.fs.createFolder("/workspace/new-dir")
176177

177178
// Create with specific permissions
178-
await sandbox.fs.createFolder("/workspace/new-dir", "755");
179+
await sandbox.fs.createFolder("/workspace/new-dir", "755")
179180
```
180181

181182

182-
### File Operations
183+
### Uploading Files
183184

184185
Daytona SDK provides options to read, write, upload, download, and delete files in Sandboxes using Python and TypeScript.
185186

186187
```python
187-
# Upload a file
188+
189+
root_dir = sandbox.get_user_root_dir()
190+
191+
# Upload a single file
192+
188193
with open("local_file.txt", "rb") as f:
189194
content = f.read()
190-
sandbox.fs.upload_file("/workspace/remote_file.txt", content)
195+
sandbox.fs.upload_file(root_dir + "/remote_file.txt", content)
191196

192-
# Download a file
197+
# Upload multiple files at once
193198

194-
content = sandbox.fs.download_file("/workspace/remote_file.txt")
195-
with open("local_file.txt", "wb") as f:
196-
f.write(content)
199+
files_to_upload = []
197200

198-
# Delete a file
201+
with open("file1.txt", "rb") as f1:
202+
files_to_upload.append(FileUpload(
203+
path=root_dir + "/data/file1.txt",
204+
content=f1.read()
205+
))
199206

200-
sandbox.fs.delete_file("/workspace/file.txt")
207+
with open("file2.txt", "rb") as f2:
208+
files_to_upload.append(FileUpload(
209+
path=root_dir + "/data/file1.txt",
210+
content=f2.read()
211+
))
212+
213+
with open("settings.json", "rb") as f3:
214+
files_to_upload.append(FileUpload(
215+
path=root_dir + "/config/settings.json",
216+
content=f3.read()
217+
))
218+
219+
sandbox.fs.upload_files(files_to_upload)
201220

202221
```
203222
```typescript
204-
// Upload a file
223+
224+
const rootDir = await workspace.getUserRootDir()
225+
226+
// Upload a single file
205227
const fileContent = new File(
206228
[Buffer.from('Hello, World!')],
207229
'data.txt',
208230
{ type: 'text/plain' }
209-
);
210-
await sandbox.fs.uploadFile("/workspace/remote_file.txt", fileContent);
231+
)
232+
await workspace.fs.uploadFile(rootDir + "/data.txt", fileContent)
233+
234+
// Upload multiple files at once
235+
const files = [
236+
{
237+
path: rootDir + '/data/file1.txt',
238+
content: new File(['Content of file 1'], 'file1.txt')
239+
},
240+
{
241+
path: rootDir + '/data/file2.txt',
242+
content: new File(['Content of file 2'], 'file2.txt')
243+
},
244+
{
245+
path: rootDir + '/config/settings.json',
246+
content: new File(['{"key": "value"}'], 'settings.json')
247+
}
248+
]
249+
250+
await workspace.fs.uploadFiles(files)
251+
252+
```
253+
254+
255+
### Downloading Files
256+
257+
The following commands downloads the file `file1.txt` from the Sandbox user's root directory and prints out the content:
258+
259+
```python
260+
261+
root_dir = sandbox.get_user_root_dir()
262+
263+
content = sandbox.fs.download_file(root_dir + "/file1.txt")
264+
265+
with open("local_file.txt", "wb") as f:
266+
f.write(content)
267+
268+
print(content.decode('utf-8'))
269+
270+
```
271+
```typescript
272+
273+
const rootDir = await workspace.getUserRootDir()
274+
275+
const downloadedFile = await sandbox.fs.downloadFile(rootDir + "/file1.txt")
211276

212-
// Download a file
213-
const downloadedFile = await sandbox.fs.downloadFile("/workspace/remote_file.txt");
214277
console.log('File content:', downloadedFile.toString())
215278

216-
// Delete a file
217-
await sandbox.fs.deleteFile("/workspace/file.txt");
279+
```
280+
281+
282+
### Deleting files
283+
284+
Once you no longer need them, simply delete files by using the `delete_file` function.
285+
286+
```python
287+
288+
sandbox.fs.delete_file("/workspace/file.txt")
289+
290+
```
291+
```typescript
292+
293+
await sandbox.fs.deleteFile("/workspace/file.txt")
218294
```
219295

220296

@@ -238,11 +314,11 @@ print(f"Permissions: {file_info.permissions}")
238314
```
239315
```typescript
240316
// Set file permissions
241-
await sandbox.fs.setFilePermissions("/workspace/file.txt", { mode: "644" });
317+
await sandbox.fs.setFilePermissions("/workspace/file.txt", { mode: "644" })
242318

243319
// Get file permissions
244-
const fileInfo = await sandbox.fs.getFileDetails("/workspace/file.txt");
245-
console.log(`Permissions: ${fileInfo.permissions}`);
320+
const fileInfo = await sandbox.fs.getFileDetails("/workspace/file.txt")
321+
console.log(`Permissions: ${fileInfo.permissions}`)
246322
```
247323

248324

@@ -276,19 +352,19 @@ sandbox.fs.replace_in_files(
276352
const results = await sandbox.fs.findFiles({
277353
path="/workspace/src",
278354
pattern: "text-of-interest"
279-
});
355+
})
280356
results.forEach(match => {
281357
console.log('Absolute file path:', match.file)
282358
console.log('Line number:', match.line)
283359
console.log('Line content:', match.content)
284-
});
360+
})
285361

286362
// Replace text in files
287363
await sandbox.fs.replaceInFiles(
288364
["/workspace/file1.txt", "/workspace/file2.txt"],
289365
"old_text",
290366
"new_text"
291-
);
367+
)
292368
```
293369

294370
title: Getting Started
@@ -447,8 +523,8 @@ sandbox.process.execute_session_command(exec_session_id, SessionExecuteRequest(
447523

448524
# Get the preview link for the Flask app
449525

450-
preview_link = sandbox.get_preview_link(3000)
451-
print(f"Flask app is available at: {preview_link}")
526+
preview_info = sandbox.get_preview_link(3000)
527+
print(f"Flask app is available at: {preview_info.url}")
452528

453529
```
454530

@@ -506,15 +582,17 @@ if __name__ == '__main__':
506582
}));
507583

508584
// Get the preview link for the Flask app
509-
const previewLink = sandbox.getPreviewLink(3000);
510-
console.log(`Flask app is available at: ${previewLink}`);
585+
const previewInfo = sandbox.getPreviewLink(3000);
586+
console.log(`Flask app is available at: ${previewInfo.url}`);
511587
}
512588

513589
main().catch(error => console.error("Error:", error));
514590

515591
```
516592

517593

594+
Need to access this endpoint programmatically? Learn more about [Preview & Authentication](/docs/preview-and-authentication).
595+
518596
:::tip
519597
You can access the Sandbox [Web Terminal](/docs/web-terminal) by printing out the preview URL for port `22222` or by simply going to Dashboard -> Sandboxes and clicking on the Terminal input sign.
520598
:::
@@ -663,6 +741,8 @@ npx ts-node claude-example.ts
663741

664742
Use the Daytona SDK [Python examples](https://github.com/daytonaio/sdk/tree/main/examples/python) or [TypeScript/JavaScript examples](https://github.com/daytonaio/sdk/tree/main/examples/typescript) to create a Sandbox and run your code.
665743

744+
Speed up your development on Daytona using LLMs. Copy the /llms.txt files and include them into your projects or chat context: [llms-full.txt](https://www.daytona.io/docs/llms-full.txt) or [llms.txt](https://www.daytona.io/docs/llms.txt)
745+
666746
Learn more by checkout out the Daytona SDK repository on [GitHub](https://github.com/daytonaio/sdk).
667747

668748
## Setting up the Daytona CLI
@@ -1095,7 +1175,7 @@ enabling you to programmatically manage development environments and execute cod
10951175

10961176
### Quick Start
10971177

1098-
Run your first line of code in a Daytona Sandbox.
1178+
Run your first line of code in a Daytona Sandbox. Use our [LLMs context files](/docs/getting-started#additional-examples) for faster development with AI assistants.
10991179

11001180
#### 1. Get Your API Key
11011181

@@ -1104,7 +1184,6 @@ Run your first line of code in a Daytona Sandbox.
11041184
- Go to the Daytona [Dashboard](https://app.daytona.io/dashboard).
11051185
- Create a new [API key](https://app.daytona.io/dashboard/keys). Make sure to save it securely,
11061186
as it won't be shown again.
1107-
- You'll need it in the next step.
11081187

11091188
#### 2. Install the SDK
11101189

@@ -1529,6 +1608,40 @@ Organization and they may proceed by issuing a new API key and creating sandboxe
15291608

15301609
The Settings subpage in the Dashboard allows you to view the Organization ID and Name and to delete the Organization if you don't need it anymore. This action is irreversible, so please proceed with caution. Personal Organizations are there by default and cannot be deleted.
15311610

1611+
title: Preview & Authentication
1612+
1613+
import { Tabs, TabItem } from '@astrojs/starlight/components';
1614+
1615+
Processes listening for HTTP traffic in port range `3000-9999` can be previewed using preview links.
1616+
1617+
A preview link's schema consists of the port, Sandbox ID and node combination, e.g.:
1618+
`https://3000-sandbox-123456.h7890.daytona.work`
1619+
1620+
If the Sandbox has its `public` property set to `true`, these links will be publicly accessible, otherwise the preview link will be available only to the Sandbox Organization users.
1621+
1622+
For programmatic access (for example, `curl`), use the authorization token to access the preview URL, e.g.:
1623+
`curl -H "x-daytona-preview-token: vg5c0ylmcimr8b_v1ne0u6mdnvit6gc0" https://3000-sandbox-123456.h7890.daytona.work`
1624+
1625+
To fetch the preview link and the authorization token for a specific port, you can simply use the SDK method:
1626+
1627+
```python
1628+
1629+
preview_info = sandbox.get_preview_link(3000)
1630+
1631+
print(f"Preview link url: {preview_info.url}")
1632+
print(f"Preview link token: {preview_info.token}")
1633+
1634+
```
1635+
1636+
```typescript
1637+
1638+
const previewInfo = await sandbox.getPreviewUrl(3000);
1639+
1640+
console.log(`Preview link url: ${previewInfo.url}`);
1641+
console.log(`Preview link token: ${previewInfo.token}`);
1642+
1643+
```
1644+
15321645
title: Process and Code Execution
15331646

15341647
import { Tabs, TabItem } from '@astrojs/starlight/components';
@@ -1598,16 +1711,46 @@ Daytona SDK provides an option to execute shell commands and manage background p
15981711
Daytona SDK provides an option to execute shell commands in Python and TypeScript. You can run commands with input, timeout, and environment variables.
15991712

16001713
```python
1601-
# Execute shell command
1714+
1715+
# Execute any shell command
1716+
16021717
response = sandbox.process.exec("ls -la")
16031718
print(response.result)
1719+
1720+
# Setting a working directory and a timeout
1721+
1722+
response = sandbox.process.exec("sleep 3", cwd="/workspace/src", timeout=5)
1723+
print(response.result)
1724+
1725+
# Passing environment variables
1726+
1727+
response = sandbox.process.exec("echo $CUSTOM_SECRET", env={
1728+
"CUSTOM_SECRET": "DAYTONA"
1729+
}
1730+
)
1731+
print(response.result)
1732+
16041733
```
16051734
```typescript
1606-
// Execute shell command
1735+
1736+
// Execute any shell command
16071737
const response = await sandbox.process.executeCommand("ls -la");
16081738
console.log(response.result);
1739+
1740+
// Setting a working directory and a timeout
1741+
const response2 = await sandbox.process.executeCommand("sleep 3", "/workspace/src", undefined, 5);
1742+
console.log(response2.result);
1743+
1744+
// Passing environment variables
1745+
const response3 = await sandbox.process.executeCommand("echo $CUSTOM_SECRET", "/", {
1746+
"CUSTOM_SECRET": "DAYTONA"
1747+
}
1748+
);
1749+
console.log(response3.result);
1750+
16091751
```
16101752

1753+
16111754
## Sessions (Background Processes)
16121755

16131756
Daytona SDK provides an option to start, stop, and manage background process sessions in Sandboxes. You can run long-running commands, monitor process status, and list all running processes.
@@ -1928,23 +2071,7 @@ const state = sandbox.instance.state
19282071
```
19292072

19302073

1931-
### Sandbox Preview Port
1932-
1933-
Daytona SDK also provides a method to get the preview port for the Sandbox.
1934-
1935-
```python
1936-
# Get the preview link for an app running on port 3000
1937-
1938-
preview_link = sandbox.get_preview_link(3000)
1939-
1940-
```
1941-
```typescript
1942-
// Get the preview link for an app running on port 3000
1943-
1944-
const previewLink = sandbox.getPreviewLink(3000)
1945-
1946-
```
1947-
2074+
To get the preview URL for a specific port, check out [Preview & Authentication](/docs/preview-and-authentication).
19482075

19492076
## Remove Sandbox
19502077

0 commit comments

Comments
 (0)