---
title: "Develop local"
description: "Develop local dùng hai process độc lập ở hai terminal. Bạn sở hữu watcher của app; CLI sở hữu Development session và tunnel dẫn về máy bạn. Sota CLI không bao giờ start, restart…"
url: "https://sotaagents.ai/vi/manual/developer-guide/local-development"
generated_by: "sotaagents-ldp"
docs_index: "https://sotaagents.ai/manual/llms.txt"
locale: "vi"
---

# Develop local

Develop local dùng hai process độc lập ở hai terminal. **Bạn** sở hữu watcher của app; **CLI** sở hữu Development session và tunnel dẫn về máy bạn. Sota CLI không bao giờ start, restart hay kill process của bạn — kể cả khi session dừng.

Terminal

```
# terminal 1 — watcher của app
npm run dev

# terminal 2 — Development session và tunnel
npm run dev:sota   # tương đương: sota dev
```

1. #### Tự chạy watcher

   Chạy `npm run dev`. Trong project scaffold có cả backend lẫn native UI, chỉ một script này đã chạy **cả hai**: `concurrently` khởi động watcher backend và watch build UI song song, gắn nhãn `backend` và `ui`, kèm `--kill-others` để một bên crash thì dừng cả cặp thay vì để lại nửa stack đang chạy.

2. #### Mở Development

   Chạy `sota dev`, chọn organization và workspace, rồi giữ process chạy. CLI chuẩn bị mọi thứ ở local trước — compile manifest, kiểm tra output frontend đã build, mở tunnel transport — rồi mới publish session trong một lần commit. Nếu bước chuẩn bị lỗi, không có gì được tạo trên server.

3. #### Iterate an toàn

   CLI theo dõi mọi file mà manifest đã compile được dựng lên từ đó — chính manifest, JSON Schema, file locale, native asset và nội dung skill được inline — rồi re-sync vào session cá nhân của bạn khi có thay đổi. Lỗi compile chỉ in diagnostics và giữ nguyên manifest last-known-good. Heartbeat mỗi 15 giây gia hạn lease của session.

4. #### Dừng sạch

   Chạy `sota dev stop`, hoặc bấm Ctrl-C trong terminal `sota dev`. Development app biến mất và Core lên lịch cleanup data. Process frontend/backend của bạn vẫn chạy — CLI nói rõ điều đó khi thoát.

### Chạy riêng UI và backend

`npm run dev` chỉ là lớp bọc tiện lợi cho hai script vẫn tồn tại độc lập. Hãy chạy riêng khi bạn muốn restart một nửa mà không đụng nửa kia, gắn debugger vào đúng một bên, hoặc — quan trọng nhất — khi backend của bạn không phải process Node.js.

| Script | Thực chất chạy gì | Ghi chú |
| --- | --- | --- |
| `npm run dev` | `concurrently --kill-others --names backend,ui "tsx watch src/backend/server.ts" "sota contracts ensure && vite build --watch"` | Cả hai nửa cùng lúc. Project chỉ có backend hoặc chỉ có UI thì rút gọn về đúng nửa đó. |
| `npm run dev:backend` | `tsx watch src/backend/server.ts` | HTTP service của app, tự restart khi source đổi. Nghe ở `PORT`, mặc định `8787`. |
| `npm run dev:ui` | `sota contracts ensure && vite build --watch` | Là _watch build_, không phải dev server. Nó làm mới App UI type contract rồi build lại `dist/ui/app.js` và `dist/ui/app.css` mỗi lần thay đổi. |
| `npm run dev:sota` | `sota dev` | Development session, đồng bộ manifest và tunnel. Độc lập với hai script trên. |

> [!NOTE]
> Không có UI server local, và đó là chủ ý.
>
> Native UI chạy bên trong host SotaAgents, không phải trên `localhost`. `dev:ui` chỉ cần giữ module đã build trên đĩa luôn mới; tunnel phục vụ đúng những bytes đó cho nền tảng — nhờ vậy cùng bộ file chạy y hệt khi được đóng gói vào artifact đã deploy.

### Dùng backend runtime của riêng bạn

Scaffold dùng TypeScript và Express vì đó là thứ phổ biến dễ hiểu, không phải vì nền tảng bắt buộc. Contract giữa SotaAgents và backend của bạn chỉ là HTTP thuần cộng một token đã verify, nên service viết bằng Go, Python, Java hay Rust đều là app backend hạng nhất. Một trong các system app của SotaAgents là service FastAPI verify đúng invocation token đó bằng Python, với cùng endpoint JWKS của Core.

Trong trường hợp đó bạn đơn giản là không dùng các script backend Node. Khởi động service theo cách của stack bạn, giữ `npm run dev:ui` cho native UI nếu app có UI, và trỏ overlay local vào cổng service của bạn đang nghe:

Terminal

```
# terminal 1 — backend của bạn, bằng ngôn ngữ của bạn
uvicorn app.main:app --reload --port 8787

# terminal 2 — watch build native UI (chỉ khi app có UI)
npm run dev:ui

# terminal 3 — Development session
sota dev
```

`sota dev` resolve Local Backend Endpoint theo thứ tự: flag `--local-url`, rồi `environments.local.service.baseUrl` trong manifest, rồi endpoint bạn dùng lần gần nhất (ghi nhớ trong `.sota/dev.json`). Trong terminal tương tác, CLI sẽ hỏi nếu không có nguồn nào; ngược lại nó fail với `LOCAL_BACKEND_UNAVAILABLE`. Sau đó CLI poll endpoint đó khoảng mỗi giây và in `[backend] available` hoặc `[backend] unavailable`. Kiểm tra này chỉ mang tính thông báo — nó không chặn việc publish session, nên backend tạm sập không làm mất Development app của bạn.

> [!WARNING]
> Live session là cá nhân.
>
> Nó thuộc một developer và một workspace. Chạy lại `sota dev` chỉ thay session cũ của chính bạn; đây không phải Staging dùng chung. Staging và Production không bao giờ phụ thuộc tunnel — chúng gọi thẳng backend bạn host.
