Xurl
X/Twitter через CLI xurl: посты, поиск, личные сообщения, медиа, API v2.
Метаданные навыка
| Источник | Встроенный (установлен по умолчанию) |
| Путь | skills/social-media/xurl |
| Версия | 1.1.1 |
| Автор | xdevplatform + openclaw + Hermes Agent |
| Лицензия | MIT |
| Платформы | linux, macos |
| Теги | twitter, x, social-media, xurl, official-api |
Справочник: полный SKILL.md
Ниже приведено полное определение навыка, которое Hermes загружает при его срабатывании. Именно это агент видит как инструкции, когда навык активен.
xurl — API X (Twitter) через официальный CLI
xurl — официальный CLI платформы для разработчиков X, работающий с X API. Он умеет и сокращённые команды для частых действий, и сырой доступ в стиле curl к любому эндпоинту v2. Все команды возвращают JSON в stdout.
Навык пригодится, чтобы:
- публиковать посты, отвечать, цитировать, удалять
- искать посты и читать ленты/упоминания
- ставить лайки, репостить, добавлять в закладки
- подписываться, отписываться, блокировать, заглушать
- отправлять личные сообщения
- загружать медиа (картинки и видео)
- получать сырой доступ к любому эндпоинту X API v2
- работать с несколькими приложениями и аккаунтами
Этот навык приходит на смену старому навыку xitter (он оборачивал сторонний Python-CLI). xurl поддерживается командой платформы для разработчиков X, работает с OAuth 2.0 PKCE и авто-обновлением токенов, а покрытие API существенно шире.
Безопасность секретов (ОБЯЗАТЕЛЬНО)
Критические правила при работе внутри сессии агента/LLM:
- Никогда не читай, не выводи, не разбирай, не пересказывай, не загружай и не отправляй
~/.xurlв контекст LLM. - Никогда не проси пользователя вставлять учётные данные/токены в чат.
- Пользователь заполняет
~/.xurlсекретами вручную на своей машине. В Docker это должен быть тот~, который видят подпроцессы инструментов Hermes; см. примечание про Docker ниже. - Никогда не советуй и не выполняй команды авторизации с секретами в строке в сессиях агента.
- Никогда не используй
--verbose/-vв сессиях агента — это может раскрыть заголовки авторизации и токены. - Чтобы проверить наличие учётных данных, применяй только:
xurl auth status.
Запрещённые флаги в командах агента (они принимают секреты прямо в строке):
--bearer-token, --consumer-key, --consumer-secret, --access-token, --token-secret, --client-id, --client-secret
Регистрацию учётных данных приложения и их ротацию пользователь делает вручную, вне сессии агента. После регистрации учётных данных пользователь авторизуется командой xurl auth oauth2 — тоже вне сессии агента. Токены сохраняются в ~/.xurl в формате YAML. У каждого приложения свои изолированные токены. Токены OAuth 2.0 обновляются автоматически.
Установка
Выбери ОДИН способ. На Linux проще всего shell-скрипт или go install.
# Shell-скрипт (ставит в ~/.local/bin, без sudo, работает на Linux + macOS)
curl -fsSL https://raw.githubusercontent.com/xdevplatform/xurl/main/install.sh | bash
# Homebrew (macOS)
brew install --cask xdevplatform/tap/xurl
# npm
npm install -g @xdevplatform/xurl
# Go
go install github.com/xdevplatform/xurl@latest
Проверка:
xurl --help
xurl auth status
Если xurl установлен, но auth status не показывает ни приложений, ни токенов, пользователю нужно завершить авторизацию вручную — см. следующий раздел.
Разовая настройка пользователем (пользователь выполняет это вне агента)
Эти шаги пользователь делает сам, НЕ агент, потому что они связаны со вставкой секретов. Направь пользователя к этому блоку; не выполняй его за него.
-
Создай или открой приложение на https://developer.x.com/en/portal/dashboard
-
Укажи redirect URI как
http://localhost:8080/callback -
Скопируй Client ID и Client Secret приложения
-
Зарегистрируй приложение локально (выполняет пользователь):
xurl auth apps add my-app --client-id YOUR_CLIENT_ID --client-secret YOUR_CLIENT_SECRET -
Авторизуйся (укажи
--app, чтобы привязать токен к своему приложению):xurl auth oauth2 --app my-app(Откроется браузер для потока OAuth 2.0 PKCE.)
Если X возвращает ошибку
UsernameNotFoundили 403 при пост-OAuth запросе/2/users/me, передай свой хэндл явно (xurl v1.1.0+):xurl auth oauth2 --app my-app YOUR_USERNAMEТак токен привязывается к твоему хэндлу, а сломанный вызов
/2/users/meпропускается. -
Сделай приложение приложением по умолчанию, чтобы все команды использовали его:
xurl auth default my-app -
Проверь:
xurl auth status xurl whoami
После этого агент может использовать любую команду ниже без дополнительной настройки. Токены OAuth 2.0 обновляются автоматически.
Частая ошибка: если пропустить
--app my-appвxurl auth oauth2, токен OAuth сохранится во встроенный профиль приложенияdefault— у которого нет ни client-id, ни client-secret. Команды будут падать с ошибками авторизации, хотя поток OAuth вроде бы прошёл успешно. Если попался на это, перезапустиxurl auth oauth2 --app my-appиxurl auth default my-app.
Ловушка с HOME в Docker: в официальной раскладке Hermes Docker
/opt/data— этоHERMES_HOME, но подпроцессы инструментов Hermes используют/opt/data/homeкакHOME. Значит, для запускаемых через Hermes командxurlпуть~/.xurlразрешается в/opt/data/home/.xurl, а не в/opt/data/.xurl. Выполни настройку пользователя с тем же HOME:HOME=/opt/data/home xurl auth apps add my-app --client-id YOUR_CLIENT_ID --client-secret YOUR_CLIENT_SECRET HOME=/opt/data/home xurl auth oauth2 --app my-app YOUR_USERNAME HOME=/opt/data/home xurl auth default my-app YOUR_USERNAME HOME=/opt/data/home xurl auth statusЕсли
HOME=/opt/data xurl auth statusсрабатывает, аHOME=/opt/data/home xurl auth statusне показывает ни приложений, ни токенов, то вызовы инструментов Hermes учётных данных не увидят.
Быстрый справочник
| Действие | Команда |
|---|---|
| Опубликовать пост | xurl post "Hello world!" |
| Ответить | xurl reply POST_ID "Nice post!" |
| Процитировать | xurl quote POST_ID "My take" |
| Удалить пост | xurl delete POST_ID |
| Прочитать пост | xurl read POST_ID |
| Искать посты | xurl search "QUERY" -n 10 |
| Кто я | xurl whoami |
| Найти пользователя | xurl user @handle |
| Домашняя лента | xurl timeline -n 20 |
| Упоминания | xurl mentions -n 10 |
| Лайк / Снять лайк | xurl like POST_ID / xurl unlike POST_ID |
| Репост / Отменить | xurl repost POST_ID / xurl unrepost POST_ID |
| Закладка / Убрать | xurl bookmark POST_ID / xurl unbookmark POST_ID |
| Список закладок / лайков | xurl bookmarks -n 10 / xurl likes -n 10 |
| Подписаться / Отписаться | xurl follow @handle / xurl unfollow @handle |
| Подписки / Подписчики | xurl following -n 20 / xurl followers -n 20 |
| Блок / Разблок | xurl block @handle / xurl unblock @handle |
| Заглушить / Снять | xurl mute @handle / xurl unmute @handle |
| Отправить ЛС | xurl dm @handle "message" |
| Список ЛС | xurl dms -n 10 |
| Загрузить медиа | xurl media upload path/to/file.mp4 |
| Статус медиа | xurl media status MEDIA_ID |
| Список приложений | xurl auth apps list |
| Удалить приложение | xurl auth apps remove NAME |
| Задать приложение по умолчанию | xurl auth default APP_NAME [USERNAME] |
| Приложение для одного запроса | xurl --app NAME /2/users/me |
| Статус авторизации | xurl auth status |
Примечания:
POST_IDпринимает и полные URL (например,https://x.com/user/status/1234567890) — xurl извлекает ID сам.- Имена пользователей работают как с ведущим
@, так и без него.
Подробности по командам
Публикация
xurl post "Hello world!"
xurl post "Check this out" --media-id MEDIA_ID
xurl post "Thread pics" --media-id 111 --media-id 222
xurl reply 1234567890 "Great point!"
xurl reply https://x.com/user/status/1234567890 "Agreed!"
xurl reply 1234567890 "Look at this" --media-id MEDIA_ID
xurl quote 1234567890 "Adding my thoughts"
xurl delete 1234567890
Чтение и поиск
xurl read 1234567890
xurl read https://x.com/user/status/1234567890
xurl search "golang"
xurl search "from:elonmusk" -n 20
xurl search "#buildinpublic lang:en" -n 15
Для X Articles используй режим сырого API вместо сокращения read. xurl read
ждёт ID поста или URL поста; не ставь read перед эндпоинтом /2/tweets/....
Запроси поле твита article и забери data.article.plain_text
из ответа JSON:
xurl --app APP_NAME '/2/tweets/2057909493250539891?expansions=author_id,attachments.media_keys,referenced_tweets.id&tweet.fields=created_at,lang,public_metrics,context_annotations,entities,possibly_sensitive,conversation_id,in_reply_to_user_id,referenced_tweets,article'
Пользователи, лента, упоминания
xurl whoami
xurl user elonmusk
xurl user @XDevelopers
xurl timeline -n 25
xurl mentions -n 20
Взаимодействие
xurl like 1234567890
xurl unlike 1234567890
xurl repost 1234567890
xurl unrepost 1234567890
xurl bookmark 1234567890
xurl unbookmark 1234567890
xurl bookmarks -n 20
xurl likes -n 20
Социальный граф
xurl follow @XDevelopers
xurl unfollow @XDevelopers
xurl following -n 50
xurl followers -n 50
# Граф другого пользователя
xurl following --of elonmusk -n 20
xurl followers --of elonmusk -n 20
xurl block @spammer
xurl unblock @spammer
xurl mute @annoying
xurl unmute @annoying
Личные сообщения
xurl dm @someuser "Hey, saw your post!"
xurl dms -n 25
Загрузка медиа
# Автоопределение типа
xurl media upload photo.jpg
xurl media upload video.mp4
# Явный тип/категория
xurl media upload --media-type image/jpeg --category tweet_image photo.jpg
# Видео нужна обработка на сервере — проверь статус (или опрашивай)
xurl media status MEDIA_ID
xurl media status --wait MEDIA_ID
# Полный сценарий
xurl media upload meme.png # возвращает id медиа
xurl post "lol" --media-id MEDIA_ID
Сырой доступ к API
Сокращения покрывают частые операции. Для всего остального используй сырой режим в стиле curl к любому эндпоинту X API v2:
# GET
xurl /2/users/me
# POST с телом JSON
xurl -X POST /2/tweets -d '{"text":"Hello world!"}'
# DELETE / PUT / PATCH
xurl -X DELETE /2/tweets/1234567890
# Свои заголовки
xurl -H "Content-Type: application/json" /2/some/endpoint
# Принудительный стриминг
xurl -s /2/tweets/search/stream
# Полные URL тоже работают
xurl https://api.x.com/2/users/me
Глобальные флаги
| Флаг | Кратко | Описание |
|---|---|---|
--app | Использовать конкретное зарегистрированное приложение (переопределяет умолчание) | |
--auth | Принудительный тип авторизации: oauth1, oauth2 или app | |
--username | -u | Какой аккаунт OAuth2 использовать (если их несколько) |
--verbose | -v | Запрещён в сессиях агента — утекают заголовки авторизации |
--trace | -t | Добавить трассировочный заголовок X-B3-Flags: 1 |
Стриминг
Стриминговые эндпоинты определяются автоматически. Среди известных:
/2/tweets/search/stream/2/tweets/sample/stream/2/tweets/sample10/stream
Принудительно включить стриминг на любом эндпоинте можно флагом -s.
Формат вывода
Все команды возвращают JSON в stdout. Структура повторяет X API v2:
{ "data": { "id": "1234567890", "text": "Hello world!" } }
Ошибки тоже приходят в JSON:
{ "errors": [ { "message": "Not authorized", "code": 403 } ] }
Типовые сценарии
Пост с изображением
xurl media upload photo.jpg
xurl post "Check out this photo!" --media-id MEDIA_ID
Ответ в ветке
xurl read https://x.com/user/status/1234567890
xurl reply 1234567890 "Here are my thoughts..."
Поиск и взаимодействие
xurl search "topic of interest" -n 10
xurl like POST_ID_FROM_RESULTS
xurl reply POST_ID_FROM_RESULTS "Great point!"
Проверка своей активности
xurl whoami
xurl mentions -n 20
xurl timeline -n 20
Несколько приложений (учётные данные настроены вручную заранее)
xurl auth default prod alice # приложение prod, пользователь alice
xurl --app staging /2/users/me # разовый запрос к staging
Обработка ошибок
- Любая ошибка даёт ненулевой код выхода.
- Ошибки API всё равно печатаются в stdout как JSON, так что их можно разобрать.
- Ошибки авторизации → пусть пользователь перезапустит
xurl auth oauth2вне сессии агента. - Команды, которым нужен ID вызывающего пользователя (лайк, репост, закладка, подписка и т. д.), сами получат его через
/2/users/me. Сбой авторизации там проявится как ошибка авторизации.
Рабочий процесс агента
- Проверь требования:
xurl --helpиxurl auth status. - Убедись, что у приложения по умолчанию есть учётные данные. Разбери вывод
auth status. Приложение по умолчанию отмечено знаком▸. Если приложение по умолчанию показываетoauth2: (none), а у другого приложения есть валидный пользователь oauth2, скажи пользователю выполнитьxurl auth default <это-приложение>, чтобы это исправить. Это самая частая ошибка настройки — пользователь добавил приложение со своим именем, но не сделал его приложением по умолчанию, и xurl продолжает обращаться к пустому профилюdefault. - Если авторизации нет вообще, остановись и направь пользователя в раздел «Разовая настройка пользователем» — НЕ пытайся регистрировать приложения или передавать секреты сам.
- Начни с дешёвого чтения (
xurl whoami,xurl user @handle,xurl search ... -n 3), чтобы подтвердить доступность. - Подтверди целевой пост/пользователя и намерение пользователя перед любым действием на запись (пост, ответ, лайк, репост, ЛС, подписка, блок, удаление).
- Используй вывод JSON напрямую — каждый ответ уже структурирован.
- Никогда не вставляй содержимое
~/.xurlобратно в разговор.
Устранение неполадок
| Симптом | Причина | Решение |
|---|---|---|
| Ошибки авторизации после успешного потока OAuth | Токен сохранён в приложение default (без client-id/secret) вместо твоего именованного приложения | xurl auth oauth2 --app my-app, затем xurl auth default my-app |
unauthorized_client во время OAuth | Тип приложения в панели X выставлен как «Native App» | Поменяй на «Web app, automated app or bot» в User Authentication Settings |
UsernameNotFound или 403 на /2/users/me сразу после OAuth | X ненадёжно возвращает имя пользователя из /2/users/me | Перезапусти xurl auth oauth2 --app my-app YOUR_USERNAME (xurl v1.1.0+), чтобы передать хэндл явно |
| 401 на каждом запросе | Токен истёк или не то приложение по умолчанию | Проверь xurl auth status — убедись, что ▸ указывает на приложение с токенами oauth2 |
client-forbidden / client-not-enrolled | Проблема с регистрацией на платформе X | Dashboard → Apps → Manage → переведи на пакет «Pay-per-use» → окружение Production |
CreditsDepleted | Нулевой баланс в X API | Купи кредиты (минимум $5) в Developer Console → Billing |
media processing failed при загрузке картинки | Категория по умолчанию — amplify_video | Добавь --category tweet_image --media-type image/png |
| Два значения «Client Secret» в панели X | Баг интерфейса — первое на самом деле Client ID | Сверься на странице «Keys and tokens»; ID оканчивается на MTpjaQ |
Примечания
- Лимиты запросов: X применяет лимиты на каждый эндпоинт. Код 429 значит «подожди и повтори». У эндпоинтов на запись (пост, ответ, лайк, репост) лимиты жёстче, чем у чтения.
- Скоупы: токены OAuth 2.0 используют широкие скоупы. Код 403 на конкретном действии обычно значит, что токену не хватает скоупа — пусть пользователь перезапустит
xurl auth oauth2. - Обновление токенов: токены OAuth 2.0 обновляются автоматически. Делать ничего не нужно.
- Несколько приложений: у каждого приложения свои изолированные учётные данные/токены. Переключайся через
xurl auth defaultили--app. - Несколько аккаунтов на приложение: выбирай через
-u / --usernameили задай умолчание командойxurl auth default APP USER. - Хранение токенов:
~/.xurl— это YAML. В Docker используй HOME подпроцесса Hermes (/opt/data/homeв официальном образе), чтобы токены легли в/opt/data/home/.xurl. Никогда не читай этот файл и не отправляй его в контекст LLM. - Стоимость: доступ к X API для сколько-нибудь серьёзного использования обычно платный. Многие сбои — это проблемы тарифа/прав, а не кода.
Атрибуция
- Исходный CLI: https://github.com/xdevplatform/xurl (команда платформы для разработчиков X, Chris Park и др.)
- Исходный навык агента: https://github.com/openclaw/openclaw/blob/main/skills/xurl/SKILL.md
- Адаптация под Hermes: переформатировано под соглашения навыков Hermes; защитные правила безопасности сохранены дословно.