Skip to Content
CLIProgrammatic use

Programmatic use

@joinmonolith/cli is also a library. The same fingerprint and perceptual hash functions the monolith binary uses are exported from the package root.

Install

bun add @joinmonolith/cli # or npm install @joinmonolith/cli

Fingerprints

import { fingerprintFile, fingerprintBytes, fingerprintStream } from '@joinmonolith/cli' // From a path const fp1 = await fingerprintFile('./image.png') // → "0x20a7b5ff…" // From an in-memory buffer const fp2 = fingerprintBytes(new Uint8Array([1, 2, 3])) // From any ReadableStream / AsyncIterable<Uint8Array> const res = await fetch('https://example.com/track.mp3') const fp3 = await fingerprintStream(res.body!)

All three return the same 0x-prefixed lowercase-hex SHA-256 string the API stores on an Artifact.

Perceptual hashes

import { detectKind, phashImage, chromaprintAudio } from '@joinmonolith/cli' import type { FileKind, KindInfo } from '@joinmonolith/cli' const bytes = new Uint8Array(await Bun.file('./image.png').bytes()) const info: KindInfo = await detectKind(bytes) if (info.kind === 'image') { const phash = await phashImage(bytes) // → "918b8b916e4aee91" } if (info.kind === 'audio') { const { fingerprint, sampleRate, channels, durationSec } = await chromaprintAudio(bytes) }

detectKind sniffs magic bytes and returns { kind: 'image' | 'audio' | 'other', mime?, ext? }.

Perceptual hashes are deterministic across the CLI, the library, and the API. The same bytes produce the same phash / chromaprint everywhere.

Build an Artifact payload

import { fingerprintFile } from '@joinmonolith/cli' import { stat } from 'node:fs/promises' async function artifactPayload(path: string, markId: string) { const [fingerprint, st] = await Promise.all([ fingerprintFile(path), stat(path) ]) return { markId, fingerprint, filename: path.split('/').pop()!, size: st.size } } const body = await artifactPayload('./my-art.png', process.env.MARK_ID!) await fetch('https://api.joinmonolith.com/api/v1/artifacts', { method: 'POST', headers: { Authorization: `Bearer ${process.env.MONOLITH_TOKEN}`, 'Content-Type': 'application/json' }, body: JSON.stringify(body) })

Types

type FileKind = 'image' | 'audio' | 'other' interface KindInfo { kind: FileKind mime?: string ext?: string }
Last updated on