Core concepts
CID, IPFS, Kubo, encryption, pinning, and IPNS — what Meshkit builds on.
IPFS and content addressing
IPFS stores files by their CID (Content Identifier) — a cryptographic hash of the content itself. The same bytes always produce the same CID, so retrieval is verifiable by design.
Kubo
Kubo is the reference Go implementation of IPFS. Meshkit communicates with Kubo over its HTTP RPC API (default: http://127.0.0.1:5001). You must have Kubo installed and running, or let Meshkit start it for you with localNode: true.
Client-side encryption
IPFS content addressing does not hide bytes. Anyone who can fetch a CID can read whatever was uploaded. Meshkit can encrypt first, so the CID names an EMSH ciphertext blob instead of the file.
Alice uploads with a password. She sends Bob the CID (this can travel in the open) and the password (this stays off the network). Bob calls retrieve with that password and gets the original file back. A download without the password returns the encrypted payload.
The CID is still a hash of the stored bytes. Those bytes are the ciphertext. Each encrypt call uses a new salt, so uploading the same file twice does not reuse a CID.
const cid = await meshkit.upload(bytes, {
encrypt: { password },
});
const plaintext = await meshkit.retrieve(cid, { password });The full walkthrough is in Encryption.
Pinning
By default, Kubo may garbage-collect content it no longer references. Pinning marks a CID as permanent — Kubo will keep it until you unpin it. Always pin content you care about:
await meshkit.pin(cid);IPNS
IPFS CIDs are immutable — changing the content produces a new CID. IPNS (InterPlanetary Name System) lets you create a stable, mutable pointer (a named key) that can be updated to point to new CIDs over time.
/ipns/<key-id> → /ipfs/<cid> (can change)Meshkit exposes IPNS through publishName, resolveName, resolveAndRetrieve, generateKey, and listKeys.
Multi-node failover
Meshkit accepts multiple Kubo URLs. At init(), it health-checks every node and builds a priority-ordered list of healthy ones. Every operation is tried on the first available node; if it fails, the next is tried automatically.
const { meshkit } = await init({
nodes: [
'http://127.0.0.1:5001', // primary
'https://backup.example.com:5001', // failover
],
});meshkit.activeNodes returns the currently healthy URLs in priority order.
Local daemon lifecycle
When localNode: true, Meshkit either spawns a fresh Kubo process or attaches to an existing one on the default port. The returned IPFSNodeHandle tells you:
handle.managed—trueif Meshkit spawned it (you should stop it on shutdown)handle.url— the RPC URLhandle.stop()— stop the daemon (only meaningful whenmanaged: true)
Use setupGracefulShutdown to stop it automatically on SIGINT/SIGTERM.