You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
All user-visible bugs and enhancements should be recorded here.
4
+
5
+
## Unreleased
6
+
7
+
Last updated: 2026-04-19 23:48:20 CEST
8
+
9
+
### Fixed
10
+
11
+
-[2026-04-19 23:08:51 CEST] OAuth2 callback listeners now bind to the host and port derived from the effective redirect URI instead of always listening on `127.0.0.1:8080`. For `localhost`, `xurl` now listens on both `127.0.0.1` and `::1`, which fixes browser-dependent loopback resolution failures while still supporting non-default callback paths.
12
+
-[2026-04-19 23:08:51 CEST] The OAuth2 listener now starts listening before the browser opens, which removes a race where the browser could reach the callback URL before the local server was ready.
13
+
-[2026-04-19 23:08:51 CEST] OAuth2 token refresh no longer depends on `/2/users/me` succeeding. If username discovery fails, `xurl` keeps the refreshed token instead of failing the request.
14
+
-[2026-04-19 23:08:51 CEST] Shortcut commands that need the current user ID now fall back to `--username` lookups when `/2/users/me` is unavailable.
15
+
-[2026-04-19 23:08:51 CEST]`GetOAuth2Header` now consistently returns a `Bearer` header even when it has to trigger a fresh OAuth2 flow.
16
+
17
+
### Enhanced
18
+
19
+
-[2026-04-19 23:08:51 CEST] OAuth2 tokens can now be retained without a discovered username label when X’s `/2/users/me` lookup is unavailable. Status output makes that state visible as `(unknown user)` instead of silently dropping the token.
20
+
-[2026-04-19 23:08:51 CEST] Repo documentation now describes the effective redirect URI as the source of callback host, port, and path, calls out explicit username authentication as the safer fallback when username discovery is unreliable, and documents the new stored `redirect_uri` behavior.
21
+
-[2026-04-19 23:08:51 CEST] Apps can now store a per-app `redirect_uri` in `~/.xurl`, `REDIRECT_URI` from the environment still takes precedence, and `xurl auth apps redirect-uri get/set` plus `auth apps update --redirect-uri` make that configuration visible and editable from the CLI.
22
+
-[2026-04-19 23:48:20 CEST] Documentation now records the confirmed X platform enrollment requirement behind `client-forbidden` / `client-not-enrolled` read failures: moving the app to the `Pay-per-use` package and the `Production` environment fixed live `/2/*` reads after OAuth had already succeeded.
> **Legacy / env-var flow:** You can also set `CLIENT_ID` and `CLIENT_SECRET` as environment variables. They'll be auto-saved into the active app on first use.
67
+
>
68
+
> `REDIRECT_URI` now resolves in this order: `REDIRECT_URI` environment variable, then the app's stored `redirect_uri` in `~/.xurl`, then the built-in default `http://localhost:8080/callback`.
61
69
62
70
#### OAuth 2.0 User-Context
63
71
**Note:** For OAuth 2.0 authentication, you must specify the redirect URI in the [X API developer portal](https://developer.x.com/en/portal/dashboard).
64
72
65
73
1. Create an app at the [X API developer portal](https://developer.x.com/en/portal/dashboard).
66
-
2. Go to authentication settings and set the redirect URI to `http://localhost:8080/callback`.
74
+
2. Go to authentication settings and set the redirect URI to the same value that `xurl` will use through `REDIRECT_URI`.
75
+
The default is `http://localhost:8080/callback`, and `xurl` derives the callback host, port, and path from the effective redirect URI. The effective value is resolved from `REDIRECT_URI`, then the app's stored `redirect_uri`, then the built-in default. When you use `localhost`, `xurl` listens on both `127.0.0.1` and `::1` so browser loopback resolution does not break the callback.
If X returns a `client-forbidden` / `client-not-enrolled` error even though auth completed successfully, check the app’s package and environment in the X developer console. On current X platform setup, the working fix was:
88
+
89
+
1. Go to `Apps` -> `Manage apps`
90
+
2. Open the app
91
+
3. Use `Move to package`
92
+
4. Choose `Pay-per-use`
93
+
5. Move the app to the `Production` environment
94
+
95
+
Without that enrollment step, `xurl whoami` and other `/2/*` reads can fail even when the OAuth callback and tokens are valid.
96
+
97
+
If X does not return your username reliably through `/2/users/me`, authenticate with an explicit handle instead:
98
+
99
+
```bash
100
+
xurl auth oauth2 YOUR_USERNAME
101
+
```
102
+
103
+
That keeps the OAuth2 token associated with the expected username and also gives shortcut commands a fallback when `/2/users/me` is unavailable.
`REDIRECT_URI` from the environment still overrides the stored app value at runtime, so `auth apps update --redirect-uri` is best for your default per-app callback while env vars remain the temporary override path.
129
+
130
+
View the effective and stored redirect URI for an app:
131
+
```bash
132
+
xurl auth apps redirect-uri get my-app
133
+
```
134
+
135
+
Set the stored redirect URI for an app:
136
+
```bash
137
+
xurl auth apps redirect-uri set my-app http://localhost:8080/callback
98
138
```
99
139
100
140
Remove an app:
@@ -124,20 +164,28 @@ View authentication status across all apps:
124
164
xurl auth status
125
165
```
126
166
167
+
This output shows the effective redirect URI for each app and, when `REDIRECT_URI` is set in the environment, also shows the stored app value separately so precedence is visible.
If OAuth succeeds but reads like `xurl whoami` fail with an error body containing `client-forbidden` or `client-not-enrolled`, the current X platform fix is to move the app into the `Pay-per-use` package and use the `Production` environment in the developer console. This is an X platform enrollment issue, not a local callback-listener issue in `xurl`.
188
+
141
189
`▸` on the left = default app. `▸` next to a user = default user.
Copy file name to clipboardExpand all lines: SKILL.md
+12-4Lines changed: 12 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -40,13 +40,15 @@ For multiple pre-configured apps, switch between them:
40
40
xurl auth default prod-app # set default app
41
41
xurl auth default prod-app alice # set default app + user
42
42
xurl --app dev-app /2/users/me # one-off override
43
+
xurl auth apps redirect-uri get prod-app
44
+
xurl auth apps redirect-uri set prod-app http://localhost:8080/callback
43
45
```
44
46
45
47
### Other auth methods
46
48
47
49
Examples with inline secret flags are intentionally omitted. If OAuth1 or app-only auth is needed, the user must run those commands manually outside agent/LLM context.
48
50
49
-
Tokens are persisted to `~/.xurl` in YAML format. Each app has its own isolated tokens. Do not read this file through the agent/LLM. Once authenticated, every command below will auto‑attach the right `Authorization` header.
51
+
Tokens are persisted to `~/.xurl` in YAML format. Each app has its own isolated tokens and may also store a `redirect_uri`. `REDIRECT_URI` in the environment still takes precedence over the stored app value. Do not read this file through the agent/LLM. Once authenticated, every command below will auto‑attach the right `Authorization` header.
50
52
51
53
---
52
54
@@ -87,7 +89,9 @@ Tokens are persisted to `~/.xurl` in YAML format. Each app has its own isolated
87
89
|**App Management**||
88
90
| Register app | Manual, outside agent (do not pass secrets via agent) |
89
91
| List apps |`xurl auth apps list`|
90
-
| Update app creds | Manual, outside agent (do not pass secrets via agent) |
92
+
| Update app config | Manual, outside agent (do not pass secrets via agent) |
93
+
| View app redirect URI |`xurl auth apps redirect-uri get [NAME]`|
94
+
| Set app redirect URI |`xurl auth apps redirect-uri set NAME URI`|
91
95
| Remove app |`xurl auth apps remove NAME`|
92
96
| Set default (interactive) |`xurl auth default`|
93
97
| Set default (command) |`xurl auth default APP_NAME [USERNAME]`|
- API errors are printed as JSON to stdout (so you can still parse them).
384
388
- Auth errors suggest re‑running `xurl auth oauth2` or checking your tokens.
385
-
- If a command requires your user ID (like, repost, bookmark, follow, etc.), xurl will automatically fetch it via `/2/users/me`. If that fails, you'll see an auth error.
389
+
- If a command requires your user ID (like, repost, bookmark, follow, etc.), xurl will automatically fetch it via `/2/users/me`. When that endpoint is unreliable, use `--username USERNAME` or authenticate with `xurl auth oauth2 USERNAME` so xurl can fall back to username lookup.
390
+
- If X returns `client-forbidden` / `client-not-enrolled` after successful auth, check the app’s X developer-console package and environment. In current testing, moving the app to `Pay-per-use` and `Production` fixed `/2/*` read failures without changing local `xurl` auth data.
-**Rate limits:** The X API enforces rate limits per endpoint. If you get a 429 error, wait and retry. Write endpoints (post, reply, like, repost) have stricter limits than read endpoints.
392
397
-**Scopes:** OAuth 2.0 tokens are requested with broad scopes. If you get a 403 on a specific action, your token may lack the required scope — re‑run `xurl auth oauth2` to get a fresh token.
393
398
-**Token refresh:** OAuth 2.0 tokens auto‑refresh when expired. No manual intervention needed.
394
-
-**Multiple apps:** Each app has its own isolated credentials and tokens. Configure credentials manually outside agent/LLM context, then switch with `xurl auth default` or `--app`.
399
+
-**Multiple apps:** Each app has its own isolated credentials, tokens, and optional stored `redirect_uri`. Configure credentials manually outside agent/LLM context, then switch with `xurl auth default` or `--app`.
400
+
-**Redirect URI precedence:** The effective redirect URI resolves from `REDIRECT_URI` in the environment first, then the app's stored `redirect_uri` in `~/.xurl`, then the built-in default.
401
+
-**Redirect URI management:** Use `xurl auth apps redirect-uri get [NAME]`, `xurl auth apps redirect-uri set NAME URI`, or `xurl auth apps update NAME --redirect-uri URI` to inspect and manage the stored per-app callback value.
402
+
-**X platform enrollment:** A successful OAuth callback does not guarantee `/2/*` reads will work. If you see `client-not-enrolled`, verify the app is in the correct X package/environment. Current confirmed fix: `Apps` -> `Manage apps` -> `Move to package` -> choose `Pay-per-use`, then move the app to `Production`.
395
403
-**Multiple accounts:** You can authenticate multiple OAuth 2.0 accounts per app and switch between them with `--username` / `-u` or set a default with `xurl auth default APP USER`.
396
404
-**Default user:** When no `-u` flag is given, xurl uses the default user for the active app (set via `xurl auth default`). If no default user is set, it uses the first available token.
397
405
-**Token storage:**`~/.xurl` is YAML. Each app stores its own credentials and tokens. Never read or send this file to LLM context.
0 commit comments