Parse and serialize the IC (Intelligence Collective) text format — a tiny, human-readable format for recording associations between things.
Isomorphic (browser + Node), TypeScript, dual ESM/CJS, zero runtime dependencies in the core.
The broader IC vision and format documentation live at ic-caves/ic-docs. This repo is just the JavaScript/TypeScript library.
npm install @owise1/ic-js_0x04916228 # perspective id (a line starting with `_`); bare `_` = no perspective
things i love # a "parent" (top-level line, no prefix)
+my family # `+` child → an affirmed connection to the parent(s) above
-doomscrolling # `-` child → a negated connection
+warmth,1620150217594 # optional ,timestamp (ms) suffix
doomscrolling # a new parent block
+huckster
// lines starting with // are comments
Consecutive top-level lines are all parents; each following +/- line creates one connection per accumulated parent (multi-parent). In memory a connection is:
interface Connection {
parent: string
child: string
affirm: boolean // + => true, - => false
perspective?: string // the `_` id
time?: number // ms, from the ,timestamp suffix
source?: string // url a connection was resolved from
}import { parse, stringify, resolve, isIcUrl } from '@owise1/ic-js'
// text -> connections (pure, synchronous)
const doc = parse('animals\n+cat\n-dog')
// [{ parent: 'animals', child: 'cat', affirm: true },
// { parent: 'animals', child: 'dog', affirm: false }]
// connections -> text (pure; default `pure: true` sorts deterministically and drops timestamps)
stringify(doc) // "_\nanimals\n-dog\n+cat"
stringify(doc, { pure: false }) // preserves insertion order and ,timestampsAn IC document can reference other IC files by URL. resolve parses the input and recursively fetches any referenced .ic URLs (appearing as a parent or child), merging their connections — cycle-safe and depth-limited. The fetcher is pluggable (defaults to the global fetch).
import { resolve } from '@owise1/ic-js'
const all = await resolve(icText, {
fetch: (url) => fetch(url).then((r) => r.text()), // optional; this is the default
depth: -1, // -1 = unlimited (default); 0/1 = don't follow refs
onError: (url, err) => {/* optional; failures are skipped silently by default */},
})import { calculateCID } from '@owise1/ic-js/cid'
(await calculateCID('hello')).toString()
// 'bafkreibm6jg3ux5qumhcn2b3flc3tyu6dmlb4xa7u5bf44yegnrjhc4yeq'calculateCID (CIDv1 / raw / sha-256) is exposed on the @owise1/ic-js/cid subpath so its only dependency, multiformats, stays out of the core bundle.
MIT