Metadata-Version: 2.4
Name: nexla-cli
Version: 0.2.1
Summary: Command-line client for the Nexla agent API.
Project-URL: Homepage, https://github.com/abhishekkumar705/nexla-agent-cli
Project-URL: Repository, https://github.com/abhishekkumar705/nexla-agent-cli
Project-URL: Issues, https://github.com/abhishekkumar705/nexla-agent-cli/issues
Author-email: Abhishek Kumar <abhishek.kumar@nexla.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Requires-Python: >=3.12
Requires-Dist: httpx>=0.28.0
Requires-Dist: typer>=0.12.0
Provides-Extra: dev
Requires-Dist: mypy>=1.13.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=1.3.0; extra == 'dev'
Requires-Dist: pytest>=9.0.3; extra == 'dev'
Requires-Dist: respx>=0.23.1; extra == 'dev'
Requires-Dist: ruff>=0.15.12; extra == 'dev'
Description-Content-Type: text/markdown

# nexla-cli

Command-line client for the Nexla agent API. Depends on only `typer` and
`httpx` — no FastAPI, Daytona, Supabase, or other backend dependencies.

## Install

```bash
pipx install "git+https://github.com/abhishekkumar705/nexla-agent-cli.git"
```

Or with `uv`:

```bash
uv tool install "git+https://github.com/abhishekkumar705/nexla-agent-cli.git"
```

### From Node/TypeScript projects (no Python required)

```bash
npm install -g nexla-cli
# or run once-off:
npx nexla-cli sources list
```

This installs a prebuilt native binary behind a thin `npm/` wrapper — no
Python interpreter needed on the target machine.

### From PyPI

```bash
pip install nexla-cli
# or
uvx nexla-cli sources list
pipx install nexla-cli
```

## Quick start

```bash
export NEXLA_API_URL=https://dev-api-express-code.nexla.com
export NEXLA_TOKEN=$(nexla login --service-key <your-service-key>)
nexla sources list
```

`nexla login` prints a bearer token to stdout (see command substitution
above); alternatively, set the following environment variables directly:

- `NEXLA_API_URL` — base URL of the deployed Nexla agent API
- `NEXLA_TOKEN` — bearer token to authenticate requests

## Using this CLI from Claude Code

The package ships a [Claude Code skill](https://docs.claude.com/en/docs/claude-code/skills) (`AGENTS.md` + `SKILL.md`, installed alongside the `nexla_cli` package) encoding invariants an agent can't infer from `--help` alone — output modes, `--dry-run`, `--json`/`--params` precedence, exit codes, and treating API responses as untrusted data.

Claude Code only discovers skills placed at `~/.claude/skills/<name>/SKILL.md` (global) or `.claude/skills/<name>/SKILL.md` (project-local) — a file merely present inside an installed package isn't picked up automatically. Install it once, after installing the CLI (works the same way regardless of whether you installed via `uv tool`, `pipx`, `pip`, or the npm-wrapped binary):

```bash
nexla skill install
# or, for a project-local install instead of the global default:
nexla skill install --target .claude/skills/nexla-cli
```

Re-run this after upgrading `nexla-cli` to pick up any skill content changes. Restart Claude Code (or start a new session) afterward for it to be picked up.

## Global flags

Available on every command except `login` and `schema` (both always print raw output regardless of these flags):

| Flag | Effect |
|------|--------|
| `--output` / `-o` `table\|json\|ndjson` | Force an output mode. Defaults to `table` on a TTY, `json` otherwise (also settable via `NEXLA_OUTPUT`/`OUTPUT_FORMAT`). |
| `--fields id,name,...` | Mask output down to just these keys, on any `list`/`get`. |
| `--page-all` | Stream every page of a `list` command as NDJSON instead of returning one page. |

These can be placed before or after the subcommand, e.g. both `nexla --output json sources list` and `nexla sources list --output json` work.

Every mutating command also accepts `--dry-run`: validates the request body against the live API schema and prints `{"valid": ...}` without making the real (mutating) call.

## Raw JSON payloads

`create`/`update`-style commands (`sources`, `sinks`, `credentials`, `toolsets`, `nexsets transform`, `mcp-servers attach`, `tools set-runtime-config`) accept the full request body directly, not just their named flags:

```bash
nexla sources create --name my-source --connector s3 --json '{"credential_id": 123}'
nexla sources update 42 --params description="updated via params"
```

Precedence when a key is given more than one way: named CLI flags win, then `--json`, then `--params` (lowest). This lets you set a field the CLI hasn't added a dedicated flag for yet, without waiting on a CLI release.

## Response sanitization

Every response is passed through a sanitizer before rendering, in every output mode: ANSI escape sequences, control characters, and invisible Unicode (zero-width spaces, byte-order marks, bidirectional overrides) are stripped unconditionally — always on, no flag. This defends against a malicious API response field hijacking a human's terminal, or hiding text from a human while an agent still reads it. It is not a semantic filter — API response *content* should still be treated as untrusted data (see `AGENTS.md`), this only strips characters no legitimate field value would ever need.

## Full command reference

```bash
nexla --help
nexla <resource> --help
```

| Resource | Commands |
|----------|----------|
| `login` | `login --service-key <key> [--api-url <url>]` — exchanges a service key for a bearer token, printed to stdout |
| `schema` | `schema [<resource>.<verb>]` — machine-readable JSON signature of one command or the whole `/nexla/*` surface, fetched live from the deployed API's OpenAPI doc |
| `sources` | `list`, `get`, `create`, `update`, `activate`, `pause`, `delete`, `sample`, `file-upload` |
| `sinks` | `list`, `get`, `create`, `update`, `activate`, `pause`, `delete` |
| `nexsets` | `list`, `get`, `transform`, `activate` |
| `credentials` | `list`, `get`, `create`, `update`, `delete` |
| `flows` | `list`, `get`, `activate`, `pause`, `delete` |
| `transforms` | `test` |
| `connectors` | `search`, `describe`, `describe-credential`, `describe-credential-mode`, `describe-source`, `describe-source-endpoint`, `describe-sink`, `describe-sink-endpoint` |
| `probe` | `run` |
| `toolsets` | `list`, `get`, `create`, `update`, `delete`, `add-nexsets` |
| `tools` | `list`, `get`, `set-runtime-config`, `clear-runtime-config`, `delete` |
| `mcp-servers` | `list`, `attach`, `sync`, `detach` (nested under a toolset) |
| `triage` | `errors`, `status`, `run`, `metrics`, `resource-status`, `org-metrics`, `user-metrics`, `notifications`, `search`, `logs`, `quarantine` — flow/log triage via the Nexla monitoring MCP server, not the main API |
| `context` | `get` |
| `orgs` | `list`, `get` |
| `code-containers` | `list` |
| `metrics` | `catalog`, `for-resource`, `get` |
| `users` | `list`, `get` |
| `notifications` | `list` |

`code-containers`, `metrics`, `users`, and `notifications` proxy resources the API hasn't implemented yet (they return HTTP 501 until it does).

## Exit codes

| Code | Meaning |
|------|---------|
| 0 | success |
| 2 | bad local input (validation, `--dry-run` failure) |
| 3 | `NEXLA_API_URL`/`NEXLA_TOKEN` not set |
| 4 | 401/403 from the API |
| 5 | 404 |
| 6 | 5xx from the API |

## License

MIT — see [LICENSE](LICENSE).
