Pine AI SDK for JavaScript/TypeScript. Let Pine AI handle your digital chores.
npm install pine-assistant # SDK
npm install -g pine-assistant # CLI (global)import { PineAI } from 'pine-assistant';
const client = new PineAI({ accessToken: '...', userId: '...' });
await client.connect();
const session = await client.sessions.create();
await client.joinSession(session.id);
for await (const event of client.chat(session.id, 'Help me negotiate my Comcast bill')) {
console.log(event.type, event.data);
}
client.leaveSession(session.id);
client.disconnect();pine auth login # Email verification
pine chat # Interactive chat (creates session)
pine send "Negotiate my Comcast bill" # One-shot message
pine sessions list # List sessions
pine task start <session-id> # Start task (Pro subscription)
pine task watch <session-id> # Watch task progressconst client = new PineAI();
const { request_token } = await client.auth.requestCode('user@example.com');
// User receives email with code
const { access_token, id } = await client.auth.verifyCode('user@example.com', '123456', request_token);
await client.connect(access_token, id);Pine AI behaves like a human assistant. After you send a message, it sends:
- A quick acknowledgment ("Got it!")
- Work logs (researching, planning)
- The substantive response (form, text, or task_ready)
Don't respond to acknowledgments — only respond to forms (with JSON), specific questions, and task lifecycle events. If you respond to every message, you'll create an infinite loop. See the SKILL.md for the full behavioral rules.
// List all sessions
const { sessions } = await client.sessions.list({ limit: 20 });
// Continue an existing session
await client.joinSession(existingSessionId);
const history = await client.getHistory(existingSessionId);
for await (const event of client.chat(existingSessionId, 'What is the status?')) { ... }// Upload a document (bills, screenshots for dispute tasks)
const [attachment] = await client.sessions.uploadAttachment(fileBlob, 'bill.pdf');
// Include in message via sendMessage with attachments optionText streaming (session:text_part) is buffered internally. You receive a single
merged text event when the stream completes (final: true), not individual chunks.
Work log parts are debounced (3s silence). Non-streaming events dispatch immediately.
Pro subscription recommended for programmatic use. For non-subscribers,
session:reward events include a web URL for browser payment:
import { PineAI } from 'pine-assistant';
// After receiving session:reward event:
console.log(`Pay at: ${PineAI.sessionUrl(sessionId)}`);MIT