> For the complete documentation index, see [llms.txt](https://docs.appmixer.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.appmixer.com/build-connectors-with-a-coding-agent/daily.md).

# Day-to-Day Work

A reference page, read out of order. Nothing here is a sequence, and none of it is needed to ship your first connector — it is what the second one, and the hundredth, look like.

## Adding a component to an existing connector

Much shorter than chapter 2, because the expensive parts already exist: authentication works, the manifests are established, the quota rules are written, and the shared helpers are there to reuse. What is left is the component itself.

The loop, in order:

```bash
appmixer connector validate <connector>          # offline, source shape
appmixer test component <dir> -i '{"in":{}}'     # live, one component
appmixer connector verify <connector>            # live, schema conformance
appmixer e2e import ... && appmixer e2e run ...  # live, as a flow
```

Then the review skill, then publish. Two version bumps, not one: **`component.json` for the component you changed**, because that version is what flows resolve against and what a changelog can point at, **and `bundle.json` for the connector**. [Shipping Changes](/build-connectors-with-a-coding-agent/shipping-changes.md) explains what each one does.

If the new component shares a request pattern with existing ones, say so in the brief. An agent left to itself will happily write a fifth copy of the same auth header block.

## Changing the auth type of a published connector

Pick the auth type once, before the first prompt. This section is for when it has to change later — the service adds OAuth, or a connector on an API key should stop making every user fetch a key. It breaks every existing user of the connector, so it needs more care than an ordinary change.

### The prompt

> Switch this connector from the private token to OAuth 2.0. Eventbrite supports it with the API key and client secret from the same key I already have. Then authenticate again and re-run the component tests to prove the connector still works on the new account.

What carries weight: the **target auth type**, **where the OAuth credentials come from** (the same app registration), and **what counts as done** — a passing run on the new credential, not a rewritten `auth.js`. Expect the agent to rewrite `auth.js`, update every place that reads the credential, bump the major version, and hand back the redirect URI registration and the login. It will leave the instance alone unless you ask.

### What changes in `auth.js`

Under `apiKey`, the module describes the fields a user fills in (the `auth` map) and the functions that use them:

```javascript
module.exports = {
    type: 'apiKey',
    definition: {
        tokenType: 'authentication-token',
        auth: {
            apiKey: {
                type: 'text',
                name: 'Private Token',
                tooltip: 'Account Settings > Developer Links > API Keys ...'
            }
        },
        accountNameFromProfileInfo: 'name',
        requestProfileInfo: async (context) => { /* uses context.apiKey */ },
        validate: async (context) => { /* uses context.apiKey */ }
    }
};
```

Under `oauth2` there is no field map; the module describes the endpoints of the exchange:

```javascript
module.exports = {
    type: 'oauth2',
    definition: () => {
        return {
            // Eventbrite has no OAuth scopes: the token carries the full
            // permissions of the user who granted it.
            scope: [],
            authUrl: 'https://www.eventbrite.com/oauth/authorize',
            requestAccessToken: 'https://www.eventbrite.com/oauth/token',
            requestProfileInfo: `${API_BASE_URL}/users/me/`,
            accountNameFromProfileInfo: 'name',
            validateAccessToken: `${API_BASE_URL}/users/me/`
        };
    }
};
```

`definition` may be an object or a function for any type ([Authentication](/building-connectors/authentication.md)); what changes is what it contains.

### Sweep for the old credential

Every place that reads the credential changes — `context.auth.accessToken` instead of `context.auth.apiKey` — including shared helpers and cache-key builders, not only the components. Ask the agent to search the whole connector for the old property; one that is missed fails at run time with an error that does not mention auth.

### Run the negative control

A passing test after the switch is not yet evidence. The old credential is usually still in the local store, and some services — Eventbrite among them — return **the same string** as the private token and the OAuth access token, so the old path can pass on its own.

**Remove the old credential, then re-run.** Only a pass without it proves the components read the new one. Ask for this explicitly if the agent does not offer it.

### It is a major version — of the bundle

Every existing account stops matching the connector:

```
1.1.1  →  2.0.0
```

with a changelog line that says users must connect again. That major belongs to `bundle.json`. It is a signal to your users, and it breaks nothing on its own.

{% hint style="warning" %}
**Do not carry that major into the components.** Bump each changed `component.json` as usual — a patch or a minor, which running flows pick up by themselves. A component major stops every flow that uses the old one, silently, and each of them then needs its version updated and a restart ([Shipping Changes](/build-connectors-with-a-coding-agent/shipping-changes.md#flows-follow-the-version)).
{% endhint %}

### Put it on the instance, then re-authorize

The instance needs the OAuth app's credentials and the new redirect URI first — see [On the Instance](/build-connectors-with-a-coding-agent/on-the-instance.md). Existing accounts then fail `appmixer account test`, and `appmixer e2e import` refuses to bind them:

```
[ERROR]: account <id> failed its validity test (expired/revoked token?)
         — re-authenticate it.
```

Authorize them again rather than deleting them. Re-authorizing updates an account in place — same id, same name — so its flows stay bound.

## Working with several instances

One alias per instance, set up once:

```bash
appmixer login you@example.com dev
appmixer login you@example.com prod

appmixer alias              # list them; * marks the ones with a session
appmixer alias prod         # switch — prints "Logged in as <email>"
```

Switching moves the API URL and the session together, so there is no state where you are pointed at one instance holding another one's token. The bare listing shows *where*; naming an alias shows *who*. Before anything destructive — a publish, a `remove` — run the named form and read the email back.

To change **user** on an instance, log out first. In CLI 2.6.0 `appmixer login` with a different email on an alias that already has a session answers `Already logged in as <the old email>` and keeps that session; only the alias moves. Later versions switch the user.

## Driving the CLI from scripts

The CLI is built to be called by something that is not a human, which is precisely why an agent can use it at all:

* **`--json`** puts machine-readable output on **stdout**, and only that.
* **Diagnostics go to stderr**, so a pipe stays clean.
* **Exit codes are stable and meaningful**:

| Command              | `0`                         | `1`                                             | `2`                              |
| -------------------- | --------------------------- | ----------------------------------------------- | -------------------------------- |
| `connector validate` | clean, or within thresholds | regression or strict failure                    | —                                |
| `connector verify`   | no fail/error findings      | fail or error findings                          | —                                |
| `e2e import`         | all imported and clean      | validation, upload, account or variable failure | —                                |
| `e2e run`            | passed                      | failed or timed out                             | fix brief emitted (`--fix` only) |
| `e2e results`        | no failed records           | failed records exist                            | —                                |

Anything you can express as "run this, check the code, act on the JSON" you can automate.

## Continuous integration

Skip the interactive login entirely:

```bash
export APPMIXER_API_URL=<your API Base URL>
export APPMIXER_TOKEN=<token>
export APPMIXER_WORKSPACE="<workspace name or id>"   # optional, pins every command
```

`APPMIXER_API_URL` replaces `appmixer url` and `APPMIXER_TOKEN` replaces `appmixer login`. Both override whatever is stored locally, which is what makes them safe in CI and worth being careful with on a workstation.

For a settings file rather than exports, `connector validate`, `connector verify` and the `e2e` commands read `~/.config/appmixer-skills/env`. The rest of the CLI — `login`, `publish` and friends — ignores it. `APPMIXER_ENV` **replaces** that file with the path you give it rather than adding to it. Values already exported always win.

**What is actually worth running in CI** is the pair that needs no credentials:

```bash
appmixer connector validate <connector>
appmixer connector verify <connector> --offline
```

The first checks your source. The second re-checks your declared schemas against the sanitized samples committed by `--record`, so schema drift is caught on every pull request without a token anywhere near the pipeline. See [Testing in Three Layers](/build-connectors-with-a-coding-agent/testing.md).

{% hint style="warning" %}
**Check `verify --offline` exits 0 before you make it a gate.** A schema that declares no `required` makes verify treat every declared field as required, so one optional field that did not appear reports `✗` and the run exits `1`. Declare `required`, and export `ITEM_SCHEMA` from components with a dynamic out port ([Testing in Three Layers](/build-connectors-with-a-coding-agent/testing.md)).
{% endhint %}

## Reading a connector that is already published

The catalogue is the best documentation there is for connector patterns, and you can pull any of it down:

```bash
appmixer component ls <vendor>.<connector>              # what is on the instance
appmixer download <vendor>.<connector>.<module>.<Component> -o /tmp/c.zip
appmixer download <vendor>.<connector>/auth.js          # a single file
```

Useful for learning, and useful for the other thing: confirming what an instance is *actually* running, as opposed to what your working copy says it should be.

## Keeping up

```bash
appmixer --version
```

For the skills, ask your agent, or check the plugin listing in your editor. A version mismatch between the CLI, the skills and the instance produces symptoms that look like bugs in all three, so check it before you debug anything unusual — the matrix is `docs/compatibility.md` in the [appmixer-skills](https://github.com/Appmixer-ai/appmixer-skills) repository.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.appmixer.com/build-connectors-with-a-coding-agent/daily.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
