About bitrix-pull
bitrix-pull is a development skill for sending real-time UI updates in Bitrix applications. It documents PHP event publishing, watch tags, JavaScript subscriptions, and mobile push, while distinguishing notifications from durable background jobs.
Key features
- 01Publish events to users or channels
- 02Notify watchers through CPullWatch tags
- 03Subscribe to commands in JavaScript
- 04Send mobile push notifications
- 05Handle queued delivery and CLI workers
Use cases
- 01Refresh a UI after an item changes
- 02Notify users watching a record
- 03Send mobile badge updates
- 04Trigger client updates from a worker
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ bxmaximum/ bitrix-framework-skills --skill bitrix-pullAfter installing, type/bitrix-pullin Claude Code to confirm it loaded.
Details
From the project READMERealtime Pull (pull)
Baseline: main 23.0+ · Verified: pull 26.100.0, main 26.800.0
pull delivers short commands to browsers and the mobile app through the push server. Needs a configured server (CPullOptions::GetQueueServerStatus()); mobile push also CPullOptions::GetPushStatus().
| Mechanism | Use for |
|---|---|
| Pull | Instant UI signal: "row 42 changed", counters |
Messenger / agents (bitrix-background-jobs) | Durable work with retries; emit Pull from the worker when the UI must refresh |
Send from PHP
\Bitrix\Main\Loader::includeModule('pull');
$ok = \Bitrix\Pull\Event::add([$userId, $otherUserId], [
'module_id' => 'vendor.module', // lower-cased by the kernel
'command' => 'itemUpdated',
'params' => ['id' => $itemId], // IDs and flags only; load data via AJAX afterwards
// 'expiry' => 86400, // seconds, default
]);
if (!$ok) {
$error = \Bitrix\Pull\Event::getLastError();
}
- Recipients: user ID(s), 32-char channel IDs or
Bitrix\Pull\Model\Channel; 3rd arg\CPullChannel::TYPE_PRIVATE(default) /TYPE_SHARED. - Per-user params:
'user_params' => [$userId => ['unread' => 3]](merged intoparamsfor that user),'dictionary' => [...](merged for all). Result is reliable since pull 26.100; before it a falsy result for these keys is not a failure — checkgetLastError(). - Invalid UTF-8 anywhere in the payload →
false(EVENT_BAD_ENCODING). - Delivery is queued and sent by a background job at the end of the hit. Long-running CLI worker: call
\Bitrix\Pull\Event::send()right afteradd().
Tags (CPullWatch)
\CPullWatch::Add($userId, 'VENDOR_ITEM_' . $itemId); // when rendering the page
\CPullWatch::AddToStack('VENDOR_ITEM_' . $itemId, [ // later, to all watchers
'module_id' => 'vendor.module',
'command' => 'itemUpdated',
'params' => ['id' => $itemId],
]);
Add()is written atOnAfterEpilogfor the current user; for another user or outside a web hit pass 3rd argtrue(immediate).- A watch lives ~30 min; the page keeps it alive with
BX.PULL.extendWatch(tag). AddToStack()accepts an array of tags andskip_users.
Subscribe in JS
Add pull.client to rel (import { PULL } from 'pull.client', global BX.PULL). moduleId must be lower-case.
// With command: (params, extra, command, info)
const off = BX.PULL.subscribe({
moduleId: 'vendor.module',
command: 'itemUpdated',
callback: (params, extra, command) => reload(params.id),
});
// Without command: one object for every module command
BX.PULL.subscribe({
moduleId: 'vendor.module',
callback: (data) => { /* data.command, data.params, data.extra */ },
});
BX.PULL.extendWatch('VENDOR_ITEM_' + itemId);
off(); // unsubscribe
- Handler object:
BX.PULL.attachCommandHandler({ getModuleId: () => 'vendor.module', handleItemUpdated(params, extra) {} })— methodhandle+ command with capital first letter, orgetMap(). - Vue:
this.$Bitrix.PullClient.get().subscribe(...)inmounted, call the returned function inunmounted(bitrix-vue). - Never use pull's global
protobuf: since pull 26.100 it is a minimal build (load,parse,Root,Typegone). Bundle your own protobufjs without assigningglobalThis.protobuf— pull readsglobalThis.protobuf.roots['push-server'].
Mobile push
\Bitrix\Pull\Push::add($users, ['module_id' => 'vendor.module', 'push' => ['message' => 'Text', 'params' => [...]]]) — kernel entry point for push (drops command/params); or add push / pushParamsCallback to Event::add() to send both. CPullStack is legacy.
Badge refresh: Push::add($userId, ['module_id' => 'pull', 'push' => ['badge' => 'Y']]). CPushManager::sendBadges() was removed in pull 26.0 (fatal) and MobileCounter::send() is a no-op; the Push::add() call works on all versions.
Checklist
-
module_id/commandidentical (lower-case module) in PHP and JS. - Payload small, UTF-8; heavy data fetched on demand.
- Tags:
CPullWatch::Addon render +extendWatchin JS. - Subscriptions removed on unmount / destroy.
- Pull never used as a job queue.