mcpField
L
linejs

linejs

github.com/evex-devDevelopment41967 installsUpdated 3w ago
Repository

About linejs

A TypeScript-first client library for the LINE Messenger protocol that speaks LINE’s Thrift binary format directly and supports E2EE and event polling. It is for developers building LINE bots or calling LINE service methods.

Key features

  1. 01Direct Thrift binary protocol support
  2. 02E2EE and event polling
  3. 03Base client and higher-level wrapper
  4. 0430+ services and 130+ methods
  5. 05Profile, messaging, and chat operations

Use cases

  1. 01Build LINE bots
  2. 02Send, receive, and decrypt chat messages
  3. 03Call LINE service RPCs
  4. 04Manage profiles and chats

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/evex-dev/linejs --skill linejs

After installing, type/linejsin Claude Code to confirm it loaded.

Details

From the project README

linejs

@evex/linejs is a TypeScript-first client library for the LINE Messenger protocol. It speaks LINE's Thrift binary wire format directly, supports E2EE, polling for events, and ships hand-written wrappers for the methods CHRLINE-Patch covers.

This skill is a roadmap, not a manual. The library moves fast; rather than freezing details that will rot, this file points the agent at the canonical sources to read on demand.

Install

deno add jsr:@evex/linejs
# Types are also available standalone:
deno add jsr:@evex/linejs-types

Latest release: check JSR — https://jsr.io/@evex/linejs or curl -s https://jsr.io/@evex/linejs/meta.json | jq -r .latest. The skill prompt does not pin a version; pin in user code.

Minimum-viable bot

import { BaseClient } from "@evex/linejs/base";
import { FileStorage } from "@evex/linejs/storage";

const storage = new FileStorage("./storage.json");
const client = new BaseClient({ device: "DESKTOPWIN", storage });

client.on("qrcall",  (url) => console.log("scan:", url));
client.on("pincall", (pin) => console.log("PIN:", pin));
client.on("update:authtoken", (t) => storage.set(".auth", t));

const cached = await storage.get(".auth");
await client.loginProcess.login(
    typeof cached === "string" ? { authToken: cached } : {},
);

for await (const op of client.createPolling().listenTalkEvents()) {
    if (op.type === "RECEIVE_MESSAGE" || op.type === "SEND_MESSAGE") {
        const msg = await client.e2ee.decryptE2EEMessage(op.message);
        if (msg.text === "!ping") {
            await client.talk.sendMessage({
                to: msg.to === client.profile?.mid ? msg.from : msg.to,
                text: "pong!",
                e2ee: !!op.message.chunks,
            });
        }
    }
}

That's the smallest useful bot. For richer surfaces start with the Client wrapper in @evex/linejs (it builds on BaseClient) — it has getMyProfile(), updateMy{DisplayName,StatusMessage,Profile}(), fetchJoinedChats(), getChat(), getUser(), uploadMyProfileImage(), uploadMyProfileBackground() and more.

Roadmap — where to look for what

In all cases, looking at the latest code is best. https://github.com/evex-dev/linejs

You want to …Look at
log in (QR / email)packages/linejs/base/login/mod.ts — uses ForSecure RPCs as of v2.7; legacy createQrCode is server-rejected
send / receive messagespackages/linejs/client/features/message/ and BaseClient.talk.sendMessage
any Thrift RPC LINE supportspackages/linejs/base/service/*/mod.ts — one wrapper per LINE service (30+ services, 130+ methods)
change profile attributesclient.updateMyProfile({...}) / see packages/linejs/client/features/profile.ts
rename / favourite / mute friendsUser.rename() / User.setFavorite() etc. — see packages/linejs/client/features/user/mod.ts
chat BGMChat.getBgm() / Chat.setBgm()
LIFF share / tokenclient.liff.shareMessages(chatMid, [...]) and client.liff.getToken({ liffId, chatMid }) — see packages/linejs/client/features/liff.ts for message builders (text / sticker / image / flex). Lower-level surface at client.liff.service / BaseClient.liff.
VOOM / timeline / Note RESTclient.voomRest({ path, channelToken }) — low-level wrapper around the gw.line.naver.jp/mh/api/v{34,40,52,57}/... gateway. Mint the channel token first: await client.base.channel.issueChannelToken({ channelId: VoomChannelId.TIMELINE }) (note: object arg, not positional string). DESKTOPWIN device cannot do this — use device: "ANDROIDSECONDARY". Once Bearer'd, the gateway moves from 401 to 504 — remaining downstream error tracked in #151.
calendar events on a contactUser.fetchCalendarEvents() — note: server-gated on some client device types (DESKTOPWIN currently lacks it)
approve a PIN login on this deviceclient.base.loginProcess.respondE2EELoginRequest({ verifier, publicKey, encryptedKeyChain, hashKeyChain, errorCode? }) — primary-side counterpart to confirmE2EELogin. Call when this client receives a PIN-login notification from another device the user wants to admit.
upload profile picture / coverclient.uploadMyProfileImage(blob) / client.uploadMyProfileBackground(blob)
Agent I (LINE's chat-tab AI search)@evex/linejs-agent — wraps Yahoo's search-agent SSE backend that LINE Android opens in a WebView. Requires Yahoo session cookies; LINE does not mint them.
E2EE primitivespackages/linejs/base/e2ee/mod.ts — AES-GCM-SIV, ECDH, decrypt encrypted QR identifier, key chain etc.
Thrift schemapackages/types/thrift.ts (data) + packages/types/line_types.ts (TS interfaces). Both auto-synced from LINE Android APK by deno task apk:sync.

When in doubt, read the source under packages/linejs/client/features/ — feature classes are short and read like documentation.

Known constraints

  • LINE 26+ requires the ForSecure QR login (createQrCodeForSecure + qrCodeLoginV2ForSecure). Legacy createQrCode is silently expired by the server. linejs v2.7+ uses ForSecure by default; older versions cannot log in.
  • map<i32, V> encoding was broken on JS-object keys before v2.7 — JS keys are strings, the encoder rejected them. Fixed in v2.7. If you're targeting older linejs, build the map as a NestedArray tuple.
  • E2EE decryption is required for most chat messages — see client.e2ee.decryptE2EEMessage(op.message). Don't read op.message.text directly.
  • Agent I needs Yahoo cookies. The LINE Android app loads the WebView with whatever Yahoo session the user already has; programmatic use requires you to obtain those cookies yourself (Yahoo Japan login → extract cookies). linejs ships the call shape, not the auth.
  • Device type matters for feature gating. DESKTOPWIN lacks several APIs that ANDROID has (e.g. getContactsV3, getContactCalendarEvents). For pure bot work DESKTOPWIN is usually enough; if a method returns API method not capable, switch device type or use a legacy fallback.

Bugs / issues

Report to https://github.com/evex-dev/linejs/issues. Useful context to include:

  • linejs version (deno info jsr:@evex/linejs shows resolved version)
  • device type and LINE app version you're targeting
  • minimal repro: the smallest snippet that reproduces, plus the error from Request internal failed: status=… headers=… body=<…> (v2.7+ includes the HTTP status / headers in the thrown message — very helpful for triage)
  • if QR login–related: which step (createSession, createQrCodeForSecure, checkQrCodeVerified, qrCodeLoginV2ForSecure) and the [login] ForSecure: maxCount=… intervalSec=… nonce=… debug line if it printed.

CHRLINE-Patch-compatible behaviour reports (e.g. "this RPC works in CHRLINE but not linejs") are also useful — name the method and we'll port it.

What this skill deliberately does NOT contain

  • Frozen API signatures — they change. Read the source.
  • A list of every wrapped method — there are 130+, see packages/linejs/base/service/ for the live set.
  • Reverse-engineering details for LINE Android — Join Our Discord.

Comments

Markdown supported