> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensor9.com/llms.txt
> Use this file to discover all available pages before exploring further.

# AWS CLI Guide

> Prove an AWS API workflow through Cloud Adapter from the command line.

The AWS CLI is the fastest way to prove the full request path: AWS command, Cloud Adapter endpoint, service adapter, and native target service. It is also a useful diagnostic control because it removes your application code from the test.

This walkthrough uses S3. The same pattern works for another AWS service when that service page documents the operation and target environment you need.

## Start a local adapter

This guide's bounded example uses S3 backed by Google Cloud Storage:

**1. Install or update the Tensor9 CLI**

Install the customer CLI with Homebrew, then confirm the binary is available:

```bash theme={null}
brew tap tensor9ine/tensor9
brew trust tensor9ine/tensor9
brew install tensor9
tensor9 --version
```

If `tensor9` is already installed, run `brew upgrade tensor9` instead of the install command.

**2. Authenticate with Tensor9**

To create a Tensor9 account and download an API key yourself, follow [Get a Tensor9 API key](https://docs.tensor9.com/byoc/getting-started/api-key.md).

A Tensor9 API key is required. Use the key issued during onboarding, or email [hello@tensor9.com](mailto:hello@tensor9.com) to request one for your organization. Do not share your account or key with another customer or organization.

If your secret manager has already supplied `T9_API_KEY`, skip the prompt. Otherwise, enter your key at a hidden prompt in the terminal where you will run `tensor9`:

> [tab] Bash
>
> ```bash theme={null}
> set +x
> IFS= read -r -s -p 'Tensor9 API key: ' T9_API_KEY
> printf '\n'
> export T9_API_KEY
> ```

> [tab] Zsh
>
> ```zsh theme={null}
> set +x
> IFS= read -r -s 'T9_API_KEY?Tensor9 API key: '
> printf '\n'
> export T9_API_KEY
> ```

Check that the variable is set without printing it, then verify your Tensor9 identity:

```bash theme={null}
: "${T9_API_KEY:?Set T9_API_KEY before continuing}"
tensor9 whoami
```

Confirm that the reported identity belongs to the intended customer account. Do not continue if authentication fails or the account is wrong. While `T9_API_KEY` is set, `tensor9` commands in this terminal use the key instead of any controller profile, so use a separate terminal for this work and run `unset T9_API_KEY` when you finish. Keep shell tracing disabled while using the key. Do not paste the key into commands, shell profiles, source files, screenshots or support messages.

See [Install and Authenticate](https://docs.tensor9.com/cloud-adapter-early-access/getting-started/install-and-authenticate.md) for the planned license lifecycle, entitlements and credential boundaries.

**3. Inspect the S3 to Google Cloud Storage mapping**

Ask Tensor9 to describe the exact directed service mapping used by this guide:

```bash theme={null}
tensor9 explain \
  -origin aws::1.0.0::s3 \
  -target google::1.0.0::gcs \
  -fmt Human
```

Read the supported S3 operations and Google Cloud Storage limitations before starting the process. The mapping is directional: this command describes S3 requests adapted to Google Cloud Storage, not the reverse direction.

**4. Prepare Google Cloud access**

Authenticate with Google Cloud using its standard Application Default Credentials chain. The adapter uses that identity when it calls Google Cloud Storage.

Use a dedicated test project and narrowly scoped credentials. Do not put credentials in the command line, source code, or screenshots.

**5. Start the S3 service adapter**

Run the S3 to Google Cloud Storage adapter as a foreground process:

```bash theme={null}
tensor9 adapt svc run \
  --origin aws::1.0.0::s3 \
  --backend google::1.0.0::gcs
```

Leave this terminal open. This is the current foreground launcher, not the pending Docker launcher for [local development mode](https://docs.tensor9.com/cloud-adapter-early-access/deployment/single-binary.md). It calls your actual target-cloud services; it is separate from the in-memory emulator. Acquisition and license renewal require Tensor9 authentication. Keep the endpoint local to your test.

**6. Copy the listening endpoint**

When the command reports its listening endpoint, copy that exact value into a second terminal:

```bash theme={null}
export T9_CLOUD_ADAPTER_ENDPOINT="<endpoint printed by tensor9>"
```

Keep the endpoint local to the test unless you have deliberately configured network access and authentication for another machine.

**7. Run one bounded S3 request**

Continue with this page's client or tool instructions. Point only S3 at `T9_CLOUD_ADAPTER_ENDPOINT`, then perform one operation whose Google Cloud Storage effect you can verify independently.

Check both sides: read the S3-shaped response and inspect the native object or bucket in Google Cloud Storage. A successful client response alone does not prove that the target state is correct.

**8. Stop the local adapter**

Return to the first terminal and press **Control-C**. Confirm the process exits before deleting the test object or bucket with Google Cloud's native client.

If the request failed, preserve the request ID, adapter endpoint, S3 operation name, Google Cloud request ID, and any `x-t9-explain-*` receipt headers before stopping the process.

## Before you begin

You need:

* an installed AWS-origin Cloud Adapter endpoint;
* an origin-side test identity accepted by that endpoint;
* a configured S3 service adapter and a target bucket;
* AWS CLI v2;
* a unique prefix that is safe to create and delete.

Read [S3 service coverage](https://docs.tensor9.com/cloud-adapter-early-access/service-catalog/aws/databases-storage/s3.md) before testing. Coverage is directional and operation-specific.

## Choose the endpoint scope

### Set S3 for the process

AWS CLI v2 supports the AWS-standard, service-specific endpoint variable:

```bash theme={null}
export AWS_ENDPOINT_URL_S3="$T9_CLOUD_ADAPTER_ENDPOINT"
aws s3api head-bucket --bucket adapter-smoke-test
```

This applies to every S3 command in the process without redirecting STS, DynamoDB, or another AWS service. The official pattern is `AWS_ENDPOINT_URL_<SERVICE>`; for S3 it is `AWS_ENDPOINT_URL_S3`.

### Set one command at a time

Use `--endpoint-url` when the endpoint should be visible on each command or when one process talks to both AWS and Cloud Adapter. Keep the URL in a Tensor9-specific variable:

```bash theme={null}
: "${T9_CLOUD_ADAPTER_ENDPOINT:?start the local adapter and copy its endpoint first}"
export AWS_PROFILE="adapter-test"
export AWS_REGION="us-east-1"
export AWS_REQUEST_CHECKSUM_CALCULATION="WHEN_REQUIRED"
export TEST_BUCKET="adapter-smoke-test"
export TEST_KEY="quickstart/$(date +%s)-hello.txt"
```

Confirm the active profile without printing secrets:

```bash theme={null}
aws configure list --profile "$AWS_PROFILE"
```

`AWS_REQUEST_CHECKSUM_CALCULATION=WHEN_REQUIRED` keeps the first smoke test on the required S3 checksum path. If your application uses optional flexible checksums, validate those algorithms separately against the selected target profile.

An explicit `--endpoint-url` takes precedence over `AWS_ENDPOINT_URL_S3`. The remaining commands use the explicit form so each network destination is visible at the call site.

## Run a read-only request first

Start with the smallest covered read. Passing `--endpoint-url` on every command makes accidental calls to AWS much less likely.

```bash theme={null}
aws s3api head-bucket \
  --bucket "$TEST_BUCKET" \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" \
  --profile "$AWS_PROFILE" \
  --region "$AWS_REGION"
```

If the target uses a bucket name that differs from the origin name, use the origin-facing name from the service adapter configuration. Cloud Adapter owns the name translation.

## Exercise a complete object lifecycle

Create a small local payload, upload it, read it back, compare it, and delete only the object created by this test.

```bash theme={null}
printf 'hello through Cloud Adapter\n' > /tmp/cloud-adapter-smoke.txt

aws s3api put-object \
  --bucket "$TEST_BUCKET" \
  --key "$TEST_KEY" \
  --body /tmp/cloud-adapter-smoke.txt \
  --content-type text/plain \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" \
  --profile "$AWS_PROFILE" \
  --region "$AWS_REGION"

aws s3api head-object \
  --bucket "$TEST_BUCKET" \
  --key "$TEST_KEY" \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" \
  --profile "$AWS_PROFILE" \
  --region "$AWS_REGION"

aws s3api get-object \
  --bucket "$TEST_BUCKET" \
  --key "$TEST_KEY" \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" \
  --profile "$AWS_PROFILE" \
  --region "$AWS_REGION" \
  /tmp/cloud-adapter-smoke.downloaded.txt

cmp /tmp/cloud-adapter-smoke.txt /tmp/cloud-adapter-smoke.downloaded.txt
```

Verify the corresponding object with the target cloud's console or CLI. The AWS-shaped success response and target resource should agree.

## Test the translated error path

Request a key that does not exist:

```bash theme={null}
aws s3api get-object \
  --bucket "$TEST_BUCKET" \
  --key "quickstart/definitely-not-present" \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" \
  --profile "$AWS_PROFILE" \
  --region "$AWS_REGION" \
  /tmp/cloud-adapter-missing.txt
```

Record the command timestamp, AWS error code, and message. A translated not-found response proves more than an empty list because it exercises the service adapter's error mapping. S3 can return permission denied instead when the caller lacks permission to establish that the object is missing. The normal CLI output does not expose arbitrary response headers; use the [Python SDK guide](https://docs.tensor9.com/cloud-adapter-early-access/guides/aws-python-sdk.md) when you need structured, redacted header capture.

## Clean up

Delete only the unique object you created:

```bash theme={null}
aws s3api delete-object \
  --bucket "$TEST_BUCKET" \
  --key "$TEST_KEY" \
  --endpoint-url "$T9_CLOUD_ADAPTER_ENDPOINT" \
  --profile "$AWS_PROFILE" \
  --region "$AWS_REGION"
```

Confirm that `get-object` can no longer read the current object. Versioning or soft delete can retain prior versions, delete markers, or recovery state; use a disposable unversioned target for this walkthrough or remove the created version explicitly. Remove the local temporary files separately.

## Common problems

| Symptom | Check |
| - | - |
| DNS or connection failure | The application-to-adapter network path, TLS name, and listener address. |
| Signature or credential error | Origin-side identity, signing region, local clock, and whether the endpoint accepts the selected authentication mode. |
| Target permission denied | The adapter's backend identity, not the AWS CLI profile. |
| Redirect or virtual-host error | Use the service adapter's documented S3 addressing mode. Path-style requests are easiest for a custom endpoint. |
| Timeout after a write | Inspect target state before retrying. A missing success response does not prove the backend write failed. |
| Command exists but operation is rejected | Check the operation table and target-specific limitations on the S3 service page. |

Use `--debug` only in an isolated environment. Its output can include headers, canonical requests, endpoints, and payload details that should not enter shared logs.

## Expand the test deliberately

After the basic lifecycle passes, add only the features your application uses, such as conditional reads, metadata, pagination, multipart upload, or versioning. Test each against the target-specific behavior in the service catalog before moving application traffic.

See [Debugging Your Adapters](https://docs.tensor9.com/cloud-adapter-early-access/debugging/overview.md), [Testing Your Adapters](https://docs.tensor9.com/cloud-adapter-early-access/local-testing/testing-your-adapters.md), and [Deployment](https://docs.tensor9.com/cloud-adapter-early-access/deployment/overview.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.