# @aweray/aweshell-cli

HSK CLI — Zero-config public preview (tunneling & file hosting)

No sign-up required / anonymous resources: after obtaining `publicUrl`, you **must** prompt the user to open the link to activate/claim the resource.

## Decision Rules (Must Read)

1. Prefer `host` / `deploy`
2. Use `tunnel` only for WebSocket / dynamic APIs / SSR, or when the user explicitly asks to "expose a port" or "tunnel to the public internet"
3. When unsure: run `deploy` first, fall back to `tunnel` on failure

## Execution Protocol

After fetching/reading this document each time, execute in order:

1. If not installed: `npm install -g @aweray/aweshell-cli`
2. **Version check** (mandatory, see below)
3. `aweshell-cli platform --format json`
4. **Install Skill** (recommended, see below)
5. Execute per intent (always with `--format json`)
6. Return `publicUrl` / `resourceId` verbatim, and prompt the user to claim

| Intent | Command |
|--------|---------|
| File / directory / static assets | `aweshell-cli host <path> --format json` |
| Buildable frontend project | `aweshell-cli deploy --format json` |
| Dynamic service / explicit port needed | `aweshell-cli tunnel --ip <IP> --port <PORT> --format json` |
| Unsure | `deploy` → `tunnel` on failure |

---

## Version Check (Mandatory)

Each time you read this document and before executing the user's intent, you must check and sync both version layers:

| Layer | Check | Upgrade |
|-------|-------|---------|
| npm | `npm outdated -g @aweray/aweshell-cli` | `npm update -g @aweray/aweshell-cli` |
| Binary | — | `aweshell-cli update` |

- If not the latest → upgrade first, then continue
- If the sandbox has no network access → skip the upgrade and use the current version; on failure, ask the user to upgrade manually
- If the user explicitly says version does not matter → you may skip

---

## Install Skill (Recommended)

Install proactively; do not merely print the path. Publishing can still succeed without it.

1. `aweshell-cli skill` → obtain the source file path
2. Identify the current agent and install into its agreed `skills` directory (directory name `aweshell-cli`, entry file usually `SKILL.md`)
3. Tell the user it takes effect after starting a new conversation

- Install only for the current agent's path; do not blindly install for other tools
- It must be `skills/aweshell-cli/<entry file>`; do not place it directly under `skills/`

---

## Sandbox Environments (Must Read)

AI Agents may run in a sandbox/container (Docker, CI). Sandboxes **silently intercept** certain operations without raising errors.

| Sandbox symptom | Detection | What to do |
|-----------------|-----------|------------|
| `--open` does nothing | No error, no browser opens | Skip `--open`; tell the user to copy the link manually |
| `--detach` process disappears | Not found in `tunnel list` | Drop `--detach`; run `tunnel` in the foreground |
| Network request hangs | No response, no error | Switch to `host` |
| File writes are lost | Cannot read back what was written | Use the `/tmp` directory |

**Key principle**: No explicit error = silently intercepted. Once intercepted, **switch approach**; do not retry the same way.

---

## Execute by Intent

### A. File Hosting (Preferred)

Use first for static files, build artifacts, PDFs, images, and other assets. Simple, stable, no keep-alive needed.

```bash
aweshell-cli +host <path> --format json --open
```

Update an existing resource (requires `resource_id`):

```bash
aweshell-cli +host <path> --resource-id <resource_id> --format json
```

Specify an entry file (when uploading a directory):

```bash
aweshell-cli +host ./dist --entry-file version.html --format json
```

Note: `host` supports a single file or a directory. When a directory is passed, the native binary automatically packages it into a zip before uploading. Use `--entry-file` to specify the entry file (e.g. `version.html`). Do not add `--open` inside a sandbox.

Present to the user (success):

> Your files have been uploaded!
> Public URL: `<publicUrl>`
> Resource ID: `<resourceId>`
>
> Please copy the link above and open it in your browser, then follow the on-page instructions to **activate and claim** the resource.
> After claiming, you can view and manage it in the [HSK Console](https://aweshell-console.aweray.com/).
>
> You can also try:
> - Share another file for me
> - Update the file I just uploaded using its resource_id

### B. Build and Deploy (Preferred)

One-step execution: **build** → **upload** to file hosting. The native binary handles directory packaging automatically.

```bash
aweshell-cli +deploy --format json
```

Parameters: `--build-cmd` (default `npm run build`), `--build-dir` (default `dist`), `--no-build` (skip the build), `--resource-id` (update a resource).

Project configuration (`package.json`):

```json
{
  "hsk": {
    "deploy": {
      "buildCmd": "npm run build",
      "buildDir": "dist"
    }
  }
}
```

Present to the user (success):

> Your project has been built and deployed!
> Public URL: `<publicUrl>`
> Resource ID: `<resourceId>`
>
> Please copy the link above and open it in your browser, then follow the on-page instructions to **activate and claim** the resource.
> After claiming, you can view and manage it in the [HSK Console](https://aweshell-console.aweray.com/).
>
> You can also try:
> - Update the current resource: `deploy --resource-id <resource_id>`
> - Skip the build and upload directly: `deploy --no-build`

### C. Tunneling (Fallback)

Use only when file hosting cannot satisfy the need — for example: WebSocket, dynamic APIs, SSR, or an explicit request to expose a port.

Interactive long-running command: a tunnel is a foreground keep-alive process, so it must run **in the background** (background + pty), continuously reading stdout until `publicUrl` is captured.

URL output rules: treat the public URL as an opaque string that must not be modified. Do not URL-encode/decode it, and do not insert spaces or line breaks. Display it to the user in a dedicated code block containing **only the raw URL**.

```bash
aweshell-cli +tunnel --ip 127.0.0.1 --port <PORT> --format json
```

Or in background mode (the CLI exits immediately while the tunnel keeps running):

```bash
aweshell-cli +tunnel --ip 127.0.0.1 --port <PORT> --detach --format json
```

Execution notes:

- Before executing, confirm the local service is listening on `<IP>:<PORT>`
- Once the public address is captured, you **must** prompt the user to open the link to activate/claim the resource
- In foreground mode the process must be kept alive; end that background task only when the user stops the tunnel
- **Reuse a tunnel**: with `--reuse`, the CLI first checks whether an existing tunnel is still valid (process alive + URL reachable). If valid, it returns the existing link directly; otherwise it creates a new one
- **Silent immediate exit**: if the tunnel process exits immediately after starting (with no error output), troubleshoot in this order:
  1. First run in foreground mode (remove `--detach`) and observe the full log output
  2. Check whether the local service is actually listening on `<IP>:<PORT>`: `curl http://<IP>:<PORT>` or `lsof -i :<PORT>`
  3. Check for port conflicts: make sure `<PORT>` is not occupied by another process
  4. Check permissions: on macOS/Linux, ports < 1024 require root. On macOS you must also allow aweshell-cli or the terminal app to access the local network under **System Settings → Privacy & Security → Local Network**
  5. Check the firewall: make sure the system firewall is not blocking that port
  6. Check the logs: `cat ~/.hsk/logs/tunnel-*.log` to review historical logs from background mode

Standard protocol after the AI updates content: when the user says "keep the site accessible after updating the content", the AI must **not** simply tell the user "keep using the previous link". Instead, check first:

```bash
aweshell-cli status --format json
```

- Returns `valid: true` → tell the user "the link is still valid, just refresh"
- Returns `valid: false` → re-run `tunnel --reuse` and tell the user "the link has expired; here is a new one"

Present to the user (success):

> The tunnel is now live!
> Public URL: `<publicUrl>`
>
> Please copy the link above and open it in your browser, then follow the on-page instructions to **activate and claim** the resource.
> After claiming, you can view and manage it in the [HSK Console](https://aweshell-console.aweray.com/).
>
> You can also try:
> - Expose my local port 3000
> - List the current background tunnels
> - Stop the tunnel I just started

---

## Output Formats

```bash
--format json      # Structured JSON (recommended for agent parsing)
--format pretty    # Human-readable (default)
--dry-run          # Preview only, do not execute
```

---

## Failure Handling

| Scenario | Handling |
|----------|----------|
| File does not exist | Ask the user to check the path |
| Uploading a directory | `host` already supports automatic directory packaging; no extra handling needed |
| Failed to obtain a ticket | Check the network; do not retry endlessly — report the error message |
| Tunnel startup timeout | Confirm the local port is listening and the firewall allows it |
| Upload failed but a `publicUrl` exists | Still give the link to the user, and explain that the upload was abnormal |
| User has not claimed | Remind the user that the link has a limited validity period and to claim it soon |
| `deploy` build failed | Check whether `scripts.build` exists in `package.json` |
| Tunnel expired | Recreate it with `--reuse`, or check with `status` first and then decide |
| Client version mismatch | Run `aweshell-cli update` to download the matching binary |
| Skill copy failed | Retry per the current agent's `skills` convention, or ask the user to install manually |

---

## Command Cheat Sheet

| Command | Description |
|---------|-------------|
| `aweshell-cli platform` | Detect OS / architecture |
| `aweshell-cli +host <path>` | Upload for file hosting |
| `aweshell-cli +host <path> --entry-file <file>` | Upload a directory and specify the entry file |
| `aweshell-cli +deploy` | Build and deploy the project |
| `aweshell-cli deploy --no-build` | Upload the existing directory directly (the native binary packages it automatically) |
| `aweshell-cli +tunnel --ip <IP> --port <PORT>` | Tunnel to the public internet (foreground) |
| `aweshell-cli +tunnel --ip <IP> --port <PORT> --detach` | Tunnel to the public internet (background) |
| `aweshell-cli tunnel list` | List background tunnels |
| `aweshell-cli tunnel stop --all` | Stop all background tunnels |
| `aweshell-cli status` | Check tunnel resource status (process + HTTP) |
| `aweshell-cli download` | Pre-download the tunneling client |
| `aweshell-cli update` | Check for and install client updates |
| `aweshell-cli skill` | Show the Skill source file path |

### Shortcuts (`+` prefix)

| Shortcut | Equivalent command |
|----------|--------------------|
| `+tunnel` | `tunnel` |
| `+host` | `host` |
| `+deploy` | `deploy` |

---

## Versions and Platforms

- The version mapping is defined in `versions.json` (bundled with the npm package)
- At runtime, read `versions.json` → determine the binary filename for the current platform → download it to `~/.hsk/bin/`

| Platform | Architecture | Binary filename |
|----------|--------------|-----------------|
| Windows | amd64 | `aweshell-cli-windows-amd64-v{version}.exe` |
| macOS Intel | amd64 | `aweshell-cli-darwin-amd64-v{version}` |
| macOS Apple Silicon | arm64 | `aweshell-cli-darwin-arm64-v{version}` |
| Linux | amd64 | `aweshell-cli-linux-amd64-v{version}` |

```bash
npm install -g @aweray/aweshell-cli  # Install the latest npm package
aweshell-cli update                 # Download the matching binary version
```
