# Linejs

> Helps a coding agent build LINE bots / clients with the `@evex/linejs` library — JSR package, Deno-first, runs on Node/Bun too. Use when the user asks to write LINE bots, automate LINE accounts, work with LINE Thrift APIs, or wrap the AI "Agent I" feature. Use when this capability is needed.

- Skill: `tomevault-io/linejs` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/linejs`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/linejs/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/linejs

---


# 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

```sh
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

```ts
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 messages | `packages/linejs/client/features/message/` and `BaseClient.talk.sendMessage` |
| any Thrift RPC LINE supports | `packages/linejs/base/service/*/mod.ts` — one wrapper per LINE service (30+ services, 130+ methods) |
| change profile attributes | `client.updateMyProfile({...})` / see `packages/linejs/client/features/profile.ts` |
| rename / favourite / mute friends | `User.rename()` / `User.setFavorite()` etc. — see `packages/linejs/client/features/user/mod.ts` |
| chat BGM | `Chat.getBgm()` / `Chat.setBgm()` |
| LIFF share / token | `client.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 REST | `client.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 contact | `User.fetchCalendarEvents()` — note: server-gated on some client device types (DESKTOPWIN currently lacks it) |
| approve a PIN login on this device | `client.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 / cover | `client.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 primitives | `packages/linejs/base/e2ee/mod.ts` — AES-GCM-SIV, ECDH, decrypt encrypted QR identifier, key chain etc. |
| Thrift schema | `packages/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 — those live in `EdamAme-x/android-reverse` (private). The linejs side is what's published.

---
> Source: [evex-dev/linejs](https://github.com/evex-dev/linejs) — distributed by [TomeVault](https://tomevault.io).
<!-- tomevault:4.0:skill_md:2026-06-23 -->

